Skip to main content
The Millwork API is a REST API at one base URL. You authenticate with a Millwork API key for your organization, submit a run (one task; the API calls it an execution), and follow it to a final status. Every final run has a receipt; only a completed live run has a result with model output. Every live run has a platform fee, charged when Millwork accepts the run; model usage is a separate cost. This page covers what every request shares. Each endpoint page lists its exact fields. For output checks, start with the REST lifecycle reference. Its operation list comes from the generated OpenAPI file. The verifier-dock contract defines the separate request and response between Millwork and your check endpoint.
Using a coding assistant? Choose Copy page or View as Markdown above, then follow Use a coding assistant. The OpenAPI field names on this site are the exact HTTP contract.

Base URL

Send and receive JSON. Set Content-Type: application/json on every request that has a body.

Authenticate with an organization API key

Send your Millwork API key as a bearer token in the Authorization header. Use an existing saved key, or create one for the intended organization in Millwork dashboard → API keys. Set MILLWORK_API_KEY as shown in Make your first API call.
Expected result: 200 with your organization’s display_name, quota, and balance. The key itself is never returned. A missing or rejected key returns 401. Check the bearer header and key configuration. Replace an invalid or revoked key before retrying. A dashboard session is not an API credential. The cookie a person receives by signing in to the dashboard works only in a browser. Do not send it from an application.

Send a request key so a retry does not start work twice

Every POST /v1/executions requires an Idempotency-Key header. This is your request key: a unique string you choose for each new run. If the connection drops before you read the response, send the same request again with the same key and the same body. Millwork returns the original run instead of starting a second one. Use a new key for new work. Reusing a key with a different body is refused; Errors and retries lists the error code.

Live runs are asynchronous

Submitting a live run returns 202 with an execution_id. Its status is queued when a model fits, or already failed when none does. Millwork records accepted as the first event and charges the platform fee at acceptance. If no model fits, it returns the fee and quota automatically. For a queued run, poll links.status from the submit response (GET /v1/executions/{executionId}) until the status is completed, failed, cancelled, or expired. Fetch the result after completed and the receipt for every final status. Read a failed run’s events for the reason. Do not submit the task again while the first run is queued or running. Run lifecycle explains each status and when you can cancel. A test run (mode: "echo") finishes during submission without calling a model. Its successful response already has status completed. It has no result, platform fee, or model cost, but it still counts toward your quota. Fetch its receipt to check the integration.

Errors are JSON problems

API errors use application/problem+json with type, title, status, and instance. Optional detail explains the problem; errors can give field and message pairs for invalid request fields. The error code is the last path segment of type. Rate and quota errors also carry retry_after_s and a Retry-After header. Read Errors and retries before you write automatic retries.

What a request costs

A live run has a platform fee, charged when Millwork accepts it, plus model usage. Your provider bills the usage when the run uses your provider key. Millwork deducts recorded model usage from your credit when it provides the model. Review the configured platform fee separately from the model-usage allowance before approving a live request. A test run (mode: "echo") does not call a model, so it has no platform fee and no model cost. Read Model access and billing.

Make your first API call

Check authentication with a free test run.

Run a model

Submit a live task and read the result.