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.

13

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 pagos (Basic, Pro e Business). A chave é criada em Painel → API & Integrações → Nova chave. Guarde-a — não é exibida novamente após a criação.

Base URL

# Prefixe todos os endpoints com esta URL base https://krjkcbxijzdzlwabqxnu.supabase.co/functions/v1/public-api

Todos os endpoints seguem o padrão {base_url}/v1/{recurso}. A URL completa aparece no painel em API & Integrações.

Conexão à API

Siga os passos abaixo para obter suas credenciais e fazer a primeira chamada autenticada.

1

Acesse o painel

Faça login em app.cotract.app. Qualquer plano pago (Basic, Pro ou Business) já habilita acesso à API.

✓ Disponível no trial de 3 dias Basic, Pro e Business
2

Crie uma API key

No painel, vá em Configurações → API & Integrações → Nova chave. Dê um nome que identifique a integração (ex.: Produção – backend).

Selecione os scopes necessários

Dê o mínimo de permissão necessário. Consulte a tabela de scopes para a lista completa.

Máximo de 10 API keys por organização
3

Copie e guarde a chave

A chave é exibida apenas uma vez imediatamente após a criação. Não é possível recuperá-la depois — se perder, revogue e crie outra.

Nunca commite a chave no repositório. Use variáveis de ambiente ou um secret manager.

.env
# Adicione ao .env e inclua no .gitignore COTRACT_API_KEY=ctk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx COTRACT_BASE_URL=https://krjkcbxijzdzlwabqxnu.supabase.co/functions/v1/public-api
4

Teste a conexão

Faça uma requisição simples para confirmar que a chave está funcionando. Um 200 OK com a lista de contratos confirma que a autenticação está correta.

cURL — verificação de conexão
curl $COTRACT_BASE_URL/v1/contracts?limit=1 \ -H "Authorization: Bearer $COTRACT_API_KEY"
Resposta esperada — 200 OK
{ "contracts": [], "pagination": { "offset": 0, "limit": 1, "total": 0 } }

Se receber erro

401

Chave inválida ou header Authorization mal formatado. Verifique o prefixo Bearer com espaço.

403

Chave válida, mas sem o scope contracts:read. Revogue e crie uma nova com os scopes corretos.

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://krjkcbxijzdzlwabqxnu.supabase.co/functions/v1/public-api/v1/contracts \ -X POST \ -H "Authorization: Bearer ctk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "title": "Contrato de Prestação de Serviços", "description": "Desenvolvimento de site para empresa de advocacia. Prazo 30 dias, valor R$5.000.", "type": "service_agreement" }'
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://krjkcbxijzdzlwabqxnu.supabase.co/functions/v1/public-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
scope: contracts:read

Retorna lista paginada dos contratos da organização. Suporta If-None-Match para cache 304.

Query params

statusstringdraft · active · signed · expired
limitintegerItens por página, máx 100 (padrão: 20)
offsetintegerDeslocamento de paginação (padrão: 0)
Resposta 200
{ "contracts": [{ "id": "550e8400-e29b-41d4-a716-446655440000", "organization_id": "org-uuid", "title": "Contrato de Prestação de Serviços", "type": "service_agreement", "status": "active", "current_version_id":"version-uuid", "created_at": "2026-05-21T10:00:00Z", "expires_at": null }], "pagination": { "offset": 0, "limit": 20, "total": 42 } }
POST /v1/contracts
scope: contracts:write 1 crédito

Cria um contrato e inicia a geração assíncrona com Gemini. Retorna 202 imediatamente com job_id. Use /job-status para polling. Retorna 402 se não houver créditos.

Body (JSON)

title *stringTítulo do contrato
description *stringContexto para geração de IA (mín. 10 chars)
type *stringnda · employment · service_agreement · e outros
answersobjectRespostas de formulário customizado (opcional)
template_iduuidUUID de template específico (opcional)
expires_atISO 8601Data de expiração (opcional)
Resposta 202 — geração iniciada
{ "id": "550e8400-e29b-41d4-a716-446655440000", "organization_id": "org-uuid", "title": "NDA Agreement", "type": "nda", "status": "draft", "current_version_id":null, "created_at": "2026-05-21T10:15:30Z", "job_id": "async-job-uuid" }
GET /v1/contracts/:id/job-status
scope: contracts:read

Retorna o progresso da geração. Faça polling a cada 2–5s. Sem cache (no-store). Quando status: "completed", o contrato está disponível via GET /v1/contracts/:id.

Resposta 200
{ "job_id": "async-job-uuid", "status": "completed", // processing | completed | failed "progress": 100, // 0 a 100 "message": "Contract generated successfully", "contract": { "id": "contract-uuid", "current_version": {"content": "# NDA..."} } }
GET /v1/contracts/:id
scope: contracts:read

Retorna contrato com a versão atual. Campo current_version.content contém o texto em Markdown gerado pelo Gemini. Suporta ETag para cache 304.

Resposta 200
{ "contract": { "id": "contract-uuid", "title": "Contrato de Prestação de Serviços", "type": "service_agreement", "status": "active", "created_at": "2026-05-21T10:00:00Z" }, "current_version": { "id": "version-uuid", "version_number": 1, "content": "# Contrato de Prestação de Serviços\n\n**Partes:**...", "content_format": "markdown", "generated_by": "gemini-2.5-flash-lite" } }
PATCH /v1/contracts/:id
scope: contracts:write

Atualiza metadados do contrato (partial update). Não altera o conteúdo — o campo type é imutável após criação.

Body (JSON — todos opcionais)

titlestringNovo título
statusstringdraft · active · signed · expired · revoked
expires_atISO 8601 | nullData de expiração
GET /v1/contracts/:id/versions
scope: contracts:read

Retorna todas as versões do contrato ordenadas por version_number DESC (mais recentes primeiro). Cada versão inclui o conteúdo Markdown completo.

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

Lista solicitações de assinatura da organização. Status: pending · signed · rejected · expired.

Query params

contract_iduuidFiltrar por contrato
limitintegerMáx 100 (padrão: 20)
offsetintegerDeslocamento de paginação
POST /v1/signature-requests
scope: signatures:write

Cria solicitação de assinatura e retorna o token de assinatura (revelado uma única vez) e o signing_url para enviar ao signatário. Formato do token: ctk_sign_<32hex>.

Body (JSON)

contract_id *uuidID do contrato
signer_email *stringE-mail do signatário
signer_name *stringNome do signatário
expires_atISO 8601Expiração (padrão: +30 dias)
Resposta 201
{ "id": "sig-request-uuid", "contract_id": "contract-uuid", "signer_email":"john@example.com", "status": "pending", "token": "ctk_sign_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // revelado uma vez "signing_url": "https://app.cotract.io/sign?token=ctk_sign_xxx", "expires_at": "2026-06-21T10:30:00Z" }
GET /v1/webhook-events
scope variável

Lista eventos na fila de dispatch para debugging e monitoramento. Status: pending · delivered · failed · dead_letter. Sempre retorna dados frescos (sem cache).

Query params

statusstringpending · delivered · failed · dead_letter
limitintegerMáx 100 (padrão: 20)
offsetintegerDeslocamento de paginação
Resposta 200
{ "events": [{ "id": "dispatch-uuid", "endpoint_id": "endpoint-uuid", "event_type": "contract.created", "status": "delivered", "attempt_count": 1, "failure_count": 0, "next_retry_at": null, "created_at": "2026-05-21T10:15:30Z" }], "pagination": { "offset": 0, "limit": 20, "total": 127 } }
GET /v1/reviews
scope: reviews:read

Lista revisões de IA da organização. Cada revisão inclui o analysis com riscos, recomendações e termos-chave identificados pelo Gemini.

Query params

statusstringpending · processing · completed · failed
limitintegerMáx 100 (padrão: 20)
offsetintegerDeslocamento de paginação
POST /v1/reviews
scope: reviews:write 5 créditos 0 se cacheado

Analisa um contrato com Gemini 2.5 Flash Lite. Identifica riscos, recomendações e termos-chave. Resultado é cacheado por SHA-256 do documento — enviar o mesmo documento duas vezes consome 0 créditos na segunda vez. Geração: 10–60s.

Body (JSON)

doc_text *stringTexto do contrato (mín. 200 chars, máx. ~200KB)
file_name *stringNome do arquivo para referência
questionsstring[]Perguntas customizadas para a IA (opcional)
Resposta 202 — análise iniciada
{ "id": "review-uuid", "file_name": "nda_sample.md", "status": "processing", "analysis": null, "created_at":"2026-05-21T10:00:00Z" }
Resposta 200 — cacheado (0 créditos)
{ "id": "review-uuid", "status": "completed", "credits_used":0, "analysis": { "summary": "NDA bem estruturado com limitações razoáveis...", "risks": [{ "level": "high", "category": "scope", "description": "..." }], "recommendations": ["Reduzir período de confidencialidade para 3 anos"], "key_terms": { "confidentiality_duration": "5 anos" } } }
GET /v1/reviews/:id
scope: reviews:read

Retorna uma revisão específica com análise completa. Suporta ETag para 304 Not Modified. Polling recomendado a cada 3–5s enquanto status: "processing".

GET /v1/financial-summary
scope: analytics:read

Retorna KPIs financeiros e de uso de créditos da organização no período corrente. MRR/ARR expressos em créditos.

Resposta 200
{ "period": { "current_year": 2026, "current_month": 5 }, "revenue": { "mrr": 5000, "arr": 60000, "one_time_revenue": 1500 }, "contracts": { "total_active": 42, "total_signed": 127, "generated_this_month": 18 }, "credits": { "subscription_quota": 10000, "purchased_packs": 25000, "consumed_this_month": 2341, "remaining": 32659 } }

Scopes (permissões)

Cada API key tem um conjunto de scopes definidos na criação. Endpoints retornam 403 Forbidden se a chave não tiver o scope exigido.

Scope Endpoints cobertos
contracts:read GET /v1/contracts, GET /v1/contracts/:id, GET /v1/contracts/:id/versions, GET /v1/contracts/:id/job-status
contracts:write POST /v1/contracts, PATCH /v1/contracts/:id
signatures:read GET /v1/signature-requests
signatures:write POST /v1/signature-requests
reviews:read GET /v1/reviews, GET /v1/reviews/:id
reviews:write POST /v1/reviews
webhooks:manage Gerenciar endpoints de webhook (via painel)
analytics:read GET /v1/financial-summary

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

Geração de contrato iniciada/concluída

contract.updated

Status ou metadados alterados

contract.signed

Contrato totalmente assinado

contract.expired

Data de expiração atingida

signature.requested

Solicitação de assinatura criada

signature.completed

Signatário concluiu a assinatura

signature.rejected

Signatário recusou a assinatura

review.completed

Revisão de IA finalizada com resultado

review.failed

Revisão de IA falhou

webhook.test

Evento de teste disparado manualmente

Headers por entrega

Header Valor
X-Cotract-SignatureHMAC-SHA256 — formato t=<timestamp>,v1=<hex>
X-Cotract-EventTipo do evento (contract.created, etc.)
X-Cotract-DeliveryUUID único do dispatch
User-AgentCotract-Webhooks/1.0

Verificar assinatura HMAC

Formato compatível com Stripe. O header inclui timestamp para proteção contra replay (clock skew máx 5 min).

Node.js / Express
const crypto = require('crypto'); function verifyWebhook(payload, secret, signatureHeader) { // Formato: t=<timestamp>,v1=<hex> const [tPart, v1Part] = signatureHeader.split(','); const timestamp = parseInt(tPart.split('=')[1], 10); const v1 = v1Part.split('=')[1]; // Proteger contra replay (5 min de skew) if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false; // Assinar: HMAC(secret, "${timestamp}.${payload}") const signedContent = `${timestamp}.${payload}`; const expected = crypto .createHmac('sha256', secret) .update(signedContent) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(v1), Buffer.from(expected) ); } // No Express (raw body obrigatório para HMAC correto): 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'); const event = JSON.parse(req.body); // processar event.event, event.data... });

Retry com backoff exponencial

Máximo 5 tentativas. Timeout por entrega: 10s. Após esgotar tentativas, evento vai para dead letter.

Tentativa Backoff Cron
15sprimário (1 min)
30sprimário (1 min)
5 minretry (5 min)
30 minretry (5 min)
2 horasretry (5 min)
Dead letterSem mais retries

Limites & Créditos

30

req / minuto por API key

Rate limit global — todas as chamadas

1

crédito por POST /contracts

Geração de contrato com IA

5

créditos por POST /reviews

0 créditos se resultado em cache (SHA-256)

leituras sem custo

GET, PATCH, job-status, etc.

Créditos mensais se renovam no início de cada ciclo. Packs avulsos são descontados somente após esgotar os créditos da assinatura. Quando o limite de requisições é atingido, a API retorna 429 Too Many Requests com o header Retry-After.

Exclusivo API

Packs de Créditos via API

Para desenvolvedores que integram via POST /v1/contracts. Cada chamada consome 1 crédito. Os packs não expiram e são descontados após esgotar os créditos mensais do plano.

Packs são para integradores que fazem alto volume via API e querem previsibilidade de custo. Não há cobrança automática de excedente — quando os créditos acabam, a API retorna 402 até você adicionar mais.

15 créditos API

R$24,90

15 chamadas POST /v1/contracts

R$1,66/contrato

MAIS POPULAR
40 créditos API

R$54,90

40 chamadas POST /v1/contracts

R$1,37/contrato

100 créditos API

R$119,90

100 chamadas POST /v1/contracts

R$1,20/contrato

Packs disponíveis na aba API & Integrações do painel após ativar 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 — adicione um pack antes de continuar
403 FORBIDDEN API key não tem o scope exigido pelo endpoint
404 NOT_FOUND Contrato não encontrado ou sem acesso
413 PAYLOAD_TOO_LARGE Body da requisição excede 1 MB
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.