API UniValidar
Valide assinaturas eletrônicas de documentos PDF (ICP-Brasil e gov.br) com o serviço oficial VALIDAR do ITI, receba os dados de cada assinante e o Relatório de Conformidade em PDF, tudo em uma única chamada.
{{BASE}}Visão geral
A API recebe o PDF assinado, consulta o VALIDAR do ITI e devolve um resultado padronizado: se o documento é válido, quem assinou, o certificado usado, a data da assinatura e o Relatório de Conformidade oficial.
POST /validar com o arquivo e o token no cabeçalho.valido, os assinantes e guarde o id como protocolo.Todas as respostas são em JSON (UTF-8). Datas seguem o formato devolvido pelo ITI (dd/mm/aaaa hh:mm:ss BRT).
Autenticação
Envie o token em todas as chamadas, por um destes cabeçalhos:
X-API-Key: uvt_seu_token_aqui
# ou
Authorization: Bearer uvt_seu_token_aquiO token dá acesso à sua cota. Guarde no servidor (variável de ambiente ou cofre de segredos) e nunca exponha em páginas públicas ou aplicativos instalados no celular do cliente.
Cada token pode ter limite diário, limite mensal e data de validade. Peça um token por sistema para acompanhar o uso separadamente.
Validar um PDF
/validarmultipart/form-dataEnvie o arquivo no campo file. Os demais parâmetros vão na URL (query string) e são opcionais.
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
fileobrigatório | arquivo | - | PDF assinado, até 15 MB. |
relatorio_conformidade | boolean | true | Anexa o PDF oficial do Relatório de Conformidade do ITI em relatorio_conformidade_base64. Use false para uma resposta mais leve e mais rápida. |
comprovante | pdf | png | - | Anexa a tela de resultado do VALIDAR como PDF ou imagem em comprovante_base64. |
cache | boolean | true | Reaproveita o resultado se o mesmo arquivo foi validado nas últimas 24 horas. false força uma consulta nova. |
completo | boolean | false | Inclui o relatório técnico completo do ITI em relatorio_iti. |
curl -X POST "{{BASE}}/validar" \
-H "X-API-Key: $TOKEN" \
-F "file=@procuracao.pdf"
import httpx TOKEN = "uvt_..." with open("procuracao.pdf", "rb") as f: r = httpx.post( "{{BASE}}/validar", headers={"X-API-Key": TOKEN}, files={"file": ("procuracao.pdf", f, "application/pdf")}, timeout=180, ) dados = r.json() if not dados["sucesso"]: print(dados["codigo"], dados["erro"]) else: print(dados["status_label"]) for a in dados["assinaturas"]: print(a["nome"], a["cpf"], a["status"])
import { readFile } from "node:fs/promises"; const form = new FormData(); form.append("file", new Blob([await readFile("procuracao.pdf")], { type: "application/pdf" }), "procuracao.pdf"); const r = await fetch("{{BASE}}/validar", { method: "POST", headers: { "X-API-Key": process.env.TOKEN }, body: form, signal: AbortSignal.timeout(180_000), }); const dados = await r.json(); if (!dados.sucesso) throw new Error(`${dados.codigo}: ${dados.erro}`); console.log(dados.status_label, dados.assinaturas);
<?php $ch = curl_init('{{BASE}}/validar'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('TOKEN')], CURLOPT_POSTFIELDS => ['file' => new CURLFile('procuracao.pdf', 'application/pdf')], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 180, ]); $dados = json_decode(curl_exec($ch), true); curl_close($ch); if (!$dados['sucesso']) { echo $dados['codigo'] . ': ' . $dados['erro']; } elseif ($dados['valido']) { echo 'Assinatura aprovada'; }
Resposta
Exemplo de resposta de uma validação aprovada (o PDF do relatório foi encurtado):
{
"id": 1532,
"sucesso": true,
"valido": true,
"status": "aprovada",
"status_label": "Assinatura aprovada",
"total_assinaturas": 1,
"assinaturas": [
{
"nome": "FULANO DE TAL",
"cpf": "***.123.456-**",
"autoridade": "ICP-Brasil",
"data": "16/10/2026 15:34:16 BRT",
"status": "aprovada",
"status_texto": "Assinatura aprovada",
"tipo_assinatura": "Destacada",
"motivo": "ASSINA POR PROCURAÇÃO",
"certificado": {
"tipo": "RFB e-CPF A1",
"emissor": "AC SAFEWEB RFB v5",
"valido_de": "04/03/2026 11:39:48 BRT",
"valido_ate": "04/03/2027 11:39:48 BRT",
"numero_serie": "0x44f3...",
"revogado": false,
"expirado": false
},
"cadeia_certificados": ["FULANO DE TAL", "AC SAFEWEB RFB v5", "AC Secretaria da Receita Federal do Brasil v4", "Autoridade Certificadora Raiz Brasileira v5"],
"cadeia_valida": true,
"integridade_ok": true,
"carimbos_tempo": [{ "emissor": "SAFEWEB 50160", "referencia": "16/10/2026 15:34:32 BRT", "status": "aprovada" }],
"algoritmo": "RSA",
"alertas": []
}
],
"documento": {
"nome": "procuracao.pdf",
"hash": "70562c78d196...a163859",
"tipo_arquivo": "PDF",
"data_validacao": "17/10/2026 20:07:27 BRT",
"conformidade": "MP 2.200-2/2001"
},
"arquivo": { "nome": "procuracao.pdf", "tamanho_bytes": 669924, "sha256": "70562c78d196...a163859" },
"tempo_ms": 6230,
"cache": false,
"relatorio_conformidade": { "disponivel": true, "tamanho_bytes": 48211, "baixar": "/validacoes/1532/relatorio-conformidade" },
"relatorio_conformidade_base64": "JVBERi0xLjQKJ...",
"relatorio_texto": "Informações gerais do arquivo: ..."
}Campos principais
| Campo | Tipo | Descrição |
|---|---|---|
id | número | Protocolo da validação. Guarde para consultar depois ou baixar o relatório. |
sucesso | boolean | true quando a consulta foi concluída (mesmo que a assinatura seja reprovada). |
valido | boolean | null | true só quando todas as assinaturas foram aprovadas. |
status | texto | Resultado geral. Veja Resultado da assinatura. |
status_label | texto | Resultado pronto para mostrar ao usuário. |
total_assinaturas | número | Quantidade de assinaturas encontradas (o carimbo do tempo não conta como assinatura). |
assinaturas | lista | Uma entrada por assinatura, com os campos da tabela abaixo. |
documento | objeto | Dados do documento segundo o ITI: nome, hash, tipo, data da validação e norma de conformidade. |
arquivo | objeto | Nome, tamanho e SHA-256 do arquivo enviado. |
tempo_ms | número | Tempo total da validação, em milissegundos. |
cache | boolean | true quando o resultado veio de uma validação recente do mesmo arquivo. |
relatorio_conformidade | objeto | disponivel, tamanho_bytes e o caminho baixar do PDF. |
relatorio_conformidade_base64 | texto | PDF oficial do Relatório de Conformidade, em base64. |
selos | lista | Selos do resultado: nome, tipo, titulo, assinatura, situacao e o caminho png. Veja Selos em PNG. |
comprovante_base64 | texto | Tela de resultado do VALIDAR (quando pedido o comprovante), com o tipo em comprovante_tipo. |
relatorio_texto | texto | Resumo do resultado em texto, como exibido pelo ITI. |
relatorio_iti | lista | Relatório técnico completo do ITI (só com completo=true). |
Cada assinatura
| Campo | Tipo | Descrição |
|---|---|---|
nome | texto | Titular do certificado. |
cpf | texto | CPF (ou CNPJ) do titular, mascarado como o ITI exibe. |
autoridade | texto | ICP-Brasil ou Gov.br. |
data | texto | Data e hora da assinatura. |
status | texto | aprovada, reprovada ou indeterminada. |
tipo_assinatura | texto | Por exemplo Destacada ou Anexada. |
motivo | texto | Motivo declarado na assinatura, por exemplo "ASSINA POR PROCURAÇÃO". |
certificado | objeto | tipo, emissor, valido_de, valido_ate, numero_serie, revogado, expirado. |
cadeia_certificados | lista | Do titular até a autoridade raiz. |
cadeia_valida | boolean | Cadeia de confiança aprovada pelo ITI. |
integridade_ok | boolean | O documento não foi alterado depois de assinado. |
carimbos_tempo | lista | Carimbos do tempo da assinatura: emissor, referencia, status. |
alertas | lista | Avisos registrados pelo ITI que não invalidam o documento. |
Resultado da assinatura
| status | valido | Significado |
|---|---|---|
| aprovada | true | Todas as assinaturas foram aprovadas pelo ITI. |
| reprovada | false | Ao menos uma assinatura é inválida (documento alterado, certificado revogado, cadeia não confiável, entre outros). |
| indeterminada | false | O ITI não conseguiu concluir a análise. Comum quando o programa que assinou não segue todos os requisitos. |
| sem_assinatura | false | O PDF não tem assinatura eletrônica. |
| desconhecido | null | Resultado não reconhecido. Tente de novo com cache=false. |
Relatório de Conformidade
É o PDF oficial emitido pelo VALIDAR, com todas as informações técnicas da validação. Vem anexado por padrão em relatorio_conformidade_base64.
import base64 if dados["relatorio_conformidade"]["disponivel"]: with open(f"relatorio-{dados['id']}.pdf", "wb") as saida: saida.write(base64.b64decode(dados["relatorio_conformidade_base64"]))
import { writeFile } from "node:fs/promises"; if (dados.relatorio_conformidade?.disponivel) { await writeFile(`relatorio-${dados.id}.pdf`, Buffer.from(dados.relatorio_conformidade_base64, "base64")); }
if ($dados['relatorio_conformidade']['disponivel']) { file_put_contents("relatorio-{$dados['id']}.pdf", base64_decode($dados['relatorio_conformidade_base64'])); }
O PDF também pode ser baixado depois, pelo protocolo:
/validacoes/{id}/relatorio-conformidadeapplication/pdfSe o relatório não estiver disponível, relatorio_conformidade.disponivel vem false e o restante do resultado continua válido. Para respostas mais rápidas quando o relatório não for necessário, envie relatorio_conformidade=false.
Selos em PNG
Cada validação gera selos prontos para exibir no seu sistema ou anexar ao processo: um selo de assinatura para cada assinante (qualificada, avançada ou eletrônica, com a situação e o protocolo) e um selo de carimbo do tempo quando a assinatura tiver carimbo. As imagens têm 880 × 392 px, fundo transparente nos cantos.
/validacoes/{id}/seloslista dos selos/validacoes/{id}/selos/{nome}.pngimage/pngOs nomes seguem o padrão assinatura-1, carimbo-1, assinatura-2... A resposta de /validar já traz a lista em selos. Para receber as imagens na mesma chamada, envie selos_base64=true e leia selos[].png_base64.
curl -H "X-API-Key: $TOKEN" -o selo-assinatura.png \
"{{BASE}}/validacoes/1532/selos/assinatura-1.png"
for selo in dados["selos"]: png = requests.get(BASE + selo["png"], headers=CAB, timeout=30).content open(f"{selo['nome']}.png", "wb").write(png)
Validar por URL
/validar/urlapplication/jsonPara PDFs que já estão publicados em um endereço acessível pela internet.
| Campo | Tipo | Padrão | Descrição |
|---|---|---|---|
urlobrigatório | texto | - | Endereço do PDF (http ou https). |
relatorio_conformidade | boolean | true | Anexa o Relatório de Conformidade. |
comprovante | pdf | png | - | Anexa a tela de resultado. |
cache | boolean | true | Reaproveita resultado recente. |
completo | boolean | false | Inclui o relatório técnico completo. |
curl -X POST "{{BASE}}/validar/url" \
-H "X-API-Key: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://exemplo.com.br/documento.pdf"}'Validar em lote
/validar/lotemultipart/form-dataAté 10 PDFs por chamada, repetindo o campo files. Aceita os mesmos parâmetros de /validar. Cada arquivo que não vier do cache consome uma unidade da cota.
curl -X POST "{{BASE}}/validar/lote?relatorio_conformidade=false" \
-H "X-API-Key: $TOKEN" \
-F "files=@contrato.pdf" \
-F "files=@procuracao.pdf"{
"total": 2,
"aprovadas": 1,
"com_erro": 0,
"resultados": [ { "id": 1533, "status": "aprovada", ... }, { "id": 1534, "status": "reprovada", ... } ]
}Os itens de resultados seguem a mesma ordem dos arquivos enviados e têm o mesmo formato da resposta de /validar.
Consultar depois
/validacoes/{id}JSONDevolve de novo o resultado de uma validação feita antes, pelo id. Cada token só enxerga as próprias validações. Aceita completo=true.
/validacoes/{id}/relatorio-conformidadePDFcurl -H "X-API-Key: $TOKEN" "{{BASE}}/validacoes/1532"
curl -H "X-API-Key: $TOKEN" -o relatorio.pdf \
"{{BASE}}/validacoes/1532/relatorio-conformidade"Cota de uso
Quando o token tem limite, as respostas de validação trazem os cabeçalhos:
| Cabeçalho | Descrição |
|---|---|
X-Cota-Restante-Dia | Validações restantes hoje (horário de Brasília). |
X-Cota-Restante-Mes | Validações restantes no mês. |
/contaJSON{
"nome": "Sistema de Procurações",
"limite_dia": 500, "usado_dia": 37, "restante_dia": 463,
"limite_mes": null, "usado_mes": 0, "restante_mes": null
}Limite null significa sem limite. Ao esgotar a cota a API responde 429 com o código COTA_ESGOTADA.
Cache
O mesmo arquivo (mesmo conteúdo, identificado pelo SHA-256) validado nas últimas 24 horas devolve o resultado na hora, com "cache": true, e não consome cota. O Relatório de Conformidade também volta anexado.
Para forçar uma consulta nova ao ITI, envie cache=false.
Erros
Todo erro devolve "sucesso": false, um codigo fixo para tratar no seu sistema e uma mensagem em erro.
{
"sucesso": false,
"codigo": "COTA_ESGOTADA",
"erro": "Limite diário atingido (500 validações)"
}| HTTP | codigo | Quando acontece | O que fazer |
|---|---|---|---|
| 400 | ARQUIVO_INVALIDO | O arquivo enviado não é um PDF. | Envie o PDF original assinado. |
| 401 | TOKEN_INVALIDO | Token ausente ou incorreto. | Confira o cabeçalho X-API-Key. |
| 403 | TOKEN_BLOQUEADO | Token desativado ou vencido. | Fale com o administrador da conta. |
| 404 | NAO_ENCONTRADO | Protocolo inexistente ou de outro token; relatório não disponível. | Confira o id. |
| 413 | ARQUIVO_GRANDE | Arquivo acima de 15 MB ou lote com mais de 10 arquivos. | Divida o envio. |
| 422 | PARAMETRO_INVALIDO | Campo obrigatório ausente ou valor inválido. A lista vem em campos. | Corrija a chamada. |
| 422 | URL_INACESSIVEL | Não foi possível baixar o PDF da URL informada. | Confira se o endereço é público. |
| 429 | COTA_ESGOTADA | Limite diário ou mensal do token atingido. | Aguarde a renovação ou peça aumento. |
| 502 | SERVICO_INDISPONIVEL | O serviço do ITI está fora do ar ou não respondeu a tempo. | Tente de novo em alguns minutos. O id fica registrado. |
Boas práticas
| Tempo de espera | Configure o cliente HTTP para aguardar até 180 segundos. A maioria das validações responde em poucos segundos, mas o ITI pode demorar em horários de pico. |
| Nova tentativa | Em SERVICO_INDISPONIVEL, aguarde alguns minutos e tente de novo, com intervalos crescentes. Não repita em sequência imediata. |
| Protocolo | Grave o id junto do documento no seu sistema. Ele permite reconsultar o resultado e baixar o relatório depois. |
| Resposta leve | Se não precisa do PDF do relatório, envie relatorio_conformidade=false: a resposta fica menor e mais rápida. |
| Arquivo original | Envie sempre o PDF exatamente como foi assinado. Qualquer alteração (mesmo reimprimir ou salvar de novo) invalida a assinatura. |
| Segurança | Chame a API a partir do seu servidor. Se precisar chamar direto de uma página web (front-end), peça ao administrador para liberar o endereço do seu site. |
Disponibilidade
/healthsem token{ "ok": true, "produto": "UniValidar", "versao": "3.0.0" }A referência técnica gerada automaticamente (OpenAPI) está em /docs.