Actiz Actiz API v1.0
Swagger UI gRPC Browser
Actiz LIMS · Portal do Desenvolvedor

API oficial do
Actiz LIMS

Acesse dados laboratoriais com segurança e flexibilidade. REST/OData v4 e gRPC, autenticação JWT multi-tenant, mais de 114 endpoints organizados por domínio.

OData v4 gRPC JWT · Multi-tenant $filter · $expand · $select MySQL · SQL Server .NET 9 · EF Core
Swagger UI
114+
Endpoints REST
27
Serviços gRPC
16
Domínios
Multi
Tenant por JWT
OData v4 completo

Filtre, ordene, pagine e expanda com $filter, $orderby, $expand, $select, $top e $skip. Limite de 1 000 registros por chamada.

JWT + Multi-tenant

Cada requisição valida o JWT e isola o banco de dados pelo claim tenant_id. Zero compartilhamento entre tenants.

gRPC + REST

Escolha o protocolo ideal: REST/OData para integrações HTTP padrão e gRPC para comunicação de alto desempenho entre serviços internos.

Expansão automática

GET /api/quote já retorna Customer, Responsáveis, DiscountType, Project, QuoteDetails → Analysis e Packs expandidos — sem parâmetros extras.

Explorador interativo: acesse /swagger para testar todos os endpoints no navegador, ou /docs para os serviços gRPC.
1
Obtenha um token JWT
Envie suas credenciais para o endpoint de login.
HTTP
POST /api/auth/login
Content-Type: application/json

{
  "username": "seu-usuario",
  "password": "sua-senha",
  "tenantId": "seu-tenant-id"
}
Resposta 200
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 86400
}
2
Inclua o token nas requisições
Use o header Authorization: Bearer em todas as chamadas. O tenant_id já está embutido no JWT.
Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
O token expira em 24 horas. Após expirar, repita o login para obter um novo token.
3
Faça sua primeira requisição
Liste orçamentos — Customer, Responsáveis e QuoteDetails já vêm expandidos automaticamente.
HTTP
GET /api/quote
Authorization: Bearer {seu-token}
4
Refine com OData
Combine operadores para buscar exatamente o que precisa.
Exemplos OData
# Urgentes, ordenados, limitados
GET /api/quote?$filter=Urgent eq true&$orderby=DateCreation desc&$top=20

# Paginação — página 2 (50 registros)
GET /api/sample?$top=50&$skip=50&$count=true

# Busca por texto
GET /api/analysis?$filter=contains(Name,'metais')

# Expansão manual adicional
GET /api/order?$expand=Customer,OrderDetails

Endpoint de login

POST/api/auth/loginObter token JWT
Request body
{
  "username": "seu-usuario",
  "password": "sua-senha",
  "tenantId": "identificador-do-tenant"
}
Resposta 200
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 86400
}

Usando o token

Authorization header
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Claims do JWT

ClaimDescriçãoObrigatório
tenant_idIdentifica o tenant e isola o banco de dados.Sim
subIdentificador do usuário autenticado.Sim
expData de expiração (Unix timestamp). Token válido por 24 h.Sim
Swagger: clique em "Authorize" e insira o token no formato Bearer {token}.
Todos os domínios suportam GET, POST, PUT, PATCH e DELETE. Explore e teste no Swagger UI.

📋 Pedidos & Orçamentos

📄Quote (Orçamento)CRUD completo
QuoteQuoteDetailQuoteDetailAnalysisQuoteDetailAnalysisPackQuoteRecurrenceQuoteDetailRecurrencePOST /with-details
📦Order (Pedido)CRUD completo
OrderOrderDetailInvoicePricelist

🔬 Análises & Laboratório

🔬Analysis6 entidades
AnalysisAnalysisPackAnalysisPackAnalysisAnalysisPriceAnalysisRequestAnalysisType
🧪Laboratory5 entidades
AssayAssayPackBottleLotMethod

🧬 Amostras & Qualidade

🧬Samples3 entidades
SampleSamplePointSampleType
📊Quality5 entidades
NonconformityQualityControlTypeAuditAuditActionPlanNonconformityActionPlan

👥 Clientes & Inventário

👥Customer2 entidades
CustomerCustomerContact
📦Inventory7 entidades
MaterialsStockProcurementProviderProviderTypeSubstanceStockNotificationHistory

🔧 Instrumentos & Geográfico

🔧Instruments7 entidades
InstrumentInstrumentTypeInstrumentDataInstrumentCommTemplateInterventionPlanningInterventionExecutionMaintenanceNotificationHistory
🌍Geographic6 entidades
AreaCityCountryFederationUnitLocationLocationType

📋 Worksheets & Auditoria

📋Worksheet5 entidades
WorksheetAutomationWorksheetTemplateWorksheetAssayWorksheetResourceWorksheetResult
🔍Audit Entities2 entidades
AuditEntityAuditEntityField

⚙️ Administrativo & Sistema

⚙️Administration50+ entidades
ActizUserProjectEntityStatusEnumerationChecklistTrainingParameterResultSpecificationRiskProcess+40 mais
🗓️Scheduling, Docs & Integration5 entidades
AgendaCalendarCalendarEventDocumentWebhook

Rotas padrão por entidade

GET/api/{entidade}Listar com OData
GET/api/{entidade}('{id}')Buscar por ID
POST/api/{entidade}Criar registro
PUT/api/{entidade}('{id}')Substituir completamente
PATCH/api/{entidade}('{id}')Atualizar parcialmente
DELETE/api/{entidade}('{id}')Remover registro
POST/api/quote/with-detailsCriação atômica Quote + Detalhes
Prefixos /api/ e /odata/ suportam OData v4. Limite: $top=1000 por requisição.

Operadores de consulta

OperadorDescriçãoExemplo
$filterFiltra registros por condição$filter=Urgent eq true
$selectSeleciona campos específicos$select=Oid,Name,Email
$expandExpande propriedades de navegação$expand=Customer,OrderDetails
$orderbyOrdena os resultados$orderby=DateCreation desc
$topLimita o número de registros (máx. 1 000)$top=50
$skipPula N registros (paginação)$skip=100
$countInclui o total de registros na resposta$count=true

Operadores de $filter

OperadorSignificadoExemplo
eq / neIgual / diferente$filter=Status eq 'Aprovado'
gt / ltMaior / menor que$filter=Discount gt 0.1
ge / leMaior ou igual / menor ou igual$filter=Quantity ge 10
and / orOperadores lógicos$filter=Urgent eq true and Discount gt 0
containsContém substring$filter=contains(Name,'metal')
startswithComeça com$filter=startswith(Name,'Lab')

Exemplos práticos

Paginação
# Página 1
GET /api/sample?$top=50&$skip=0&$count=true&$orderby=DateCreation desc

# Página 2
GET /api/sample?$top=50&$skip=50&$orderby=DateCreation desc
Expansão aninhada
# Quote já expande automaticamente — mas você pode adicionar mais
GET /api/quote?$expand=Entitystatus

# Order com Customer selecionando campos + OrderDetails
GET /api/order?$expand=Customer($select=Name,Email),OrderDetails
Filtros combinados
# Orçamentos urgentes com desconto
GET /api/quote?$filter=Urgent eq true and Discount gt 0&$orderby=DateCreation desc&$top=20

# Amostras de um cliente com expansão seletiva
GET /api/sample?$filter=CustomerId eq 'abc-123'&$expand=SampleType&$select=Oid,Code,DateCreation
Use o gRPC Browser em /docs para explorar e testar interativamente. Server Reflection está ativo.

Autenticação gRPC

Inclua o JWT no metadata de cada chamada:

Metadata
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Serviços disponíveis

ActizUseractizuser.proto
Analysisanalysis.proto
Assayassay.proto
Authauth.proto
Checklistchecklist.proto
ChecklistDetailschecklistdetails.proto
ChecklistTemplatechecklisttemplate.proto
ChecklistTemplateDetailschecklisttemplatedetails.proto
EntityNoteentitynote.proto
EntityStatusentitystatus.proto
Enumerationenumeration.proto
EnumerationDetailsenumerationdetails.proto
FileAttachmentfileattachment.proto
Instrumentinstrument.proto
Locationlocation.proto
Lotlot.proto
Nonconformitynonconformity.proto
Propertyproperty.proto
Providerprovider.proto
Resultresult.proto
Samplesample.proto
Samplingsampling.proto
StatusTransitionstatustransition.proto
Stockstock.proto
StockBatchstockbatch.proto
StockInventorystockinventory.proto
Worksheetworksheet.proto

1. Autenticação

curl -X POST https://seu-servidor/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"seu-usuario","password":"sua-senha","tenantId":"seu-tenant"}'
const resp = await fetch('/api/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ username: 'seu-usuario', password: 'sua-senha', tenantId: 'seu-tenant' })
});
const { token } = await resp.json();
localStorage.setItem('actiz_token', token);
import requests

resp = requests.post('https://seu-servidor/api/auth/login', json={
    'username': 'seu-usuario',
    'password': 'sua-senha',
    'tenantId': 'seu-tenant'
})
token = resp.json()['token']
using var client = new HttpClient();
var resp = await client.PostAsJsonAsync("/api/auth/login",
    new { username = "seu-usuario", password = "sua-senha", tenantId = "seu-tenant" });
var json = await resp.Content.ReadFromJsonAsync<JsonElement>();
string token = json.GetProperty("token").GetString()!;

2. Listar Quotes com filtros

curl "https://seu-servidor/api/quote?\$filter=Urgent eq true&\$top=10&\$orderby=DateCreation desc" \
  -H "Authorization: Bearer {seu-token}"
const token = localStorage.getItem('actiz_token');
const params = new URLSearchParams({
  '$filter': 'Urgent eq true',
  '$orderby': 'DateCreation desc',
  '$top': '10'
});
const resp = await fetch(`/api/quote?${params}`, {
  headers: { 'Authorization': `Bearer ${token}` }
});
const data = await resp.json(); // data.value = array de quotes
headers = {'Authorization': f'Bearer {token}'}
params = {'$filter': 'Urgent eq true', '$orderby': 'DateCreation desc', '$top': 10}
resp = requests.get('https://seu-servidor/api/quote', headers=headers, params=params)
quotes = resp.json()['value']
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", token);

var url = "/api/quote?$filter=Urgent eq true&$orderby=DateCreation desc&$top=10";
var result = await client.GetFromJsonAsync<ODataResponse<Quote>>(url);

3. Criar Quote com detalhes (endpoint atômico)

curl -X POST https://seu-servidor/api/quote/with-details \
  -H "Authorization: Bearer {seu-token}" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "cliente-id",
    "entitystatusId": "status-id",
    "responsible": "usuario-id",
    "urgent": false,
    "discount": 0.0,
    "quoteDetails": [{
      "item": "Análise de Água",
      "sampletype": "tipo-id",
      "quantity": 1,
      "quoteDetailAnalysis": [{
        "analysis": "analise-id",
        "quantity": 1,
        "unitaryvalue": 150.00
      }],
      "quoteDetailAnalysisPack": []
    }]
  }'
const resp = await fetch('/api/quote/with-details', {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    customerId: 'cliente-id',
    entitystatusId: 'status-id',
    responsible: 'usuario-id',
    urgent: false,
    discount: 0.0,
    quoteDetails: [{
      item: 'Análise de Água',
      sampletype: 'tipo-id',
      quantity: 1,
      quoteDetailAnalysis: [{ analysis: 'analise-id', quantity: 1, unitaryvalue: 150.00 }],
      quoteDetailAnalysisPack: []
    }]
  })
});
const result = await resp.json();

4. PATCH — atualização parcial

cURL
curl -X PATCH "https://seu-servidor/api/quote('quote-oid')" \
  -H "Authorization: Bearer {seu-token}" \
  -H "Content-Type: application/json" \
  -d '{"Urgent": true, "Discount": 0.15}'
Mar 2026
Feat
gRPC Genérico para Todas as Entidades
Serviço gRPC genérico (EntityService) com operações ListEntities, GetEntity, CreateEntity, UpdateEntity, PatchEntity e DeleteEntity para qualquer entidade da API — paridade completa REST ↔ gRPC
Mar 2026
Feat
19 Novos Controllers e Services
Controllers e services para os módulos de Worksheet (Automation, Template, Assay, Resource, Result), Manutenção de Instrumentos (Planning, Execution, Notification), Qualidade (Audit, ActionPlan, NonconformityActionPlan), Orders (QuoteRecurrence), Analysis, Scheduling, Integration (Webhook) e Inventory
Mar 2026
Feat
State Machine REST + gRPC — máquinas de estado por tipo de entidade
GET /api/StateMachine?entityType={tipo} retorna a máquina de estados completa com estados, transições, regras e constraints. gRPC StateMachineService com GetStateMachine e GetConfiguredEntityTypes.
Mar 2026
Feat
Processamento de resultados — motor de regras de negócio
POST /api/Result/process e POST /api/Assay/{id}/results processam resultados com auto-população, parsing por tipo, limiar LD/PQL, avaliação de especificações e transições de status. GET /api/Result/{id}/detail retorna histórico e trilha de status. gRPC ProcessResults e GetResultDetail no ResultService.
Mar 2026
Fix
Quote + Reflection — NullReference e SafeJsonTypeInfoResolver
QuoteService corrigido para QuoteDetails/QuoteValues nulos e criação inline de Service. SafeJsonTypeInfoResolver contorna bug do .NET 9 com NullabilityInfoContext em tipos cross-module. AuditTrailSaveChangesInterceptor resolve ITenantContext via CreateScope.
Mar 2026
Feat
AI Chat autenticado + upload e download de arquivos
POST /api/ai/chat com autenticação JWT, session management e timeout configurável. FiledataService para criação e remoção de anexos. Filedata armazena conteúdo como binário. Novo DTOs para listagem de anexos.
Mar 2026
Feat
MCP — integração com agentes de IA via Model Context Protocol
Endpoint /mcp expõe 7 ferramentas genéricas (list, get, create, update, patch, delete + discovery) para agentes IA consumirem a API. Autenticação via Bearer JWT. ActizMcpTools implementa todas as operações CRUD com suporte a OData.
Mar 2026
Feat
CodeGenerationService — geração automática de código e numeração sequencial
Novo serviço aplica código sequencial, campos de auditoria, regras Syntax e EntityStatus inicial na criação de entidades. Suporte a reset diário/mensal/anual e critérios de seleção de Syntax.
Mar 2026
Fix
Auditoria multi-tenant aplicada em todos os contextos de escrita
O interceptor de auditoria foi acoplado ao TenantDbContextFactory, o AuditTrailService passou a usar contexto tenant-aware e o DELETE lógico (GCRecord) agora registra evento ObjectDeleted na trilha de auditoria.
Mar 2026
Feat
Auto-expand em GET /api/quote
Customer, DiscountType, Contact, Responsible, TechnicalResponsible, CommercialResponsible, PreparationResponsible, Project e QuoteDetails (com Analysis e Packs) são expandidos automaticamente sem parâmetros extras.
Mar 2026
Fix
MySQL row-size-too-large — AsSplitQuery
Erro "Row size too large (>8126)" resolvido com AsSplitQuery. EF Core executa queries separadas para navegações de coleção, evitando o limite do InnoDB em tabelas temporárias.
Mar 2026
Fix
MySqlConnector — InvalidCastException em colunas DOUBLE
DbCommandInterceptor com SafeDoubleReader contorna o bug do MySqlConnector 2.4.x que bufferiza valores inteiros de colunas DOUBLE como Int32, causando falha em GetDouble().
Mar 2026
Feat
POST /api/quote/with-details — criação atômica
Novo endpoint que cria Quote + QuoteDetails + QuoteDetailAnalyses + QuoteDetailAnalysisPacks em uma única transação.
Mar 2026
Feat
CRUD completo para QuoteDetail, QuoteDetailAnalysis e QuoteDetailAnalysisPack
Controllers e services com GET, POST, PUT, PATCH e DELETE para as entidades filhas de Quote.
Mar 2026
Fix
OData model builder — startup exceptions eliminadas
ArgumentException e AmbiguousMatchException no startup resolvidas. Rotas OData limpas e sem warnings.
Mar 2026
Security
Supressão de detalhes internos nas respostas de erro
Stack traces e detalhes de banco de dados não são mais expostos nas respostas de autenticação e erros globais.