Check the current contract and validator results before you build on this.
A useful document-operation result answers four separate questions: did the operation execute, what changed or degraded, which exact artifact was produced, and what evidence accompanied it? A single `success: true` cannot carry those meanings. Production APIs need typed errors, diagnostics, loss entries, content-addressed artifact identity, and a receipt whose authority is stated rather than implied.
Why a file URL is not a sufficient result
Many document APIs return a URL and maybe a MIME type. That works for a demo, but the caller must guess whether the operation completed as requested.
Consider a DOCX-to-PDF conversion that returned a valid PDF after substituting a font and rasterizing a chart. The transport succeeded and the file opens. The recipient may still reject the artifact because text reflowed or the chart is no longer searchable. If the response says only success, the loss becomes invisible precisely when the workflow needs to decide whether human review is required.
The opposite problem also occurs. A package validator may report three diagnostics while the operation still produces an acceptable draft. Treating every diagnostic as a hard failure forces unnecessary retries and hides the difference between an advisory and a violated release rule.
Separate the five result planes
A document result becomes easier to reason about when it has distinct planes:
| Plane | Question | Example |
|---|---|---|
| Status | Did the requested operation complete? | ok, error, cancelled |
| Error | Why could it not complete? | invalid input, unavailable binding, resource limit |
| Diagnostics | What should an operator or reviewer inspect? | overflow warning, missing optional metadata |
| Losses | What requested semantic or visual property was not preserved? | font substitution, flattened chart |
| Artifact and receipt | Which bytes exist, and what evidence is bound to them? | SHA-256, byte count, policy version |
Keep these fields machine-readable. Prose can explain a result to a person, but a retry controller, release gate, or agent needs stable codes and explicit retryability.
Errors describe non-completion
An error says the requested operation did not produce a result that satisfies its completion contract. Useful fields include:
- a stable error code;
- the stage that failed: selection, validation, authorization, binding, execution, storage, or release;
- whether retrying the same request can help;
- which input location caused the problem, when safe;
- bounded remediation guidance;
- a correlation identifier for operator investigation.
Do not mark invalid input as retryable. Do not make authorization errors look like transient infrastructure failures. Do not expose stack traces, secrets, or private storage paths to the agent.
For MCP, the official tools specification distinguishes protocol errors such as an unknown tool or invalid arguments from tool-execution errors returned by the tool. A document server can preserve that distinction and still return domain-specific codes inside a structured result.
Diagnostics describe observations
A diagnostic is evidence about the run, not necessarily a failure. It may report that a text box is close to capacity, an optional field was normalized, a viewer-specific feature was found, or an external validator was unavailable.
Every diagnostic should state its severity and source. “Validation warning” is too vague. Prefer a code, a locator, the validator or rule set, and the policy consequence:
{
"code": "TEXT_OVERFLOW_RISK",
"severity": "review",
"locator": "slide:4/shape:revenue-summary",
"source": "layout-preflight-v1",
"message": "Estimated text exceeds the configured box capacity."
}
The message helps a person. The code, severity, locator, and source let software decide what happens next.
Losses describe fidelity changes
A loss says the output differs from a requested or source property in a way the operation recognizes. Losses are especially important for conversion, normalization, and compatibility work.
Useful loss dimensions include:
- content omitted;
- semantics flattened;
- editability reduced;
- appearance changed;
- metadata removed;
- interactive behavior removed;
- accessibility structure reduced;
- unsupported feature preserved only as an image or fallback.
A loss is not automatically unacceptable. A macro removed from an externally shared workbook may be intentional. A chart flattened to an image may be acceptable for archival PDF and unacceptable for an analyst’s editable deck. The caller’s loss policy decides.
That is why the result should return losses even when status is ok. The execution completed; the policy decision remains open.
Artifact identity binds the result to bytes
The artifact section should identify the exact output rather than only its location. At minimum, record:
- media type and intended extension;
- byte count;
- a cryptographic hash such as SHA-256;
- a storage or download reference with an explicit lifetime;
- the operation and request identifiers that produced it.
A URL can expire or point to replaced content. A hash lets a later reviewer verify whether the downloaded artifact is the same byte sequence the operation recorded. It does not prove the artifact is visually correct, safe, or approved. It proves identity under the hash function.
A receipt is evidence, not automatic approval
A receipt can bind the artifact hash to the operation name, implementation version, input digest, policy version, validator results, losses, timestamps, and actor or system authority. The W3C PROV-O recommendation provides a general model for entities, activities, agents, and provenance interchange; a document receipt can use a narrower domain-specific representation while preserving the same basic questions of what was produced, by which activity, from which inputs, and under whose authority.
Receipts need explicit limits:
- An unsigned receipt is a record, not tamper-proof evidence.
- A signed receipt proves only what the signer is authorized to attest.
- A hash proves exact-byte identity, not correctness.
- A validation result applies to the named validator and version.
- An approval applies only if the approver, policy, and exact artifact are bound.
An illustrative result envelope
{
"status": "ok",
"operation": "pptx.render",
"requestId": "req_01…",
"diagnostics": [],
"losses": [],
"artifact": {
"mediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"bytes": 48231,
"sha256": "…",
"download": { "href": "…", "expiresAt": "…" }
},
"receipt": {
"artifactSha256": "…",
"inputSha256": "…",
"policyVersion": "release-policy-v3",
"validationState": "structural-pass",
"releaseState": "candidate"
}
}
This is a design example, not the live Runstamp response schema. Retrieve the current operation contract before implementation.
Model the lifecycle after the operation
The operation result should not silently promote an artifact from generated candidate to released deliverable. A sensible lifecycle is:
- operation returns a candidate artifact and evidence;
- automated gates interpret diagnostics and losses;
- a reviewer inspects the exact bytes where required;
- an authorized action approves the same hash;
- release records the destination and final policy state.
If any step regenerates or modifies the file, the hash changes and the approval must not follow automatically.
Runstamp’s operation-result contract defines the current product boundary. The evidence model separates byte identity, structural validity, appearance, and destination acceptance. For conversion design, the loss-ledger research draft explains why fidelity observations must survive a technically successful operation.
Verify the envelope with controlled failure cases
Result-envelope tests should exercise branches that ordinary success fixtures miss. Begin with a known-good request and record the complete result. Then change one condition at a time: invalidate an input field, remove a runtime binding, exceed a resource limit, force a recognized fidelity loss, mutate output bytes after validation, and retry the same logical request. Each case should change only the relevant plane of the envelope.
An input failure should produce a typed error and no deliverable artifact. A fidelity loss may still produce an artifact, but the loss must remain visible and policy must decide whether release can continue. A post-validation byte mutation should invalidate the earlier artifact hash and any receipt or approval bound to it. A same-key retry should return the existing logical result or a clear in-progress state rather than create an unrelated second artifact.
Use known-bad controls for the evidence layer as well. Supply a receipt with the wrong artifact digest, a validation record from an older policy version, and an expired download reference. The consumer should reject those records without relabeling the operation itself as failed. Execution may have completed while evidence or delivery is no longer acceptable.
Finally, test serialization across every supported client surface. SDK, CLI, MCP, webhook, and dashboard representations should preserve stable status, error, loss, artifact, and receipt fields. A concise display may omit detail, but it must not turn completed_with_losses into an unqualified success or present a generated candidate as released. These controls make the envelope an enforceable contract rather than a documentation convention.
Review checklist
Before shipping a document result schema, confirm that:
- status does not hide recognized losses;
- errors have stable codes, stages, and retryability;
- diagnostics name their source and locator;
- artifacts carry media type, size, hash, and retention behavior;
- receipts state their signer and evidence limits;
- candidate, approved, and released are separate states;
- clients cannot approve one hash and download another.
A result envelope should make ambiguity expensive to introduce and easy to detect.
Keep the document workflow in your product.
Pick an operation, run it on a real file, then embed review and release where your customers work.