Skip to main content
Goal: Get one real model answer for your organization, with a record of the run and what it cost. This page continues Set up with the CLI, which ended with a free test run. 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. What this does not finish. A completed run proves that this saved model answered a paid request. It does not move your setup application past echo_proved, and its receipt does not confirm which model OpenRouter actually ran. Step 5 says what the receipt does confirm.

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 finished Set up with the CLI, so you already have:
  • an organization approved for the private preview;
  • an organization API key in an approved secret store, available as SOLVERAPI_API_KEY;
  • a setup application at echo_proved: you fetched the receipt for its test run. A test run (the API calls it Echo) has no platform fee and no model cost.
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.
You do not run millwork tenant start again on this page. Without --template starter, that command uses its default setup, which needs a model Millwork provides. With today’s catalog it stops with pool_not_certified and creates nothing. The steps below call the API directly.
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 sums them. Neither includes the platform fee.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.