Skip to main content
An action that spends credits will not run in a single call. The first call tells you what it would do and runs nothing; the second, carrying a confirmation id back, is what runs it. There is no single-call version, and no header or argument turns one on. That is the same rule the product follows on screen — nothing spends on an assistant’s own judgement (How approvals work). Over the API, the confirmation id is what a person’s yes looks like. Today the action on this shape is images.generate. Any action that spends takes the same two-call form; the reference says so on each one.

The round-trip

These two calls are one worked example, run start to finish. They assume your key is in an environment variable — see Quickstart if you have not made one yet.

Call 1 — ask what it would do

Send the request without confirmation_id.
Read three fields:
  • status is confirmation_required and run_id is null — nothing ran.
  • request_summary is one sentence describing what would be made. It is written for a person to read, so it is the thing to put in front of whoever is approving.
  • confirmation_id is the token for the request you were just shown.

Call 2 — confirm it

Send the same request again with the id added.
status is dispatched and run_id names the run. The work is under way and the images land on the board you named.

What the id is bound to

The confirmation id stands for the request you were shown, not for the action in general. Three properties follow, and they are worth knowing before you build against it. It is single use. Send a consumed id again and the call is declined:
It expires. About thirty minutes. The same confirmation_invalid answer covers an expired id, an id that was never issued, and one that belongs somewhere else — deliberately one answer, so the code cannot be used to probe for valid ids. Changing the arguments on call 2 does not change the run. If you confirm with a larger count than you proposed, what runs is what you confirmed — the reply comes back carrying the original numbers. The id carries the approved request with it, so the second call cannot quietly enlarge the first.
Do not treat call 2’s arguments as the source of truth. Build your integration so the thing a person approved is the thing that is sent — and check the count and aspect_ratio on the dispatched reply if you need to be sure what ran.

Recovering from a refusal

Everything on this page answers 200. Branch on ok, never on the status code — a declined action is a successful HTTP response carrying a reason. The full list is on Errors and refusals.

A pattern that works

1

Propose, and stop

Call without confirmation_id. Store the confirmation_id and the request_summary together.
2

Put the summary in front of a person

request_summary is one plain sentence and is written for exactly this. Show it; do not re-describe the request yourself.
3

Confirm within the window

Send the id back on the second call. If more than about half an hour has passed, propose again rather than retrying — an expired id cannot be revived.
4

Record what ran

Log the run_id and the working_in block beside it. It is the fastest way to catch an integration quietly spending in the wrong workspace.

Checking the balance first

credits.balance takes no workspace — credits belong to the account, not to a single workspace — and is worth calling before an unattended job spends.
A job that stops for want of credits is easier to prevent than to notice. See Recipes for the other calls worth wiring into an integration.