Attachments and OCR
Upload a file, let DocDealer extract structured data from it, and feed that into the form.
This is the flow that makes DocDealer worth wiring into a backend rather than filling a form by hand: upload an ID, a deed, a land-registry extract, and have its contents become form values.
Upload
Multipart, with file, fileName and documentId. Max 50 MB.
curl -X POST https://thedocdealer.com/api/attachments \
-H "Authorization: Bearer $DOCDEALER_API_KEY" \
-F "file=@dni.pdf" \
-F "fileName=dni.pdf" \
-F "documentId=<uuid>"PDFs, images (JPEG/PNG/GIF/WebP/TIFF), Office documents, plain text and CSV are accepted. DOCX is converted to PDF server-side. Identical files are de-duplicated by hash, so re-uploading the same document costs nothing and returns the existing attachment.
Analyse
Analysis is asynchronous: start it, then poll.
It targets a specific file_attachment field, and that is not incidental — the field's schema is
what tells the model which shape to extract. Analysing "a PDF" in the abstract would give you prose;
analysing it as the dni field of the comparecientes object gives you the name, number and
expiry the template actually needs.
# Start — returns { "id": "<analysisId>", ... }
curl -X POST https://thedocdealer.com/api/ai/analyze/attachment \
-H "Authorization: Bearer $DOCDEALER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"documentId": "<uuid>",
"attachmentIds": ["<attachmentId>"],
"fieldId": "field_dni",
"entryIndex": 0
}'
# Poll — status: 0 pending, 1 success, 2 error
curl "https://thedocdealer.com/api/documents/<uuid>/attachment-analyses/<analysisId>" \
-H "Authorization: Bearer $DOCDEALER_API_KEY"Requires the attachments:analyze scope, which spends AI credit. For API-key callers, results are
auto-accepted regardless of what you pass for autoAccept — there is no human in the loop to review
them.
Reference the result from the form
Analyses are referenced, not copied:
{
"comparecientes._count": 1,
"comparecientes.0.dni": { "type": "attachment_analysis", "$ref": "<analysisId>" }
}The reference is what lets a rule branch on something the model extracted —
path: "address.postcode" on a condition reads into the analysis result, so document structure can
follow the contents of an uploaded file.
The upload → analyse flow is mandatory
There is no shortcut for callers who already hold the extracted data. A
file_attachment field accepts exactly one value shape — a reference to a real analysis:
{ "type": "attachment_analysis", "$ref": "<analysisId>" }Anything else on such a field is rejected with 403 and this message:
Field "comparecientes.0.dni" is a file attachment — do not set it directly and never
inline extracted data. Call create_attachment_upload_url, upload the file from disk,
then analyze_attachments, which fills this field from the real extraction.In particular, inlining { "type": "attachment_analysis", "data": { "analysisResult": … } }
does not work, even though it looks like it should. The server requires a non-empty
$ref to an analysis it created, so provenance always traces back to a real uploaded file
and a real extraction.
So a migration of existing records still has to push the source files through
POST /api/attachments and POST /api/ai/analyze/attachment. That costs an analyze_file
call per document, which is the expensive call type — budget for it rather than being
surprised by it.
Cost
analyze_file is one of the two expensive call types — it is a vision call over a whole document.
Two things follow:
- De-duplication is free money. The same file uploaded twice is analysed once.
- Re-triggering is not cached. Asking for analysis again means you want a fresh result, so it runs again. Do not poll by re-posting.
Mint a key without attachments:analyze for any integration that only needs to read or attach files.
See Authentication.