Pular para o conteúdo principal

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 rotao que faz
POST /v1/api/documentsCreate 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}/documentsCreate participant document
PATCH /v1/api/participant-documents/{participantDocumentId}/computed-fieldsUpdate computed fields of a participant document
GET /v1/api/participants/{participantId}/documentsFetch competency documents for a participant
GET /v1/api/participants/{participantId}/documents-dataGet all documents data for a participant
POST /v1/api/competencies/{competencyId}/participants/{participantId}/document-group/{documentGroupId}/split-and-redistributeSplit and redistribute document api
GET /v1/api/participant-documents/{participantDocumentId}Fetch an document by id
GET /v1/api/participant-documents/{participantDocumentId}/file-urlObter a URL do arquivo de um documento
PATCH /v1/api/participant-documents/{participantDocumentId}/statusUpdate 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:

  1. inputValue é sempre um array de strings — mesmo para um único valor, mesmo quando o valor é numérico (["90"], nunca 90).
  2. 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 como rules[0][type] — é descartada em silêncio: a requisição responde 200, 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.
  3. Uma regra contribui um item por propriedade configurada. Configurar duas propriedades da mesma regra é dois itens com o mesmo type e inputName diferente — é o caso de CNH_CATEGORY no 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 é o que identifica o envio

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:

campoquando vem preenchido
fileUrlhouve envio de arquivo no documento
justificationFileUrlhouve justificativa com anexo

As combinações possíveis:

  • envio normal → fileUrl preenchido, justificationFileUrl null
  • envio e justificativa com anexo → os dois preenchidos
  • só justificativa com anexo → fileUrl null
  • justificativa só de texto, sem anexo → justificationFileUrl null
A URL expira

É 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": [...] }.