API de Integração¶
Referência de endpoints para integração entre sistema parceiro e TOMODAT3.
Convenções de autenticação¶
Endpoints de parceiro (server-to-server)¶
Use:
- Header
X-Integration-API-Key: <api_key> - Header
X-Tenant: <tenant_id>quando o endpoint operar no banco do tenant
Endpoints do cliente final dentro do TOMODAT¶
Use JWT de usuário logado (na interface do TOMODAT), não API key do parceiro.
O que é tenant na API¶
tenant é o identificador da conta/ambiente do cliente final no TOMODAT.
Em outras plataformas, isso pode equivaler a:
- conta
- organização
- workspace
- cliente
Quando o endpoint opera no banco do cliente final, envie X-Tenant: <tenant_id>.
Tipos integráveis atualmente suportados¶
Use esses slugs em item_type_slug:
| Slug | Nome exibido | Geometria | Descrição |
|---|---|---|---|
cliente |
Cliente | POINT |
Unidade/cliente final no mapa |
poco |
Poço | POINT |
Ponto de infraestrutura hidráulica |
caixa-d-agua |
Caixa d'Água | POINT |
Reservatório/ponto físico relacionado a abastecimento |
Catálogo detalhado de tipos integráveis¶
Esta é a lista oficial para integração no estado atual:
| Nome do tipo | Slug técnico (item_type_slug) |
Geometria esperada (geometry.type) |
Integrável |
|---|---|---|---|
| Cliente | cliente |
Point |
Sim |
| Poço | poco |
Point |
Sim |
| Caixa d'Água | caixa-d-agua |
Point |
Sim |
Regras importantes:
- O
slugdeve ser enviado exatamente como documentado. geometry.typedeve respeitar a geometria esperada do tipo.- Se o item for criado sem geometria, o usuário final poderá posicioná-lo depois no mapa.
Regra de manutenção desta tabela¶
Sempre que a lista de tipos integráveis mudar no produto, esta documentação deve ser atualizada no mesmo ciclo de entrega.
Sobre properties:
propertiesé JSON livre.- Atualmente não existe schema obrigatório por tipo nessa integração.
- Recomendação: manter estrutura estável no sistema parceiro para facilitar suporte.
Endpoints de itens via integração¶
POST /api/integration/items¶
Cria item integrado.
Headers:
X-Integration-API-KeyX-Tenant
Body exemplo:
{
"external_id": "cli-123",
"item_type_slug": "cliente",
"name": "Joao da Silva",
"geometry": {
"type": "Point",
"coordinates": [-49.1234, -26.4567]
},
"properties": {
"status": "ativo"
},
"external_data": {
"telefone": "47999990000",
"plano": "Residencial"
},
"external_actions": [
{
"label": "Ver cliente no ERP",
"url": "https://erp.exemplo.com/clientes/cli-123",
"icon": "eye"
}
]
}
Resposta sucesso: 201.
Erros comuns:
401: API key ausente/inválida.403: tenant não pertence ao parceiro.404: tipo integrável não encontrado.409:external_idjá existe para esse parceiro no tenant.422: validação de payload.
PUT /api/integration/items/{external_id}¶
Atualiza item integrado por external_id.
Body permitido:
namepropertiesexternal_dataexternal_actions
Regra:
- Campo
geometryé proibido nesse endpoint.
Erros comuns:
404: item não encontrado.422: tentou enviargeometryou payload inválido.
DELETE /api/integration/items/{external_id}¶
Soft delete (item fica inativo).
Resposta sucesso: 200.
Resposta exemplo:
{
"message": "Item desativado",
"deleted_at": "2026-03-12T10:00:00+00:00"
}
POST /api/integration/items/{external_id}/restore¶
Restaura item soft-deleted.
Resposta sucesso: 200.
POST /api/integration/items/sync¶
Sincronização em lote por tipo (full sync).
Body exemplo:
{
"item_type_slug": "cliente",
"items": [
{
"external_id": "cli-123",
"name": "Joao da Silva",
"properties": { "status": "ativo" },
"external_data": { "telefone": "47999990000" },
"external_actions": [
{ "label": "Ver cliente", "url": "https://erp.exemplo.com/clientes/cli-123" }
]
},
{
"external_id": "cli-456",
"name": "Maria Souza"
}
]
}
Comportamento:
- Cria itens novos.
- Atualiza itens existentes.
- Restaura itens soft-deleted presentes no payload.
- Soft delete em itens que existem no TOMODAT mas não vieram no payload.
- Não altera geometria de item existente.
Resposta sucesso: 200.
Resposta exemplo:
{
"created": 5,
"updated": 12,
"restored": 1,
"deactivated": 2,
"unchanged": 81,
"total_received": 100,
"total_in_tomodat": 99
}
Endpoints de vínculo de tenant¶
Fluxo A - cliente final gera código, parceiro vincula¶
Passo 1 (cliente final, dentro do TOMODAT):
POST /api/integration/tenant-link-codes(JWT do usuário admin)
Passo 2 (sistema parceiro):
POST /api/integration/tenants/linkcomX-Integration-API-Key
Body exemplo:
{
"code": "A1B2C3D4",
"external_id": "erp_client_42",
"integrated_types": ["cliente", "poco"]
}
Resposta sucesso:
{
"tenant_id": "tenant_abc",
"external_id": "erp_client_42",
"linked": true,
"integrated_types_configured": [
{
"slug": "cliente",
"external_base_url": null
},
{
"slug": "poco",
"external_base_url": null
}
]
}
Erros comuns:
422: código inválido, expirado, já usado, ou tenant vinculado a outro parceiro.401: API key ausente/inválida.
Fluxo B - tenant já é do parceiro, só configurar tipos¶
Endpoint:
POST /api/integration/tenants/{tenant_id}/configure-types
Body exemplo:
{
"integrated_types": [
{
"slug": "cliente",
"external_base_url": "https://erp.exemplo.com/api/clientes"
},
{
"slug": "poco",
"external_base_url": "https://erp.exemplo.com/api/pocos"
}
]
}
Dados externos e ações¶
external_data¶
Objeto JSON livre com dados que o TOMODAT exibe para o usuário final.
Exemplo:
{
"telefone": "47999990000",
"status_financeiro": "em_dia",
"plano": "Residencial"
}
external_actions¶
Lista de ações clicáveis para abrir páginas do sistema parceiro.
Formato recomendado:
[
{ "label": "Ver Detalhes", "url": "https://...", "icon": "eye" },
{ "label": "Nova OS", "url": "https://...", "icon": "plus" }
]
Observações:
iconé opcional.urldeve ser absoluta.- Links são abertos em nova aba no frontend.
Sobre endpoint de detalhes externos (proxy)¶
Na versão atual, o fluxo oficial usa dados cacheados (external_data e external_actions).
Um endpoint proxy para buscar detalhes online no sistema parceiro pode ser adicionado em versão futura, mas não faz parte do contrato obrigatório atual.
Embed token e iframe¶
Endpoint para gerar token:
POST /api/integration/embed-token
Body:
{
"tenant_id": "tenant_abc"
}
Resposta:
{
"embed_token": "<jwt>",
"expires_in": 3600
}
Para renovação automática via postMessage, veja Renovação de Embed Token.
Troubleshooting rápido¶
401 Unauthorized¶
- API key ausente ou inválida.
- Token JWT expirado no fluxo de iframe.
403 Forbidden¶
- Tenant não pertence ao parceiro da API key usada.
422 Unprocessable Entity¶
- Payload inválido.
- Tipo integrável inexistente.
- Código de vínculo expirado/já usado.
429 Too Many Requests¶
- Rate limit em geração de código de vínculo ou endpoints públicos.