v1 · REST · Disponível em todos os planos

Gere contratos
programaticamente

API REST simples para integrar geração de contratos com IA no seu sistema. Envie uma descrição, receba um contrato profissional pronto.

7

Endpoints

30

Req / min

REST

Protocolo

HMAC

Webhooks

Autenticação

Todas as requisições precisam de uma API key no header Authorization. As chaves seguem o padrão ctk_live_* e são geradas na aba API & Integrações do painel.

Header de autenticação
# Inclua em toda requisição Authorization: Bearer ctk_live_xxxxxxxxxxxxxxxx Content-Type: application/json

Disponível em todos os planos, já no teste gratuito de 3 dias. A chave é criada em Painel → API & Integrações → Nova chave. Guarde-a — não é exibida novamente após a criação.

Base URL

# Base URL — disponível no painel em API & Integrações https://cotract.app/api/v1

A URL exata da sua instância aparece no painel após criar a primeira API key.

Quick start

Da API key ao contrato gerado em 3 passos.

1

Crie a API key no painel

Painel → API & Integrações → Nova chave

2

Faça POST para criar o contrato

A geração é assíncrona — retorna 202 com job_id

cURL
curl https://cotract.app/api/v1/contracts \ -X POST \ -H "Authorization: Bearer ctk_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "title": "Contrato de Prestação de Serviços", "description": "Desenvolvimento de site institucional para empresa de advocacia. Prazo 30 dias, valor R$5.000, pagamento 50% entrada e 50% entrega.", "contract_type": "servicos" }'
Resposta 202
{ "job_id": "job_7f3a2b1c", "contract_id": "ctr_9e4d5f6a", "status": "processing", "message": "Contract generation started" }
3

Faça polling do job-status

Progresso de 0 a 100. Quando status: "completed", o contrato está pronto

Node.js — polling com intervalo
// Poll até o contrato ficar pronto async function waitForContract(contractId) { while (true) { const res = await fetch( `https://cotract.app/api/v1/contracts/${contractId}/job-status`, { headers: { Authorization: `Bearer ${API_KEY}` } } ); const data = await res.json(); if (data.status === 'completed') return data; if (data.status === 'failed') throw new Error(data.error); // Aguarda 2s antes do próximo poll await new Promise(r => setTimeout(r, 2000)); } }

Endpoints

GET /v1/contracts

Retorna lista paginada dos contratos da organização. Ordenados por data de criação decrescente.

Query params

pageintegerPágina (padrão: 1)
limitintegerItens por página, máx 100 (padrão: 20)
statusstringdraft · active · signed · archived
Resposta 200
{ "data": [{ "id": "ctr_9e4d5f6a", "title": "Contrato de Prestação de Serviços", "status": "active", "created_at": "2026-05-17T14:30:00Z" }], "pagination": { "page": 1, "total": 42, "has_more": true } }
POST /v1/contracts

Cria um contrato e inicia a geração assíncrona. Retorna 202 imediatamente com job_id e contract_id. Use /job-status para fazer polling. Consome 1 crédito do plano.

Body (JSON)

title *stringTítulo do contrato
description *stringDescrição do contexto para geração (mín. 20 chars)
contract_typestringservicos · trabalho · imobiliario · comercial · juridico
expires_atISO 8601Data de expiração (opcional)
Resposta 202 — geração iniciada
{ "job_id": "job_7f3a2b1c", "contract_id": "ctr_9e4d5f6a", "status": "processing", "credits_remaining": 23 }
GET /v1/contracts/:id/job-status

Retorna o progresso da geração. Faça polling a cada 2–3s. Quando status: "completed", o contrato está disponível em GET /v1/contracts/:id.

Resposta 200
{ "contract_id": "ctr_9e4d5f6a", "status": "completed", // processing | completed | failed "progress": 100, // 0 a 100 "completed_at": "2026-05-17T14:30:12Z" }
GET /v1/contracts/:id

Retorna o contrato com conteúdo completo (campo content em Markdown). Só disponível após status: "completed".

Resposta 200
{ "id": "ctr_9e4d5f6a", "title": "Contrato de Prestação de Serviços", "status": "active", "content": "# Contrato de Prestação de Serviços\n\n**Partes:**...", "version": 1, "expires_at": null, "created_at": "2026-05-17T14:30:00Z" }
PATCH /v1/contracts/:id

Atualiza metadados do contrato. Não altera o conteúdo gerado — para isso use o editor no painel.

Body (JSON — todos opcionais)

titlestringNovo título
statusstringdraft · active · archived
expires_atISO 8601 | nullData de expiração
GET /v1/contracts/:id/versions

Retorna todas as versões do contrato em ordem cronológica. Cada versão tem o conteúdo completo.

Resposta 200
{ "versions": [{ "version": 1, "content": "# Contrato...", "created_at": "2026-05-17T14:30:12Z" }] }
GET POST
/v1/signature-requests

GET lista as solicitações de assinatura. POST cria uma nova solicitação e retorna o link de assinatura para enviar ao signatário.

POST body

contract_id *stringID do contrato
signer_name *stringNome do signatário
signer_email *stringE-mail do signatário
POST — Resposta 201
{ "id": "sig_3c2d1e0f", "sign_url": "https://cotract.app/sign/abc123xyz", "status": "pending", "expires_at": "2026-06-17T00:00:00Z" }

Webhooks

Configure endpoints para receber eventos em tempo real. Cada entrega inclui assinatura HMAC-SHA256 no header X-Cotract-Signature. Retry automático com backoff exponencial.

contract.created

Contrato criado via API ou painel

contract.updated

Título, status ou expiração alterados

signature.requested

Solicitação de assinatura criada

signature.completed

Contrato assinado pelo signatário

Verificar assinatura HMAC

Node.js
const crypto = require('crypto'); function verifyWebhook(payload, secret, signature) { const expected = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature) ); } // No Express: app.post('/webhook', express.raw({type:'application/json'}), (req, res) => { const sig = req.headers['x-cotract-signature']; if (!verifyWebhook(req.body, WEBHOOK_SECRET, sig)) return res.status(401).send('Unauthorized'); // processar evento... });

Limites & Créditos

30

req / minuto por API key

Rate limit global — todas as chamadas

1

crédito por /contracts ou /reviews

Geração e validação consomem 1 crédito cada

leituras sem custo

GET, PATCH, job-status, etc.

Créditos de API são uma bolsa separada da assinatura: não expiram e são consumidos só pela API. Quando acabam, a API retorna 402 Payment Required — sem cobrança automática extra. Quando o rate limit é estourado, retorna 429 Too Many Requests com o header Retry-After.

Exclusivo API

Créditos de API

Para quem integra via /v1/contracts ou /v1/reviews. Bolsa separada da assinatura: não expira, consumida só pela API (1 crédito por contrato gerado ou validação). Pagamento único, cartão ou PIX.

App vs. API: geração pelo painel exige assinatura ativa; geração pela API exige créditos de API. São saldos independentes — sem surpresa de fatura. Quando acabam, a API responde 402 Payment Required e é só comprar mais.

20 créditos API

R$29,80

20 chamadas /contracts ou /reviews

R$1,49/crédito

100 créditos API

R$119,90

100 chamadas /contracts ou /reviews

R$1,20/crédito

MAIS POPULAR
500 créditos API

R$549,90

500 chamadas /contracts ou /reviews

R$1,10/crédito

Créditos disponíveis na aba API & Integrações do painel após ativar o teste ou qualquer plano.

Erros

Todos os erros seguem o formato {"error": "mensagem", "code": "ERROR_CODE"}.

HTTP Código Causa
401 UNAUTHORIZED API key inválida ou ausente
402 INSUFFICIENT_CREDITS Sem créditos disponíveis para criar contrato
404 NOT_FOUND Contrato não encontrado ou sem acesso
422 VALIDATION_ERROR Campos obrigatórios ausentes ou inválidos
429 RATE_LIMITED Limite de 30 req/min atingido
500 INTERNAL_ERROR Erro interno — tente novamente
Disponível em todos os planos, inclusive gratuito

Pronto para integrar?

Crie uma conta, gere sua API key e faça o primeiro contrato em menos de 5 minutos.