> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://infonite.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://infonite.dev/_mcp/server.

# On Action Required

POST 

Fired when the source asks for something only your customer can provide.

A one-time code sent to their phone, a push notification to confirm, a security question, an extra field the engine could not know in advance. The execution is **paused, not broken**, and it is waiting for you.

**This is the one event you cannot replace with patience.** The others tell you about a run that is progressing on its own; this one is a run that will expire unless you answer, and the window is the institution's, not ours. The alternative is polling the state every few seconds for every execution in flight.

[Execution State](api:GET/executions/handler/v1/\{execution_id}) answers `423` and carries `form_schema` — the exact fields to collect, with `x-meta.timeout` saying how long you have — and `action_required_expires`, the deadline as a date.

Ask for exactly what the form declares, nothing more. The values travel like any other secret: you may send them encrypted.

[Resume an Execution](api:PUT/executions/handler/v1/\{execution_id}) hands the answer over and the engine carries on from where it stopped.

A strong-authentication challenge: a code, a push confirmation, a signature.

Anything else the engine needs and could not know in advance — a security question, a contract to choose.

**`producer` says who is asking**: `engine` while the login is being resolved, or the feature's own code — `accounts_read`, say — when one feature raised the challenge on its own.

**Move fast.** A code issued by a bank expires on the institution's timetable, usually a couple of minutes. Past the deadline the execution is aborted with `ACTION_TIMEOUT` and has to be started again.

**This event only happens when you asked for it to be possible.** An execution started with `customer_interaction_available: false` never pauses: if the source raises a challenge, the execution ends instead.

Reference: https://infonite.dev/api-reference/direct-executions/direct-executions-api/webhooks/webhook-direct-executions-action-required

## Request

### Payload

- `app_id` (string, required) — The application this execution was launched with — the one your secret belongs to. Worth keeping when your product uses more than one, a sandbox and a production app being the usual case: every record and every event we send carries it.
- `customer_id` (string, required) — The `customer_id` you supplied when the execution was initialised, returned as you sent it — so an answer can be routed to the right case with no lookup on your side.
- `execution_id` (string, required) — The execution this belongs to — the value you poll for the state and address every results endpoint with. Always present here: an event exists because an execution does.
- `event` ("action_required", required) — The event type: `action_required`.
- `date` (string, required) — When the event was raised, in UTC. Deliveries can arrive out of order — a retry is delivered after whatever came next — so order your own records by this, not by arrival.
- `customer_available` (boolean, required) — Whether the execution was started as one a person can answer (`customer_interaction_available`). When `false`, a challenge from the source cannot be solved and the execution ends instead of waiting.
- `status_reason` (enum or enum or enum or enum or enum or enum or enum or enum or enum or enum or enum, required) — The precise reason for the state at the moment of the event — one of the execution reasons, or a feature's own when `producer` names a feature. Branch on this and not on the message: it is a stable code. [Every reason by family](/direct-executions/lifecycle#every-reason-by-family).
- `session_id` (string, optional, nullable)
- `external_execution_id` (string, optional, nullable)
- `locking_hash` (string, optional, nullable)
- `event_class` ("ExecutionEvent", optional, default: ExecutionEvent) — Payload class discriminator — always this value for an execution event. If the same endpoint also receives flow events, branch on it first.
- `producer` ("engine" or enum, optional, default: engine) — Who raised it: `engine` for the execution itself — the login, typically — or the feature's own code when a single feature is what needs something. An `action_required` from the accounts reader says `accounts_read`, so you know what is being asked for before reading the form.
- `status_message` (string, optional, nullable)
- `data` (map from string to any, optional, nullable)