Convenções, Autenticação e Erros
Regras comuns a todos os endpoints descritos nas próximas páginas — leia antes de integrar, para não repetir o mesmo "por que isso deu 500?" em cada recurso.
Payloads
Todo corpo de requisição/resposta é JSON (Content-Type: application/json), serializado a partir de records
Java via Jackson. Não há um envelope genérico ({ "data": ..., "meta": ... }) — a resposta de sucesso é o
próprio recurso, ou uma lista dele.
Variáveis de processo
Sempre que um endpoint recebe ou devolve variáveis (start, setVariables, completeExternalTask,
correlateEvent, o campo variables de ProcessInstance), o formato de fio é um mapa nome → ProcessVariable:
{
"variables": {
"cpfCliente": { "name": "cpfCliente", "value": "12345678900" },
"aprovado": { "name": "aprovado", "value": true, "isTransient": false }
}
}
isTransient é opcional (default false) — ver Variáveis de Processo
para o que ele significa em termos de persistência. Note a redundância aparente da chave do mapa com o campo
name dentro do valor — ambos precisam bater; é assim que o modelo (ProcessVariable) é definido hoje, não uma
opção da camada REST.
Paginação
Endpoints paginados (POST /process-instances/search, o deprecated GET /process-instances/summary) devolvem
um PageResult:
{
"content": [ /* ... */ ],
"totalElements": 45,
"totalPages": 3,
"page": 0,
"size": 20
}
page começa em 0. size tem teto de 100 — um valor maior é silenciosamente reduzido a 100, não rejeitado.
CORS
Desabilitado por padrão. Preencha kikwiflow.rest.cors.allowed-origins para liberar origins específicas — o
filtro então libera GET/POST/PUT/DELETE/OPTIONS/PATCH, todos os headers, e Access-Control-Allow-Credentials:
kikwiflow:
rest:
cors:
allowed-origins: "https://monitor.suaempresa.com"
Autenticação e identidade
O Kikwiflow não embute um esquema de autenticação. Toda operação de comando recebe um IdentityContext
(actorId, tenantId, roles), mas ele é resolvido a partir da requisição HTTP por um ponto de extensão que
sua aplicação implementa:
public interface HttpIdentityResolver {
IdentityContext resolve(HttpServletRequest request);
}
Registre um bean HttpIdentityResolver (ex.: decodificando um JWT já validado por outro filtro, lendo uma
sessão) e ele substitui automaticamente o padrão — KikwiflowSecurityAutoConfiguration só registra o seu com
@ConditionalOnMissingBean.
:::danger Sem um HttpIdentityResolver próprio, a API é efetivamente anônima
O resolver padrão devolve sempre actorId: "anonymous", roles: [], e tenantId lido cru do header
X-Tenant-Id (sem validar que quem chamou tem direito àquele tenant):
request -> new IdentityContext("anonymous", request.getHeader("X-Tenant-Id"), Set.of());
Isso é adequado para desenvolvimento local, não para produção com múltiplos tenants ou dados sensíveis. Ver Segurança e Multi-tenancy para o quadro completo (inclusive o fato de que o motor não aplica isolamento por tenant automaticamente na maioria das operações — é responsabilidade da camada de API/controller, e portanto de quem consome ou embute esta API). :::
Nenhum endpoint destes documentos exige um header de autenticação específico — o que existe depende
inteiramente do HttpIdentityResolver que a aplicação hospedeira registrar.
Erros
Todo erro conhecido é serializado por KikwiflowExceptionHandler no mesmo formato:
{ "code": "NOT_FOUND", "message": "Process Instance Not Found" }
| Exceção | HTTP | code | Quando acontece |
|---|---|---|---|
NotFoundException | 404 | NOT_FOUND | Recurso (instância, definição, tarefa, incidente) inexistente pelo id/key informado. |
TaskNotFoundException | 404 | NOT_FOUND | POST /events/correlate/{correlationKey} sem nenhum EVENT_CATCHER esperando aquela chave — chave nunca existiu, já foi consumida, corrida ANY já decidida, cancelada por boundary, ou tenant errado. |
NotImplementedException | 501 | NOT_IMPLEMENTED | Parâmetro de filtro aceito pela assinatura do endpoint mas ainda não implementado no backend de consulta (ver Tarefas Externas). |
IllegalStateException | 409 | CONFLICT | Operação inválida para o estado atual (ex.: retentar um incidente que já não está OPEN). |
IllegalArgumentException | 400 | BAD_REQUEST | Entrada rejeitada por validação de domínio — ex.: orderBy fora da whitelist em /process-instances/search. |
Lacunas conhecidas do tratamento de erros
Vale conhecer estas antes de assumir que "erro = uma dessas cinco entradas":
- Deploy desabilitado não vira 403.
POST /process-definitionscomkikwiflow.security.deploy-enabled: false(o padrão) lançaSecurityException— sem handler dedicado, isso cai no tratamento padrão do Spring Boot e retorna 500 com o corpo de erro genérico do container, não o envelope{code, message}acima. O mesmo vale para qualquerDeploymentSecurityManagercustomizado que lanceSecurityException. - Definição inválida no deploy também vira 500.
InvalidProcessDefinitionException(gateway semproviderType, bean deAnswerProviderinexistente, etc. — ver Regras de Processo Válido) não tem handler dedicado; um deploy malformado retorna 500 em vez de um 400 com detalhe do que está errado na definição. - Não há validação de payload (
@Valid/Bean Validation). Um corpo faltando um campo obrigatório (ex.:processDefinitionKeyausente emPOST /process-instances) não é rejeitado antecipadamente com 400 — o comportamento depende do que a camada do motor faz ao recebernullnaquele ponto, e pode ser um 500 com stack trace pouco informativo em vez de um erro de validação claro.
Se sua aplicação expõe esta API a clientes externos (não só a um frontend interno confiável), vale colocar um
@ExceptionHandler(SecurityException.class)/@ExceptionHandler(InvalidProcessDefinitionException.class)
próprio no seu contexto Spring — KikwiflowExceptionHandler é registrado com @ConditionalOnMissingBean, mas
isso só substitui a classe inteira, não adiciona handlers a mais; para complementar sem reescrever os cinco
handlers existentes, adicione um @RestControllerAdvice próprio (ordem de resolução por especificidade de
exceção, não por handler mais recente).