Regras que importam
- O arquivo nunca sai da máquina. Só a impressão digital do arquivo, o nome, o tamanho e os dados da obra e da autoria chegam à API.
- Acesso por contrato. A documentação é pública, o acesso não. Cada token pertence a uma conta com liberação ativa, concedida pela equipe.
- Não é registro público. O RegistrarObra não substitui INPI, Biblioteca Nacional, ANCINE, cartório ou qualquer órgão de registro, e não concede direito autoral, marca ou patente.
- Prova anterioridade, não autoria. O registro prova que o arquivo existia na data. A autoria que sai no certificado é declarada pelo titular; o RegistrarObra não a verifica.
- Prazos reais. O certificado costuma sair em até 15 minutos depois que o registro entra em processamento. A confirmação da âncora na blockchain Bitcoin leva algumas horas. Não prometa ao seu usuário confirmação na blockchain em minutos.
- Crédito por obra. Cada registro criado consome 1 crédito da conta titular. Crédito não se compra pela API.
- Um registro por arquivo. A mesma impressão digital não é registrada duas vezes, em nenhuma conta.
- Nada se apaga pela API. Não há endpoint de exclusão.
Visão geral
Base URL: https://auth.registrarobra.com.br/functions/v1
Tudo é JSON em UTF-8, sobre HTTPS. As respostas de erro trazem error em português (ver Erros).
| Método | Caminho | Escopo | Para quê |
|---|---|---|---|
| GET | /api-health-check | health:read | Testar a conexão e ver o saldo de créditos |
| POST | /api-submit-bulk-registration-job | bulk:create | Registrar de 1 a 25 obras (consome crédito) |
| GET | /api-get-bulk-job | bulk:read | Situação de um lote e de cada item |
| GET | /api-get-registration | registration:read | Situação de um registro |
| GET | /api-list-registrations | registration:read | Registros mais recentes, com paginação |
| GET | /api-get-registration-artifact | artifact:read | Link de download do certificado ou da ficha |
| GET | /api-verify-hash | registration:read | A verificação pública, por impressão digital |
Fluxo em três passos
- Obtenha a impressão digital do arquivo no seu sistema. O arquivo continua onde está; à API vai só a impressão digital, no formato do campo
file_hash(ver a especificação OpenAPI). O passo a passo técnico é entregue no início do contrato. - Crie o lote.
POST /api-submit-bulk-registration-jobcom de 1 a 25 obras. A resposta é202com ojob_id; o processamento segue em segundo plano e cada item vira um registro, consumindo 1 crédito. - Acompanhe e baixe. Receba o webhook do lote ou consulte
GET /api-get-bulk-job. Com oregistration_idde cada item, consulteGET /api-get-registrationatéstatusserconcluidoe baixe o certificado porGET /api-get-registration-artifact.
Autenticação
Envie o token da integração em todas as chamadas:
Authorization: Bearer ro_live_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefOs cabeçalhos x-api-key e x-api-token também são aceitos, com o token puro.
- O token (
ro_live_+ 64 caracteres) é mostrado uma vez, quando a equipe cria a integração. O RegistrarObra guarda só uma impressão dele; se você perder o token, a equipe gera outro e o anterior deixa de valer. - Guarde o token no servidor, nunca em código que roda no navegador ou no celular do seu cliente.
- Para revogar ou trocar um token, fale com a equipe. A revogação vale na hora.
- Uma integração pode ser da conta pessoal ou de um workspace. Em workspace, ela vê e cria registros do workspace, e o titular precisa continuar com permissão nele.
Escopos:
| Escopo | Permite |
|---|---|
health:read | Testar a conexão e ler o saldo de créditos |
bulk:create | Criar lotes (consome crédito) |
bulk:read | Consultar lotes criados por esta integração |
registration:read | Consultar e listar registros; verificar impressão digital |
artifact:read | Baixar certificado e ficha |
Limites
| Limite | Valor |
|---|---|
| Requisições por integração | Definido no contrato: 30 por minuto por padrão, até 600. Acima disso, 429 com Retry-After |
| Obras por lote | 1 a 25 |
| Corpo do lote | 256 KB |
| Arquivo | até 500 GB; arquivo vazio e arquivo comprimido (.zip, .rar, .7z, .iso...) são recusados |
| Título | 160 caracteres |
| Descrição | 600 caracteres |
| Nome do arquivo | 255 caracteres |
| Autores por obra | 1 a 10 |
external_job_id | até 128 caracteres: letras, números e . _ : - |
| Link de download | 120 segundos |
| Listagem | até 50 registros por página |
Idempotência
Envie sempre um external_job_id no lote: o identificador do pedido no seu sistema. Se a mesma integração mandar o mesmo external_job_id de novo — por um timeout do seu lado, por exemplo —, a API devolve o lote que já existe (200, "idempotent": true) em vez de criar outro e gastar crédito de novo. Duas chamadas simultâneas com o mesmo valor também resultam num lote só. order_id e job_id são aceitos como apelidos de external_job_id.
Endpoints
Nos exemplos, o token está na variável de ambiente REGISTRAROBRA_TOKEN. Os exemplos em TypeScript rodam em Node.js 18 ou mais novo e usam este auxiliar:
const BASE = "https://auth.registrarobra.com.br/functions/v1";
export async function api<T>(caminho: string, init: RequestInit = {}): Promise<T> {
const resposta = await fetch(`${BASE}/${caminho}`, {
...init,
headers: {
Authorization: `Bearer ${process.env.REGISTRAROBRA_TOKEN}`,
"Content-Type": "application/json",
...init.headers,
},
});
const corpo = await resposta.json();
if (!resposta.ok) throw Object.assign(new Error(corpo.error), { status: resposta.status, corpo });
return corpo as T;
}GET/api-health-check
Testa token, escopo e webhook, sem efeito colateral, e mostra o saldo de créditos da conta titular. Escopo health:read.
curl -s https://auth.registrarobra.com.br/functions/v1/api-health-check \
-H "Authorization: Bearer $REGISTRAROBRA_TOKEN"const saude = await api<{ credits: { available: number } }>("api-health-check");
console.log(`Créditos disponíveis: ${saude.credits.available}`);Resposta 200:
{
"ok": true,
"safe_test": true,
"side_effects": false,
"server_time": "2026-09-19T12:00:00.000Z",
"integration": {
"id": "5b0c2f4e-3a1d-4c7b-9e8f-1a2b3c4d5e6f",
"name": "Editora Exemplo",
"status": "active",
"key_prefix": "ro_live_01234567",
"scopes": ["health:read", "bulk:create", "bulk:read", "registration:read", "artifact:read"],
"rate_limit_per_minute": 30,
"webhook_configured": true,
"last_used_at": "2026-09-19T11:58:00.000Z"
},
"credits": { "available": 42 },
"checks": { "authentication": "ok", "scope": "health:read", "webhook": "configured" },
"next_recommended_calls": ["POST /api-submit-bulk-registration-job", "GET /api-get-bulk-job", "GET /api-get-registration"]
}POST/api-submit-bulk-registration-job
Registra de 1 a 25 obras com a mesma categoria e a mesma autoria. Escopo bulk:create. Consome 1 crédito por obra registrada; a API confere o saldo antes de aceitar e recusa o lote inteiro (409) se faltar crédito ou se alguma impressão digital já tiver registro.
Campos principais:
work_type: categoria —documento,musica,roteiro,livro,foto,video,argumento,obra_artistica,filme,planta_arquitetura,marca(identidade visual; não substitui o registro de marca no INPI) oupatente(invenção; não é patente).authors: 1 a 10 autores, na ordem; o primeiro é o principal. Nome completo, CPF válido, nacionalidade, CEP, estado, cidade, bairro, rua e número são obrigatórios. Coautores precisam de e-mail: recebem convite para confirmar.items: cada obra comtitle,file_name,file_hash(a impressão digital do arquivo, no formato da especificação),file_sizeem bytes e, se quiser,descriptionprópria.consent: os quatro aceites do site, todostrue. Colete-os do titular no seu sistema: aceite dos Termos de Uso, da Política de Privacidade, da responsabilidade por guardar o arquivo original e da execução imediata e irreversível. Eles ficam gravados em cada obra, com o id da sua integração.external_job_id: seu identificador do pedido (ver Idempotência).
curl -s -X POST https://auth.registrarobra.com.br/functions/v1/api-submit-bulk-registration-job \
-H "Authorization: Bearer $REGISTRAROBRA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"external_job_id": "pedido-2026-0042",
"name": "Álbum Cerrado",
"work_type": "musica",
"description": "Faixas do álbum Cerrado.",
"consent": {
"accepted_terms": true,
"accepted_privacy": true,
"acknowledged_original_file_responsibility": true,
"acknowledged_immediate_execution_and_irreversibility": true
},
"authors": [{
"full_name": "Maria da Silva",
"cpf": "529.982.247-25",
"email": "maria@exemplo.com.br",
"nationality": "Brasileira",
"cep": "70610-420",
"state": "DF",
"city": "Brasília",
"neighborhood": "Asa Sul",
"street": "SQS 308 Bloco A",
"number": "101"
}],
"items": [{
"title": "Chuva de Outubro",
"file_name": "chuva-de-outubro.wav",
"file_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"file_size": 48213996
}]
}'import { stat } from "node:fs/promises";
import { basename } from "node:path";
const caminho = "/obras/chuva-de-outubro.wav";
const impressaoDigitalDoArquivo: string = obterImpressaoDigital(caminho); // do seu sistema
const lote = await api<{ job_id: string; idempotent?: boolean }>("api-submit-bulk-registration-job", {
method: "POST",
body: JSON.stringify({
external_job_id: "pedido-2026-0042",
work_type: "musica",
consent: {
accepted_terms: true,
accepted_privacy: true,
acknowledged_original_file_responsibility: true,
acknowledged_immediate_execution_and_irreversibility: true,
},
authors: [{
full_name: "Maria da Silva",
cpf: "529.982.247-25",
nationality: "Brasileira",
cep: "70610-420",
state: "DF",
city: "Brasília",
neighborhood: "Asa Sul",
street: "SQS 308 Bloco A",
number: "101",
}],
items: [{
title: "Chuva de Outubro",
file_name: basename(caminho),
file_hash: impressaoDigitalDoArquivo,
file_size: (await stat(caminho)).size,
}],
}),
});
console.log(lote.job_id);Resposta 202:
{
"success": true,
"queued": true,
"job_id": "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
"external_job_id": "pedido-2026-0042",
"total_items": 1,
"status": "queued"
}Reenvio com o mesmo external_job_id responde 200 com "idempotent": true, o job_id existente e os contadores atuais.
GET/api-get-bulk-job
Situação de um lote criado por esta integração e de cada item, na ordem de envio. Informe job_id ou external_job_id. Escopo bulk:read.
curl -s "https://auth.registrarobra.com.br/functions/v1/api-get-bulk-job?external_job_id=pedido-2026-0042" \
-H "Authorization: Bearer $REGISTRAROBRA_TOKEN"const { job, items } = await api<{ job: { status: string }; items: Array<{ title: string; status: string; registration_id: string | null }> }>(
`api-get-bulk-job?job_id=${lote.job_id}`,
);
for (const item of items) console.log(item.title, item.status, item.registration_id);Resposta 200 (resumida):
{
"integration_id": "5b0c2f4e-3a1d-4c7b-9e8f-1a2b3c4d5e6f",
"job": {
"id": "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
"name": "Álbum Cerrado",
"status": "completed",
"total_items": 1,
"completed_items": 1,
"failed_items": 0,
"created_registrations": 1,
"external_job_id": "pedido-2026-0042",
"callback_attempts": 1,
"callback_last_status": 200
},
"items": [{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"position": 0,
"title": "Chuva de Outubro",
"file_name": "chuva-de-outubro.wav",
"file_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"file_size": 48213996,
"status": "completed",
"error_message": null,
"registration_id": "3c9d8e7f-6a5b-4c4d-9e3f-2a1b0c9d8e7f"
}]
}Lote completed quer dizer que os registros foram criados e entraram em emissão — não que os certificados já saíram. Veja Situações.
GET/api-get-registration
Um registro da conta (ou do workspace) da integração. Escopo registration:read.
curl -s "https://auth.registrarobra.com.br/functions/v1/api-get-registration?registration_id=3c9d8e7f-6a5b-4c4d-9e3f-2a1b0c9d8e7f" \
-H "Authorization: Bearer $REGISTRAROBRA_TOKEN"const { registration, artifacts } = await api<{
registration: { status: string; blockchain_tx_id: string | null };
artifacts: { certificate: { available: boolean } };
}>(`api-get-registration?registration_id=${registrationId}`);
const bloco = registration.blockchain_tx_id?.match(/^bitcoin-h:(\d+)/)?.[1];
console.log(registration.status, artifacts.certificate.available, bloco ? `bloco ${bloco}` : "âncora aguardando");Resposta 200:
{
"integration_id": "5b0c2f4e-3a1d-4c7b-9e8f-1a2b3c4d5e6f",
"registration": {
"id": "3c9d8e7f-6a5b-4c4d-9e3f-2a1b0c9d8e7f",
"title": "Chuva de Outubro",
"description": "Faixas do álbum Cerrado.",
"authors": "Maria da Silva",
"work_type": "musica",
"status": "concluido",
"payment_status": "paid",
"product_type": "registro",
"processing_step": "done",
"file_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"blockchain_tx_id": "bitcoin-h:915000",
"ficha_hash": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
"ficha_blockchain_tx_id": "bitcoin-h:915000",
"created_at": "2026-09-19T12:00:05.000Z",
"paid_at": "2026-09-19T12:00:06.000Z",
"completed_at": "2026-09-19T12:07:41.000Z",
"bulk_job_id": "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b"
},
"artifacts": {
"certificate": { "available": true, "endpoint": "https://…/functions/v1/api-get-registration-artifact?registration_id=…&artifact=certificate" },
"ficha": { "available": true, "endpoint": "https://…/functions/v1/api-get-registration-artifact?registration_id=…&artifact=ficha" }
}
}blockchain_tx_idé um identificador interno da âncora. Trate-o como opaco, com uma exceção: quando começa combitcoin-h:, o número depois dos dois-pontos é a altura do bloco Bitcoin que confirma a âncora. Qualquer outro valor significa âncora ainda não confirmada.ficha_hashé a impressão digital da ficha de cadastro, o documento com a autoria declarada, ancorado junto com o arquivo.processing_stepé informativo; não dependa dos valores.artifactspode trazer outras entradas além decertificateeficha; ignore as que não conhecer.
GET/api-list-registrations
Registros da conta (ou do workspace) da integração, do mais novo para o mais antigo. Parâmetros: limit (1 a 50, padrão 20) e before (data ISO 8601). Quando há mais página, a resposta traz next_before: mande-o em before na chamada seguinte. Escopo registration:read.
curl -s "https://auth.registrarobra.com.br/functions/v1/api-list-registrations?limit=20" \
-H "Authorization: Bearer $REGISTRAROBRA_TOKEN"let before: string | null = null;
do {
const pagina = await api<{ registrations: Array<{ id: string; title: string; status: string }>; next_before: string | null }>(
`api-list-registrations?limit=50${before ? `&before=${encodeURIComponent(before)}` : ""}`,
);
for (const registro of pagina.registrations) console.log(registro.id, registro.status, registro.title);
before = pagina.next_before;
} while (before);Resposta 200:
{
"integration_id": "5b0c2f4e-3a1d-4c7b-9e8f-1a2b3c4d5e6f",
"registrations": [{
"id": "3c9d8e7f-6a5b-4c4d-9e3f-2a1b0c9d8e7f",
"title": "Chuva de Outubro",
"work_type": "musica",
"status": "concluido",
"payment_status": "paid",
"product_type": "registro",
"file_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"created_at": "2026-09-19T12:00:05.000Z",
"paid_at": "2026-09-19T12:00:06.000Z",
"completed_at": "2026-09-19T12:07:41.000Z",
"bulk_job_id": "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b"
}],
"next_before": null
}GET/api-get-registration-artifact
Link de download de um documento de registro concluído: artifact=certificate (certificado em PDF) ou artifact=ficha (ficha de cadastro em PDF). A URL é assinada e vale 120 segundos: baixe logo. Com return=redirect, a API responde 302 direto para o arquivo. Antes da conclusão, responde 409. Escopo artifact:read.
curl -sL "https://auth.registrarobra.com.br/functions/v1/api-get-registration-artifact?registration_id=3c9d8e7f-6a5b-4c4d-9e3f-2a1b0c9d8e7f&artifact=certificate&return=redirect" \
-H "Authorization: Bearer $REGISTRAROBRA_TOKEN" \
-o certificado.pdfimport { writeFile } from "node:fs/promises";
const documento = await api<{ url: string; file_name: string }>(
`api-get-registration-artifact?registration_id=${registrationId}&artifact=certificate`,
);
const pdf = await fetch(documento.url);
await writeFile(documento.file_name, Buffer.from(await pdf.arrayBuffer()));Resposta 200:
{
"integration_id": "5b0c2f4e-3a1d-4c7b-9e8f-1a2b3c4d5e6f",
"registration_id": "3c9d8e7f-6a5b-4c4d-9e3f-2a1b0c9d8e7f",
"artifact": "certificate",
"file_name": "certificado-3C9D8E7F.pdf",
"content_type": "application/pdf",
"url": "https://…/storage/v1/object/sign/…",
"expires_in_seconds": 120
}GET/api-verify-hash
A mesma verificação pública da página registrarobra.com.br/verificar: diz se existe registro concluído com a impressão digital informada (do arquivo ou da ficha de cadastro) e, se existir, a data, a obra, a autoria declarada e a situação da âncora. Não olha a conta: o resultado é o que qualquer pessoa vê na página pública. Escopo registration:read.
curl -s "https://auth.registrarobra.com.br/functions/v1/api-verify-hash?file_hash=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" \
-H "Authorization: Bearer $REGISTRAROBRA_TOKEN"const verificacao = await api<{ found: boolean; registered_at?: string; anchor?: { confirmed: boolean } }>(
`api-verify-hash?file_hash=${impressaoDigitalDoArquivo}`,
);
console.log(verificacao.found ? `registrado em ${verificacao.registered_at}` : "sem registro concluído");Resposta 200:
{
"integration_id": "5b0c2f4e-3a1d-4c7b-9e8f-1a2b3c4d5e6f",
"found": true,
"matched": "file",
"registered_at": "2026-09-19T12:00:05.000Z",
"title": "Chuva de Outubro",
"authors_declared": "Maria da Silva",
"work_type": "musica",
"anchor": {
"confirmed": true,
"bitcoin_block_height": 915000,
"bitcoin_block_hash": "00000000000000000001a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f7",
"bitcoin_block_time": "2026-09-19T14:31:02.000Z"
},
"verification_url": "https://registrarobra.com.br/verificar?hash=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}Sem registro concluído, a resposta é {"found": false, "verification_url": "…"}.
Endpoints descontinuados
POST /api-create-upload-session e GET /api-get-upload-session respondem 410 Gone. Eram do tempo em que se enviava o arquivo; hoje o arquivo nunca é enviado. Use POST /api-submit-bulk-registration-job.
Webhooks
Se a integração tiver uma URL de webhook (cadastrada pela equipe, https e com endereço público), o RegistrarObra avisa quando o processamento de um lote criado pela API termina. O evento é bulk_job.<status> — normalmente bulk_job.completed, bulk_job.partial ou bulk_job.failed.
O webhook anuncia o resultado do lote (registros criados e créditos consumidos), não a emissão do certificado. Depois dele, acompanhe cada registro por GET /api-get-registration.
Cabeçalhos de cada entrega:
| Cabeçalho | Conteúdo |
|---|---|
Content-Type | application/json |
User-Agent | RegistrarObra-Webhooks/1.0 |
x-registrarobra-event | O evento, como bulk_job.completed |
x-registrarobra-delivery | Id desta tentativa (muda a cada tentativa) |
x-registrarobra-timestamp | Momento do envio, em segundos Unix |
x-registrarobra-signature | t=<segundos>,v1=<HMAC-SHA256 em hex> |
Corpo:
{
"event": "bulk_job.completed",
"integration_id": "5b0c2f4e-3a1d-4c7b-9e8f-1a2b3c4d5e6f",
"external_job_id": "pedido-2026-0042",
"job": {
"id": "0f8e7d6c-5b4a-4938-8271-605f4e3d2c1b",
"name": "Álbum Cerrado",
"status": "completed",
"total_items": 1,
"completed_items": 1,
"failed_items": 0,
"created_registrations": 1
},
"items": [{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"position": 0,
"title": "Chuva de Outubro",
"status": "completed",
"error_message": null,
"registration_id": "3c9d8e7f-6a5b-4c4d-9e3f-2a1b0c9d8e7f",
"file_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"completed_at": "2026-09-19T12:00:06.000Z"
}],
"delivered_at": "2026-09-19T12:00:07.000Z",
"delivery_id": "c0ffee00-1234-4abc-9def-001122334455"
}Verifique a assinatura antes de confiar no corpo. A assinatura é o HMAC-SHA256, com o segredo ro_whsec_... da integração (mostrado uma vez, na criação), do texto <t>.<corpo cru>. Use o corpo exatamente como chegou, antes de interpretar o JSON, e recuse t a mais de 5 minutos do seu relógio.
import { createHmac, timingSafeEqual } from "node:crypto";
export function assinaturaValida(corpoCru: string, cabecalho: string | undefined, segredo: string, agora = Date.now()) {
const partes = Object.fromEntries((cabecalho ?? "").split(",").map((parte) => {
const [chave, ...resto] = parte.split("=");
return [chave.trim(), resto.join("=").trim()];
}));
const t = Number(partes.t);
if (!Number.isSafeInteger(t) || !/^[0-9a-f]{64}$/.test(partes.v1 ?? "")) return false;
if (Math.abs(agora / 1000 - t) > 300) return false;
const esperado = createHmac("sha256", segredo).update(`${t}.${corpoCru}`).digest("hex");
return timingSafeEqual(Buffer.from(esperado), Buffer.from(partes.v1));
}Com Express, leia o corpo cru:
import express from "express";
const app = express();
app.post("/webhooks/registrarobra", express.text({ type: "application/json" }), (req, res) => {
if (!assinaturaValida(req.body, req.header("x-registrarobra-signature"), process.env.REGISTRAROBRA_WEBHOOK_SECRET!)) {
return res.sendStatus(401);
}
const evento = JSON.parse(req.body);
res.sendStatus(200); // responda rápido; processe depois
void processarLote(evento.job.id, evento.items);
});Entrega e novas tentativas:
- Responda
2xxem até 5 segundos. Qualquer outro status, tempo esgotado ou redirecionamento (3xx) conta como falha; o RegistrarObra não segue redirecionamentos. - São até 5 tentativas, com intervalos aproximados de 1 minuto, 5 minutos, 15 minutos e 1 hora. Depois disso a entrega para; a equipe pode reenviar.
- A entrega é "pelo menos uma vez": trate repetição pelo par
job.id+event, não pelodelivery_id. - Da sua resposta, só o status HTTP é guardado. O último status aparece em
callback_last_statusnoGET /api-get-bulk-job.
Erros
Todo erro vem como JSON com error (mensagem em português) e, quando houver, details. Não dependa do texto da mensagem: use o status HTTP e os campos de details.
{
"error": "Lote invalido",
"details": {
"issues": [
{ "field": "items[0].file_hash", "message": "SHA-256 em hexadecimal minúsculo (64 caracteres)" },
{ "field": "authors[1].email", "message": "obrigatório para coautores" }
]
}
}| Status | Quando |
|---|---|
400 | Parâmetro ausente ou malformado; corpo inválido, com details.issues (field e message para cada problema) |
401 | Token ausente, inválido ou revogado |
403 | Escopo insuficiente, acesso à API não liberado para o titular, ou titular sem permissão no workspace |
404 | Lote ou registro não encontrado para esta integração |
405 | Método HTTP errado |
409 | Impressão digital já registrada (details.file_hashes); créditos insuficientes (details.required_credits, details.available_credits); documento pedido antes da conclusão |
410 | Endpoint descontinuado |
413 | Corpo maior que o limite do endpoint |
429 | Limite por minuto atingido; espere os segundos de Retry-After |
500 | Erro inesperado; a resposta traz request_id (e o cabeçalho x-request-id) para o suporte |
Situações
| Objeto | Valor | Significado |
|---|---|---|
| Lote | queued | Na fila |
| Lote | processing | Criando os registros |
| Lote | completed | Todos os itens resolvidos (registrados ou já registrados antes) |
| Lote | partial | Parte dos itens falhou |
| Lote | failed | Nenhum item foi registrado |
| Item | completed | Registro criado e 1 crédito consumido |
| Item | duplicate | O arquivo já tinha registro; nenhum crédito consumido |
| Item | failed | Não registrado; veja error_message |
| Registro | pendente | Criado, aguardando confirmação (crédito ainda não consumido) |
| Registro | processando | Crédito consumido; emissão em andamento |
| Registro | concluido | Certificado disponível |
A âncora na blockchain Bitcoin é confirmada algumas horas depois da conclusão. Enquanto isso, o certificado já pode ser baixado e mostra a âncora como aguardando; o blockchain_tx_id passa a começar com bitcoin-h: quando o bloco confirma.
Créditos e cobrança
- Cada obra registrada pela API consome 1 crédito da conta titular da integração — a conta pessoal do titular, também quando a integração é de um workspace. Item
duplicatenão consome. - O saldo aparece em
credits.availablenoGET /api-health-check. - Crédito não se compra pela API. A conta titular compra créditos no painel do site ("Comprar créditos"), com preço por faixa de volume (registrarobra.com.br/planos), ou recebe créditos conforme o contrato, pela equipe.
Usando com IA
Se você integra com a ajuda de um assistente de IA, aponte-o para /llms-full.txt, que traz esta documentação e a especificação num arquivo só, e para a especificação OpenAPI. Um começo de conversa:
Você vai me ajudar a integrar meu sistema com a API do RegistrarObra.
Leia a documentação completa em https://registrarobra.com.br/llms-full.txt
e a especificação OpenAPI em https://registrarobra.com.br/openapi.yaml.
Regras que não podem ser quebradas:
- O arquivo da obra nunca é enviado à API; siga a documentação para o formato de cada campo.
- O token da API fica só no servidor, em variável de ambiente; nunca no código do navegador nem em logs.
- Todo lote leva external_job_id, para não gastar crédito duas vezes num reenvio.
- Verifique a assinatura de todo webhook antes de usar o corpo.
- Não prometa ao usuário final confirmação na blockchain Bitcoin em minutos: o certificado costuma sair em até 15 minutos; a âncora confirma em algumas horas.
- O RegistrarObra comprova anterioridade; não é registro público e a autoria é declarada, não verificada.
- Não há endpoint que apague registro, e crédito não se compra pela API.Como obter acesso
O acesso à API é concedido pela equipe do RegistrarObra, sob contrato. Não existe cadastro de desenvolvedor pelo site.
Para conversar, escreva para contato@registrarobra.com.br ou use a página Contato. Conte:
- quem é a empresa e qual o caso de uso;
- o volume estimado de obras por mês;
- se precisa de webhook (e a URL
httpsque vai recebê-lo); - se a integração é da conta pessoal ou de um workspace.
Com o contrato, a equipe libera o acesso na conta titular, cria a integração com os escopos e o limite combinados e entrega o token (e o segredo do webhook) uma única vez.
Changelog
- 2026-09-19 — Documentação pública e arquivos para assistentes de IA. Novos:
GET /api-list-registrations,GET /api-verify-hashe o saldo de créditos (credits.available) noGET /api-health-check. - 2026-09-16 — API sob contrato: acesso liberado pela equipe; token e segredo do webhook mostrados uma vez; assinatura de webhook obrigatória no formato
t=...,v1=...; os quatro aceites passaram a ser obrigatórios no lote; validação completa de autores e itens; idempotência também em chamadas simultâneas. - 2026-03-21 — O arquivo deixou de ser enviado: o registro passou a usar só a impressão digital. Os endpoints de sessão de envio foram descontinuados (
410).