Skip to main content
A document does not have to come from a Doodocs template. When an external system has already produced the PDF — an order from 1C, a contract from a CRM, a scan — upload it and route it like any other document. The bytes travel outside the API: the server hands you a presigned form, you send the file straight to storage, confirm the upload, then create the document by file_id. All three steps are covered by the documents:write scope.

From a file to a document in flight

Step 1. Reserve the file

POST /developer/v1/files creates the record and returns the upload form.
size_bytes is the exact byte count. The signed policy rejects an object larger than that, and _confirm compares what storage holds against what you declared.

Step 2. Send the bytes to storage

Submit the form as multipart/form-data: every entry of fields verbatim first, the file last as the file part.
A successful upload is 204 with no body. Do not send X-API-Key here — the signature in the form already authorizes the request. The form is valid until expires_at; after that, reserve the file again.

Step 3. Confirm the upload

Until the upload is confirmed, the file cannot be attached to a document.
Confirming an already confirmed file changes nothing and returns 200, so retrying after a timeout is safe.

Step 4. Create the document from the file

Pass file_id to POST /documents instead of template_id. The file becomes the document’s PDF — exactly what approvers see and signers sign.
template_id and file_id are mutually exclusive: passing both or neither is DEVELOPER.INVALID_ARGUMENT. template_values without template_id is rejected too, rather than silently ignored.
From here the path is the usual one — route, send and sign. The key’s owner becomes the initiator, the same as when creating from a template.

Limits

Nothing is converted: a DOCX or an image is rejected, and the file goes to signing exactly as you sent it. Produce the PDF on your side.
The unconfirmed-upload limit counts by key owner and is shared with the web app: an integration that reserves files without confirming them also consumes that person’s quota in the interface.

Errors

A document created from a file gets no number automatically — numbering is tied to templates. Pass number in POST /documents if you need one.