Documentos
Envio de um documento avulso para análise, sem vínculo com participante ou projeto. É o caminho mais curto para integrar. Este guia também cobre o envio de documento já vinculado a um participante e as demais operações sobre documentos.
Rotas
| método e rota | o que faz |
|---|---|
POST /v1/api/documents | Create a new document using API |
GET /v1/api/documents/{_id} | Fetch a document uploaded by company in API |
POST /v1/api/competencies/{competencyId}/participants/{participantId}/documents | Create participant document |
PATCH /v1/api/participant-documents/{participantDocumentId}/computed-fields | Update computed fields of a participant document |
GET /v1/api/participants/{participantId}/documents | Fetch competency documents for a participant |
GET /v1/api/participants/{participantId}/documents-data | Get all documents data for a participant |
POST /v1/api/competencies/{competencyId}/participants/{participantId}/document-group/{documentGroupId}/split-and-redistribute | Split and redistribute document api |
GET /v1/api/participant-documents/{participantDocumentId} | Fetch an document by id |
GET /v1/api/participant-documents/{participantDocumentId}/file-url | Obter a URL do arquivo de um documento |
PATCH /v1/api/participant-documents/{participantDocumentId}/status | Update participant document status |
Antes do primeiro envio
O tipo que você vai enviar precisa estar habilitado para a sua empresa. Se
não estiver, a resposta é 400 com "Tipo de documento não suportado" — o
erro não distingue "tipo inexistente" de "tipo não habilitado". Peça a
habilitação ao seu contato na Dynadok.
Para conhecer os tipos existentes e o que cada um extrai, veja a seção
Documentos — uma página por tipo, com a interface de
campos extraídos daquele tipo (ver "Receber o resultado" abaixo, sobre
parsedContent). Nem todo tipo listado ali está necessariamente habilitado
para a sua empresa; a habilitação é o que se pede ao contato Dynadok.
Aplicar regras de validação por requisição (rules)
Além da configuração de regras que a empresa já tem para o tipo de documento,
dá para aplicar regras só naquele envio, pelo campo rules. Ele é aceito
em três rotas: POST /v1/api/documents (abaixo), a de documento de
participante (ver Enviar o documento de um participante)
e a de split-and-redistribute (ver Separar e redistribuir).
O catálogo de regras — cada uma com suas propriedades, valores padrão e opções aceitas, com exemplos de uso — está em Regras de validação. Aqui vão só as três coisas que costumam sair erradas na primeira tentativa:
inputValueé sempre um array de strings — mesmo para um único valor, mesmo quando o valor é numérico (["90"], nunca90).- Numa requisição multipart, o array inteiro viaja como uma string JSON,
num campo de formulário chamado
rules(não é um campo por regra). Qualquer outra forma — um campo por regra, ou chaves com colchetes comorules[0][type]— é descartada em silêncio: a requisição responde200, o documento é criado e nenhuma regra é aplicada. Não há erro avisando, e a resposta do envio não devolve as regras, então o sintoma só aparece depois, num documento validado sem a regra que você esperava. - Uma regra contribui um item por propriedade configurada. Configurar
duas propriedades da mesma regra é dois itens com o mesmo
typeeinputNamediferente — é o caso deCNH_CATEGORYno exemplo abaixo, que liga a checagem (CNH_CATEGORY_VALIDATE) e define as categorias aceitas (CNH_CATEGORY_TYPES) em dois itens separados.
Exemplo aplicando duas regras de uma vez — aceitar apenas CNH dentro do prazo de validade e de categoria B ou AB:
curl --request POST 'https://api.dynadok.com/v1/api/documents' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE' \
--form 'files=@"/caminho/cnh.pdf"' \
--form 'type="CNH"' \
--form 'rules="[{\"type\":\"EXPIRATION_DATE\",\"inputName\":\"EXPIRATION_DATE_TYPE\",\"inputValue\":[\"valid\"]},{\"type\":\"CNH_CATEGORY\",\"inputName\":\"CNH_CATEGORY_VALIDATE\",\"inputValue\":[\"categories\"]},{\"type\":\"CNH_CATEGORY\",\"inputName\":\"CNH_CATEGORY_TYPES\",\"inputValue\":[\"B\",\"AB\"]}]"'
Enviar um documento avulso
curl --request POST 'https://api.dynadok.com/v1/api/documents' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE' \
--form 'files=@"/caminho/documento.pdf"' \
--form 'type="RG"' \
--form 'ownerData="{\"name\":\"João Silva\",\"cpf\":\"12345678909\"}"'
files aceita mais de um arquivo — as páginas são unificadas num documento só.
ownerData é opcional; se enviado, é validado como um JSON com name,
cpf, cnpj e dateOfBirth — os quatro também opcionais dentro do objeto.
Dois campos opcionais valem conhecer: maxPages limita quantas páginas são
analisadas, e rules aplica regras de validação só naquele envio — formato,
armadilhas e exemplo completo em
Aplicar regras de validação por requisição,
acima. Regras do tipo
Documentos Substitutos
aceitam em DOCUMENTS_IDS tanto um tipo de documento ("CNH", "RG") quanto
um ObjectId — não é preciso ter o id em mãos para referenciar um tipo.
A resposta vem na hora, com o documento ainda em PROCESSING (os valores
possíveis de status estão listados em Fluxo assíncrono)
— o _id é o que você guarda:
{
"code": 200,
"message": "OK",
"timestamp": 1758585600000,
"data": {
"_id": "6500a1b2c3d4e5f600000001",
"status": "PROCESSING",
"pagesCount": 2,
"type": "RG",
"ownerData": { "name": "João Silva", "cpf": "12345678909", "cnpj": null, "dateOfBirth": null },
"createdAt": "2026-09-23T12:00:00.000Z"
}
}
Receber o resultado
Configure o webhook EXTERNAL_DOCUMENT_PROCESSED — é o caminho recomendado,
descrito em Webhooks. Para uma conferência pontual:
curl 'https://api.dynadok.com/v1/api/documents/6500a1b2c3d4e5f600000001' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE'
Os dados extraídos vêm em data.parsedContent; o que falhou na validação, em
data.validationErrors. parsedContent é tipado como objeto genérico no
schema publicado — não é lá que você descobre os campos daquele tipo. A
interface real, campo a campo, está na seção Documentos,
uma página por tipo (ex.: RG, CNH).
Os demais campos da resposta estão na Referência.
Enviar o documento de um participante
Quando o documento pertence a alguém já cadastrado como participante de uma
competência (ver Participantes), envie por essa rota em
vez da avulsa. Não leva ownerData — os dados do dono vêm do cadastro do
participante, não do envio.
curl --request POST 'https://api.dynadok.com/v1/api/competencies/6500a1b2c3d4e5f600000004/participants/6500a1b2c3d4e5f600000002/documents' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE' \
--form 'files=@"/caminho/documento.pdf"' \
--form 'competencyDocumentId="6500a1b2c3d4e5f60000000a"'
Os campos do envio são exatamente estes: files e competencyDocumentId,
obrigatórios, mais dependentId, rules e extraData, opcionais. Esta rota não
leva os campos do envio avulso descrito acima.
rules aplica regras de validação só naquele envio e segue o mesmo formato das
outras rotas: uma string JSON com o array inteiro, num único campo de
formulário. Formato, armadilhas e catálogo completo em
Aplicar regras de validação por requisição.
curl --request POST 'https://api.dynadok.com/v1/api/competencies/6500a1b2c3d4e5f600000004/participants/6500a1b2c3d4e5f600000002/documents' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE' \
--form 'files=@"/caminho/cnh.pdf"' \
--form 'competencyDocumentId="6500a1b2c3d4e5f60000000a"' \
--form 'rules="[{\"type\":\"EXPIRATION_DATE\",\"inputName\":\"EXPIRATION_DATE_TYPE\",\"inputValue\":[\"valid\"]}]"'
O competencyDocumentId de cada documento solicitado vem em
Consultar os documentos solicitados ao participante.
Para documento de dependente, informe também o dependentId. Um
competencyDocumentId que não pertença à competência informada responde 400.
Resposta no mesmo formato do envio avulso:
{
"code": 200,
"message": "OK",
"timestamp": 1758585600000,
"data": {
"_id": "6500a1b2c3d4e5f600000001",
"status": "PROCESSING",
"pagesCount": 1,
"type": "RG",
"ownerData": { "name": null, "cpf": null, "cnpj": null, "dateOfBirth": null },
"createdAt": "2026-09-23T12:00:00.000Z"
}
}
Listar os documentos de um participante
curl 'https://api.dynadok.com/v1/api/participants/6500a1b2c3d4e5f600000002/documents' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE'
{participantId} aqui é o id da competencyParticipant (o mesmo participantId
usado no envio, acima) — não o id do documento. O _id de cada item da lista
abaixo é o do documento, um valor diferente do id do caminho; note que
competencyParticipantId no corpo de resposta repete o id do caminho.
Filtra por categoria com categories (CSV ou repetido, ex.:
?categories=DOCUMENT,INPUT); o default é só DOCUMENT.
{
"code": 200,
"message": "OK",
"timestamp": 1758585600000,
"data": [
{
"_id": "6500a1b2c3d4e5f600000001",
"competencyDocumentId": "6500a1b2c3d4e5f60000000a",
"competencyParticipantId": "6500a1b2c3d4e5f600000002",
"participantDependentId": null,
"documentGroupId": "6500a1b2c3d4e5f600000007",
"type": "RG",
"status": "PROCESSING",
"createdAt": "2026-09-23T12:00:00.000Z",
"competencyDocumentTitle": "RG do titular"
}
],
"meta": { "page": 1, "perPage": 20, "total": 1, "lastPage": 1 }
}
GET /v1/api/participants/{participantId}/documents-data devolve o mesmo tipo
de documento, mas todos de uma vez em data.documents, sem paginação e sem o
filtro por categoria. Formato completo na Referência.
Editar campos calculados de um documento
Campos preenchidos manualmente por quem revisa o documento (não extraídos por OCR/LLM).
O _id aqui é o do documento de participante — o que vem de "Enviar o documento
de um participante" ou de "Listar os documentos de um participante", não o de
POST /v1/api/documents.
curl --request PATCH 'https://api.dynadok.com/v1/api/participant-documents/6500a1b2c3d4e5f600000001/computed-fields' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE' \
--header 'Content-Type: application/json' \
--data '{
"computedFields": [
{ "label": "Vencimento conferido", "value": "true", "type": "CHECKBOX" }
]
}'
{
"code": 200,
"message": "OK",
"timestamp": 1758585600000,
"data": {
"_id": "6500a1b2c3d4e5f600000001",
"computedFields": [
{ "label": "Vencimento conferido", "value": "true", "type": "CHECKBOX" }
]
}
}
type aceita CHECKBOX, TEXT, TEXT_AREA ou MARKDOWN.
Separar e redistribuir um arquivo em vários documentos
POST .../document-group/{documentGroupId}/split-and-redistribute recebe um
ou mais arquivos (multipart, campo files, obrigatório) e tenta separar o
conteúdo em documentos distintos dentro do grupo indicado — útil quando o
participante manda várias páginas num PDF só. Aceita também documentRules,
maxPages, allowProcessingOnNewVersion e
rejectOnMissingRequiredTypesInGroup.
{
"code": 200,
"message": "OK",
"timestamp": 1758585600000,
"data": {
"_id": "6500a1b2c3d4e5f600000008",
"fileHash": "3f29e2d1c9b7a04e8f6c1d2b5a7e9f01",
"results": [
{
"_id": "6500a1b2c3d4e5f600000001",
"validationErrors": [],
"documentStatus": "PROCESSING",
"uploadGroupId": "6500a1b2c3d4e5f60000000b",
"aiDocumentSplitId": "6500a1b2c3d4e5f600000008"
}
],
"pendingDocuments": [
{ "type": "RG", "alternativeName": "RG do titular" }
]
}
}
results traz um item por documento reconhecido; pendingDocuments lista os
tipos esperados pelo grupo que não vieram nesse envio.
Buscar e atualizar um documento pelo id de participante
GET /v1/api/participant-documents/{participantDocumentId} devolve o mesmo
formato de documento das rotas acima (parsedContent, validationErrors,
computedFields, validationCheckpoints), mais os dados de onde ele está
anexado: documentUrl, competencyDocumentTitle, justification e
justificationUrl. Formato completo na Referência.
PATCH .../participant-documents/{participantDocumentId}/status não muda
para qualquer status da tabela em
Fluxo assíncrono. O DTO de entrada valida status
contra um enum que hoje só contém um valor: ACTION_REQUIRED. Qualquer outro
valor responde 400. Na prática, esta rota serve para uma coisa: marcar o
documento como pendente de reenvio, com um motivo:
curl --request PATCH 'https://api.dynadok.com/v1/api/participant-documents/6500a1b2c3d4e5f600000001/status' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE' \
--header 'Content-Type: application/json' \
--data '{
"status": "ACTION_REQUIRED",
"reason": "Foto ilegível, reenviar com melhor iluminação"
}'
O schema publicado não declara o formato do corpo de resposta desta rota —
confira o resultado direto na Referência ou com um
GET /v1/api/participant-documents/{participantDocumentId} em seguida.
Obter o arquivo de um documento
GET /v1/api/participant-documents/{participantDocumentId}/file-url devolve uma
URL assinada e temporária do arquivo. É o caminho para arquivar, auditar ou
mostrar ao usuário final o que foi enviado.
curl 'https://api.dynadok.com/v1/api/participant-documents/6500a1b2c3d4e5f600000030/file-url' \
--header 'x-api-key: 550e8400-e29b-41d4-a716-446655440000.SUA_CHAVE'
{
"code": 200,
"message": "OK",
"timestamp": 1758585600000,
"data": {
"fileUrl": "https://…/documents/2026-10-02/abc.pdf?X-Amz-Signature=…",
"justificationFileUrl": null
}
}
São dois arquivos independentes, e cada um pode vir null:
| campo | quando vem preenchido |
|---|---|
fileUrl | houve envio de arquivo no documento |
justificationFileUrl | houve justificativa com anexo |
As combinações possíveis:
- envio normal →
fileUrlpreenchido,justificationFileUrlnull - envio e justificativa com anexo → os dois preenchidos
- só justificativa com anexo →
fileUrlnull - justificativa só de texto, sem anexo →
justificationFileUrlnull
É uma URL assinada, com validade limitada. Não armazene o endereço: guarde o
participantDocumentId e consulte de novo quando precisar. Para descobrir o tipo
do arquivo, use o Content-Type devolvido ao baixar, ou a extensão no caminho da
URL — um documento enviado em formato livre (.xlsx, .zip) é armazenado como
veio, sem conversão para PDF.
Quando o documento não tem arquivo nenhum — nem envio, nem anexo de justificativa
— a resposta é 404. Falha ao gerar a URL de um arquivo que existe responde
500: os dois casos são distintos de propósito, para que ausência de dado não se
confunda com problema de infraestrutura.
Erros típicos
Ver Envelope e erros para o formato geral. Nesta
superfície, o mais comum é 400 com "Tipo de documento não suportado" no
envio, e erro de validação por campo do formulário — ownerData inválido
aparece como { "property": "ownerData", "message": [...] }.