Skip to content

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 slug deve ser enviado exatamente como documentado.
  • geometry.type deve 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-Key
  • X-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_id já 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:

  • name
  • properties
  • external_data
  • external_actions

Regra:

  • Campo geometry é proibido nesse endpoint.

Erros comuns:

  • 404: item não encontrado.
  • 422: tentou enviar geometry ou 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:

  1. Cria itens novos.
  2. Atualiza itens existentes.
  3. Restaura itens soft-deleted presentes no payload.
  4. Soft delete em itens que existem no TOMODAT mas não vieram no payload.
  5. 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/link com X-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.
  • url deve 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.