Skip to main content
A run is one task you send to Millwork; the API calls it an execution. A completed live run gives you two records. Use the result in your application: it holds the model output. Keep the receipt as the record of what ran: it never includes the prompt or the model output. Every run that reaches a final status leaves a receipt. Only a completed live run has a result. A test run (the API calls it Echo, mode: "echo") does not call a model, so it has no result, no platform fee, and no model cost. Failed, cancelled, and expired runs have no result either. This diagram shows which record each run leaves behind.

Result

Fetch a result only after a live run reaches completed:
A 404 means the run is not complete, produced no result, or the result expired. When retention_expires_at contains a date, that is the result’s expiry time. If it is null, the API has not reported an automatic expiry. For a run on a catalog model, inspect the model requested and the model reported by the provider:
requested is what Millwork asked for. resolved is what the provider or gateway reported. billed_by is customer when your provider account was used and millwork when Millwork provided the model. For a model saved directly with a provider model ID, model_provenance is null. Its saved name does not establish which model the provider actually ran. How model routing works explains this distinction.

Receipt

A receipt records the run’s outcome, selected saved model, recorded usage, checks, and any follow-up action. Completed live runs on catalog models also record the requested and provider-reported model details. Test runs call no model. The receipt does not copy the prompt or output. The receipt records model usage in cost and totals.usd. It reports the platform fee separately in totals.platform_fee_usd, after any refund. The fee is zero for a test run or when Millwork refunds a run that failed before any model attempt. Read the run’s events when you need to follow individual model attempts; the receipt does not list or count them. A run has one part today, so slices holds one entry. Splitting a task across several models is planned.
The values above are illustrative, not model prices. Customer content is absent.

Why an output check passed or failed

The receipt records what the output check found. An output check is the check applied to the run’s output; the API calls it a verifier. The receipt keeps its result in slices[0].verifier:
  • is_correct says whether the output passed the check.
  • quality_score is a separate score from 0 to 1. A high score does not mean the output passed.
  • anchor_results lists the check’s named anchors, when the check reports them. A named anchor is one rule the check tested, such as a required field being present. Each is true when the output met the rule and false when it did not.
Here the check rejected the output because price_is_positive_number is false, even though the quality score is high. The receipt page in the dashboard shows the same anchors, failed ones first. A check that reports no anchors shows none. No anchors does not mean every rule passed: only is_correct says whether the output passed.

The receipt has no verdict

NOT CHECKED or an absent boolean verdict is not a rejection. Read the run status and the receipt’s verification_checks to see whether your customer check was attempted. A run may still be queued or running, or it may end before the check is attempted. If an attempted customer check records technical_failure, read its reported failure. Correct that cause, then make a fresh remote observation before deciding whether to submit another paid task: millwork verifier test --verifier-id "<verifier ID>" --idempotency-key "<new request key>" --json. Reuse that key only to recover the same test. Do not replace a working credential based only on an absent verdict. The original run and receipt remain the record of what happened. If you did not name an output check, the basic check records one anchor, non_empty_output. It confirms only that output is present, not that the answer is right. Anchor names come from your check and appear on the receipt. Keep customer values out of them.

What to store

  • Store the result only as long as your application needs it.
  • Keep the receipt when you need a record without the prompt or model output. Check how long your plan keeps receipt details.
  • Keep the run ID (execution_id) so you can connect status, result, receipt, and support context.

How long Millwork keeps receipts

Millwork removes receipt details according to your organization’s plan tier. Read your tier from quota_tier in GET /v1/account. The time counts from when the run was created, not from when it finished. Millwork first removes the details recorded in run events, such as the route, model usage, and check results, then deletes those events after the second period. The run ID and final status can remain available longer while related records are retained. GET /v1/receipts/{executionId} returns 404 once the run record is also deleted. Deleting your organization can remove details sooner. The receipt period is not the result’s expiry. The result has its own expiry in retention_expires_at. Save each receipt you need before detail removal starts. Save recent receipts shows how to export them.

Final outcomes

A run can end as completed, failed, cancelled, or expired. Request the result only after a live run reaches completed. For every other final status, read the run, events, and receipt to see what happened. The platform fee is charged when Millwork accepts a live run, whatever its final status. Read when the platform fee is charged. No result? Follow the recovery steps in Errors and retries.