API do Contravo

Crie contratos a partir do seu CRM, leve os dados para o ERP ou faturamento e mantenha os clientes sincronizados, sem digitar nada duas vezes.

A documentação é aberta. O acesso à API (chave de integração) faz parte dos planos pagos.

Começando

A API usa JSON e HTTPS. Todos os endereços começam com:

https://api.contravo.com.br/v1

Tudo que se faz nas telas também se faz pela API, e com as mesmas regras: o que a pessoa não pode fazer na tela, a chave também não pode. Cada empresa só enxerga os próprios dados.

Autenticação

O administrador da sua empresa gera uma chave de integração e escolhe o que ela pode fazer (por exemplo: só ler contratos, ou criar clientes e contratos). Envie a chave em todas as chamadas:

Cabeçalho
Authorization: Bearer pk_live_1a2b3c4d_SEU_SEGREDO
  • A chave aparece uma única vez, quando é criada. Guardamos apenas uma assinatura dela, nunca a chave em si.
  • Uma chave pode ser revogada a qualquer momento, sem afetar as outras.
  • Tudo o que a chave faz fica no histórico com o nome dela (ex.: “API: Integração ERP”).
  • Nunca coloque a chave em código que roda no navegador ou no celular do cliente.

Formato dos dados

  • Datas: AAAA-MM-DD, por exemplo 2026-12-01.
  • Valores em dinheiro: texto com ponto decimal, por exemplo "12500.00" (evita erro de arredondamento).
  • CPF e CNPJ: com ou sem pontuação; os dígitos verificadores são conferidos.
  • Chaves dos dados: cada informação do contrato tem uma chave fixa da sua empresa, como valor_contrato ou data_inicio. A lista completa está em GET /fields.
  • Seu próprio id: clientes e contratos aceitam um externalId, o código deles no seu sistema, para você nunca precisar guardar os ids do Contravo.

Paginação

As listas vêm em páginas. Use page (começa em 1) e pageSize (20, 50 ou 100; padrão 20). A resposta traz o total para você saber quantas páginas existem:

{ "data": [ ... ], "page": 1, "pageSize": 20, "total": 137 }

Clientes

PUT/clients/external/{externalId}

Cria ou atualiza o cliente pelo código do seu sistema. Responde 201 quando cria e 200 quando atualiza. É a forma mais simples de manter os cadastros sincronizados.

PUT /clients/external/CLI-0042
{
  "type": "PJ",
  "name": "Construtora Vale Verde Ltda",
  "document": "32.188.842/0001-05",
  "email": "contratos@valeverde.com.br",
  "contacts": [
    { "name": "Eduardo Rocha", "email": "eduardo@valeverde.com.br",
      "cpf": "602.572.505-57", "defaultRoles": ["SIGNER"] }
  ]
}
GET/clients?search=vale&page=1&pageSize=20

Lista e busca por nome, e-mail ou CPF/CNPJ.

GET/clients/external/{externalId}

Busca pelo código do seu sistema.

Templates e campos

GET/templates

Modelos de contrato da empresa, com a versão publicada de cada um.

GET/templates/{id}/variables

Os dados que um modelo pede: chave, nome, tipo, opções e colunas das listas. Use para montar a chamada de criação do contrato.

GET/fields

O dicionário de campos da empresa: cada chave e o que ela significa.

Contratos

POST/contracts

Cria um contrato a partir de um template publicado, já com os dados que você tiver. Os dados do cliente e da sua empresa são preenchidos automaticamente.

POST /contracts
{
  "templateId": "cm3x8k2p00001",
  "clientId": "cm3x8j9a00007",
  "externalId": "PED-2026-1187",
  "values": {
    "data_inicio": "2026-12-01",
    "prazo_meses": 12,
    "indice_reajuste": "IPCA",
    "equipamentos_locados": [
      { "identificador": "AND-8513", "descricao": "Andaime tubular",
        "quantidade": 109, "valor_unitario_mensal": "35.00" }
    ]
  }
}
POST/contracts/{id}/register-signed

Assinado fora do Contravo (papel, gov.br, outra plataforma): envie a prova em multipart/form-data com file (PDF, JPG ou PNG, até 20 MB), signedAt (AAAA-MM-DD) e method (PAPER, GOV_BR, CERTIFICATE, PLATFORM, OTHER). O contrato precisa estar na coluna de Assinatura e passa a Vigente.

POST/contracts/{id}/addenda

Abre um aditivo num contrato vigente. Envie { "reason": "EXTENSION" }: EXTENSION (prorrogação), ITEMS (itens), VALUE (valor), TERMINATION (distrato) ou OTHER. O aditivo é um contrato próprio (mesmas rotas de dados, envolvidos e assinatura); quando assinado, a mudança é aplicada ao contrato original e aparece no histórico dele.

POST/contracts/{id}/cancel

Cancela um contrato ou aditivo ainda não assinado. Envie o motivo em comment. Contrato assinado não é cancelado: use um aditivo de distrato.

GET/contracts/{id}/attachments/{attachmentId}/file

Baixa um documento do contrato (ex.: o assinado). O cabeçalho X-File-Sha256 traz a impressão digital e X-File-Intact diz se o arquivo continua igual ao enviado.

GET/contracts?externalId=PED-2026-1187

Lista e filtra contratos por situação, cliente, texto ou o seu código.

GET/contracts/{id}

O contrato completo: dados, envolvidos, etapa atual e o que falta para avançar.

Ler e alterar dados

GET/contracts/{id}/variables

Todos os dados do contrato pelas chaves da empresa, com resumo de valor e vigência. É a chamada principal para levar o contrato ao ERP ou faturamento.

Resposta (resumida)
{
  "number": 1042,
  "externalId": "PED-2026-1187",
  "status": "IN_WORKFLOW",
  "summary": { "value": "3815.00", "startDate": "2026-12-01", "endDate": "2027-11-30" },
  "variables": {
    "indice_reajuste": { "label": "Índice de reajuste", "type": "SELECT", "value": "IPCA" },
    "equipamentos_locados": {
      "type": "LIST",
      "value": [ { "identificador": "AND-8513", "quantidade": 109, "valor_unitario_mensal": "35.00" } ],
      "totals": { "total": "3815.00", "groups": [] }
    }
  }
}
PUT/contracts/{id}/variables

Altera só os dados enviados (null limpa). Cada valor é conferido pelo tipo; o fim da vigência e os totais são recalculados. Contrato assinado não muda.

GET/contracts/{id}/variables/history

Toda mudança de valor: antes, depois, quem fez e quando.

Buscar itens

GET/contracts/items?q=AND-8513

Em qual contrato está um item? Procura o texto em todas as listas de todos os contratos (por exemplo, o identificador de um equipamento).

Erros

Os erros vêm com uma mensagem em português, pronta para mostrar a quem usa o seu sistema. Quando o problema é em dados específicos, cada chave vem com o seu motivo:

400
{ "statusCode": 400,
  "message": "Valores inválidos: data_inicio (data inválida)",
  "errors": { "data_inicio": "data inválida" } }
  • 401 chave ausente, errada ou revogada · 403 a chave não tem permissão para isso
  • 404 não encontrado (ou de outra empresa) · 409 já existe (ex.: CPF/CNPJ repetido)
  • 429 limite de chamadas atingido (veja Limites de uso)

Limites de uso

Para manter a API rápida para todos, cada empresa tem dois limites, conforme o plano. Só as chamadas de integração contam; o uso pelas telas do sistema não conta.

  • Por minuto (rate limit): protege contra rajadas e laços infinitos. Picos curtos de até o dobro são aceitos, desde que a média do minuto fique dentro do limite.
  • Por mês (cota): o total de chamadas no mês do calendário. Recomeça todo dia 1º.
PlanoPor minutoPor mês
Grátis—Sem acesso à API
Profissional6020.000
Empresa300200.000

Toda resposta informa quanto ainda resta no minuto atual:

Cabeçalhos da resposta
X-RateLimit-Limit: 60        ← chamadas permitidas por minuto
X-RateLimit-Remaining: 57    ← quantas ainda restam neste minuto
X-RateLimit-Reset: 1764590460 ← quando o contador recomeça (segundos desde 1970)

Ao passar do limite, a resposta é 429 com o cabeçalho Retry-After, que diz em quantos segundos tentar de novo:

429
Retry-After: 12

{ "statusCode": 429, "message": "Limite de chamadas por minuto atingido. Tente de novo em 12 segundos." }

Precisa de mais? Os limites de uma empresa podem ser ampliados sem trocar de plano. Fale com a gente.

Boas práticas

  • Use o seu código (externalId). PUT /clients/external/… cria ou atualiza numa chamada só, em vez de buscar e depois criar.
  • Envie só o que mudou. PUT /contracts/…/variables aceita apenas os campos alterados.
  • Ao receber 429, espere o Retry-After. Para erros 5xx, tente de novo aos poucos (1s, 2s, 4s…), no máximo algumas vezes.
  • Guarde o que muda pouco. Templates e o dicionário de campos raramente mudam: consulte uma vez por dia, não a cada contrato.
  • Uma chave por integração. Assim o histórico mostra de onde veio cada mudança, e dá para revogar uma sem parar as outras.

Versões

O endereço tem a versão (/v1). Novidades que não quebram integrações (campos e endereços novos) entram na mesma versão. Mudanças que quebrariam uma integração só acontecem numa versão nova (/v2), com aviso antecipado; a anterior continua funcionando por um período de transição.

Webhooks em breve

Seu sistema será avisado quando algo acontecer: contrato aprovado, assinado, vencendo, reajustado. Sem precisar consultar a API de tempos em tempos.

Referência completa

Todos os endereços, campos e respostas, gerados direto do código (sempre atualizados):

Abrir a referência técnica →