Skip to main content
Goal: Get one real model answer for your organization, with a record of the run and what it cost, using the API directly. For a guided terminal journey, use Set up with the CLI. Here you pay for one live run: a run that calls a model. A run is one task you send to Millwork; the API calls it an execution. The CLI and API call an organization a tenant. You are done when: the run’s status is completed, final_text in its result holds the model’s answer, and its receipt names the saved model you asked for and the usage the provider reported. A saved model is a model your administrator added to your organization; the API calls it an arm. A receipt is the record of a run without its prompt or output. A completed run proves that this saved model answered a paid request. Its receipt identifies the saved model and recorded usage; for this directly saved model, it does not confirm which model OpenRouter actually ran. Step 5 explains the receipt fields.

What this run costs

  • Platform fee: charged when Millwork accepts the run, not when it completes. If you cancel, the fee and the quota count stay, and Millwork does not stop a model call that is already running.
  • Model usage: this run uses a saved model on OpenRouter. OpenRouter bills the provider account your administrator identified, under that account’s terms. Millwork bills nothing for the usage.
Millwork returns the fee and the quota count automatically in one case: it failed the run before any model attempt started. That happens when no model could serve it, the output check (the API calls it a verifier) was unavailable, or the selected model was not ready. Read Model access and billing for every outcome. This diagram shows the requests you send with a request key (the value you put in the Idempotency-Key header), the moment the fee is charged, the model call whose usage appears on the receipt, and the two records you fetch.

Before you begin

You need an organization with private-preview access and an organization API key in your secret store, available as SOLVERAPI_API_KEY. If you followed Set up with the CLI, you can use the same organization and key here. These steps submit another paid run through the API. SOLVERAPI_API_KEY holds the same organization key that the other REST guides call MILLWORK_API_KEY. This page keeps the name you set during CLI setup. This page also needs:
  • A saved model your administrator approved. Your administrator saves one model on OpenRouter for this organization, confirms its status is ready, and gives you its id and the name of the provider account that pays for its usage. Millwork does not create that provider account or add credit to it; step 1 says what the administrator sends instead.
  • Credit and quota. Your organization needs Millwork credit for the platform fee, and room in your quota for one more live run. Your quota is the number of runs your organization may submit per calendar month (UTC), and how many may run at once. An owner can check both in the dashboard under Usage & spend. The provider account needs its own credit with OpenRouter.
  • curl and jq, in an empty working directory. The examples save the request, status, result, and receipt as files there. They never save your key.
The CLI guide completes setup and a first model answer in the terminal. This page is the direct API alternative for a saved model your administrator approved. You do not need to repeat CLI setup before following it.
1

Confirm the saved model

Ask your administrator for the exact id of the approved saved model. Do not pick a different saved model because it appears first in a list.
Expected result: provider is openrouter, kind is model, status is ready, and data_class_grants includes public. Keep ARM_ID; every later step pins the run to it.ready means the saved model’s configuration passed Millwork’s checks. It does not prove that the next provider call will succeed.
An administrator saves the model with POST /v1/arms and an organization API key. The request body is:
credential_ref names a provider key already stored with Millwork for this organization. It is a reference, not the provider key itself. This path requires an existing reference from your administrator. If your organization does not have one, ask support to arrange secure setup before continuing. Send the provider name and organization ID, never the key.Leave out endpoint and model_deployment_id for this kind of saved model. The response returns arm_id, status, and status_reason. Saving a model does not call it and does not add credit. If the response is lost, list the saved models with GET /v1/arms before saving the same model a second time.
2

Review and submit one paid run

Write the request to a file first, so you can review it before anything is charged. This task asks for one word and pins the run to your saved model:
What each field does:
  • mode: "live" calls a model. A test run (mode: "echo") would not.
  • data_classes: ["public"] allows only public information in this task.
  • max_cost_usd is the model-usage budget. Once recorded spend reaches it, Millwork starts no further provider calls. A call already started can finish above this amount. The platform fee is separate.
  • max_runtime_s is the run’s time limit.
  • on_eval: [] means Millwork does nothing more on its own after the output check, not even a switch to another saved model.
  • routing.required_arm_id pins the run to your saved model.
  • There is no verifier_id, so Millwork applies its built-in output check. A basic check confirms only that output is present. It does not judge whether the answer is right.
If an assistant runs these steps for you, it must get your explicit approval before it sends the next request. Approving setup or a provider connection is not approval for this run.Choose one request key for this run and keep it with the request file. Millwork reads it from the Idempotency-Key header. A retry with the same key and the same body returns the same run instead of starting the work twice.
Expected result: the jq line prints execution_id, "status": "queued", and "mode": "live" from the 202 response. On failure, curl reports the HTTP status and the problem body lands in the file. Millwork charged the platform fee at this moment. 202 means Millwork accepted the run, not that it completed. Keep execution_id; every status, result, receipt, and support request uses it.If the response is lost, send the same body with the same request key. Do not submit a second run to find out what happened to the first; both would be charged.
3

Wait for a final status

Read the id from the saved response, then read the run’s status:
While status is queued, running, or progress, repeat only this request, at least two seconds apart. Stop after 90 seconds and keep the id; a run still in progress is not lost. Do not submit again. Run a model shows a complete polling example with its own environment setup.Expected result: status is completed. The other final statuses are failed, cancelled, and expired. For those, skip to If it fails.
4

Read the answer

Fetch the result, the model’s answer, only after completed:
Expected result: final_text holds the model’s answer, in this example the word ok. retention_expires_at is when the result stops being available, or null when Millwork has not reported an expiry. Copy the answer while you have it; the receipt never contains it.For this kind of saved model, model_provenance is null. Millwork did not record which model OpenRouter actually ran. Do not fill that in from the saved model’s name or from a catalog entry.
5

Keep the receipt

Fetch the receipt for every final status, including failed and cancelled:
Expected result: execution_id matches, mode is live, and content_policy is content_free. In each route, required_arm_id and selected_arm both equal your ARM_ID, and fallback_chain is empty. model_costs holds the tokens and model cost the provider reported, and totals.usd sums them. The receipt reports the platform fee separately in totals.platform_fee_usd, after any refund.The receipt confirms which saved model answered and the usage the provider reported. It does not confirm which model OpenRouter actually ran. Keep the receipt as your record; Results and receipts says what to store and for how long.To see your remaining Millwork credit:
This is your Millwork balance, not your OpenRouter balance, and it does not itemize this run. If your role cannot see the balance, ask an organization owner. A missing value is not zero.

If it fails

Errors and retries lists every error code and what to send support without sharing a secret.

Next step

Run a model

Let Millwork choose from your catalog instead of pinning one saved model.