Validate before you send
Ask what a generate call would find, before you make it. The dry run applies every check the real call applies, tells you how many pages the document will have and what it is expected to cost, and charges nothing, reserves nothing and stores nothing.
The call
POST /api/v1/compose/documents/validate
Authorization: Bearer <key>
{
"data": { "number": "2026-000147" },
"settings": { "templateId": "invoice-standard-8bc99b" },
"estimatePages": true,
"plannedExtras": ["signature"]
}
The body is the body of
generate, plus two optional keys.
It needs the same token scope (documents:compose), the same
settings rules (isTest needs its scope), and it takes an
optional Idempotency-Key like every other POST: a replay
within 24 hours returns the first answer, balance included, so use a fresh key for
a fresh estimate. Nothing is charged either way.
estimatePages(defaulttrue): render the document once, for this call only, to count its pages. It is never stored or charged and it queues behind production work. Sendfalsefor a cheaper answer withoutpages.estimate.plannedExtras: extras you will add after the document. Today["signature"], so its cost appears in the estimate.
The answer
The call itself succeeded (output.status is succeeded); the
verdict is in output.compose.validation.
| Field | Meaning |
|---|---|
ok | No blocking problem: generate would not be refused for what was checked here. |
errors | What would refuse the call, shaped like a real error (code, number, message, details): a missing field in a strict template, a payload that fails a reject JSON Schema, a stored file that does not exist, a limit exceeded, a seal your organisation has not bought. |
warnings | What the real call would warn about, shaped like output.warnings. |
templateErrors, templateWarnings | The template diagnostics, as sentences: the same engine as the console’s Validate button and the upload (unknown formatting codes, charts that cannot be drawn, conditions the engine cannot explain). |
missingFields, unusedFields | Read by the template and absent from the payload; sent and never read. |
payloadSchema | The template’s JSON Schema verdict: mode, checked, valid, and the first violations (path, keyword, message; never a value). |
pages | estimate (the real page count of a render made for this call, appended PDFs included), method (rendered, not_requested or unavailable when the platform was too busy to spare a render), limit. |
files | The stored files the request names, checked to exist and to be the right kind. |
estimatedCredits | See below. |
charged, stored | Always 0 and false. |
What the credit estimate promises
The estimate is a deterministic model (per-operation-rate/v1), not a
guess: it is the same price function the real reservation uses, at your
organisation’s rates.
"estimatedCredits": {
"model": "per-operation-rate/v1",
"certainty": "dependsOn",
"credits": 5,
"maximum": 15,
"dependsOn": [
{"item": "signature", "credits": 10,
"condition": "charged when the envelope is sent (Signer Fly or Document Fly)"}
],
"testItems": 0,
"chargedOn": "delivery",
"balance": {"availableCredits": 1247, "sufficient": true},
"plan": {
"subscriptionId": "6c1f...", "planCode": "PIONR026",
"takes": [{"item": "document", "counter": "calls", "units": 1},
{"item": "signature", "counter": "calls", "units": 0}],
"remaining": {"calls": 4210}, "sufficient": true,
"whenShort": "refused", "endsAt": "2026-12-31T23:00:00+00:00"
}
}
creditsis the document’s rate: flat, whatever the format or the number of pages. It is charged when the document is delivered and refunded on any failure.certaintyisexactwhen nothing else can be charged anddependsOnwhen something may be: a qualified seal or timestamp (only if applied) or the extras you declared.maximumis the most the whole thing can cost, andsufficientcompares it with what you can still draw.planisnullwithout a plan. With one, it says what each item takes from which counter of the plan (takes; on a plan counted in calls a signature planned after its document rides on the same call,units0), what is left, whether it is enough, and what happens when it is not (whenShort:creditif you turned paying with credit on,blockfor a plan that never blocks, otherwiserefusedwithSUBSCRIPTION_ALLOWANCE_EXHAUSTED). An item the plan covers takes no credit;creditsandmaximumstay the credit price.- An
isTestcall is0credits and one test item. - It is true for today’s rates. A later change of rate, or an envelope’s own fees beyond the extras you named, are outside it.
There is no image preview. A preview would be a second render of every page to a raster, the cost of a real generation for something you cannot send. The page count is what you need before sending, and it is in the answer.