Skip to main content
Most of a formation runs without you. Occasionally it cannot: the state rejects every company name you submitted, or a document has to be signed again. When that happens doola raises a required action on the company, tells you over a webhook, and waits. A required action is the one thing in the Partner API that blocks on you. Until it is resolved, that company’s formation does not progress — so treat these events as work items, not notifications. This page covers what every required action has in common: how you are told, how to read them, and how to recover the ones you missed. Each kind has its own page for the part that differs — how you actually clear it.

New company names needed

FORMATION_NAME_OPTIONS_EXHAUSTED — the state rejected every name you submitted. You send replacements.

SS-4 signature needed again

FORMATION_SIGNATURE_SS4_RESET — a name change voided a signed SS-4. Your founder signs again.
A closed action is never reopened. If the same thing is needed again, doola raises a new action with a fresh requiredActionId. Key your records on requiredActionId, not on the company plus the code.

Anatomy

Every action carries a requiredActionId, an actionCode that says what is needed, and a reason written for a person to read. These are the three you build against: Full field list: Required action. For name rejections the reason usually names the exact names the state turned down. When doola could not capture them it falls back to a fixed sentence, All submitted company name options were rejected by the state. Submit new options.

Statuses

An action’s status is the last thing that happened to it. open tells you whether it still needs attention. resolved and rejected are terminal, and open is then false. Every other status means the action is still open.
submitted is not done. It means doola has your answer and is acting on it; for name options that means refiling with the state. Wait for the action to close before telling your user the matter is settled.

How doola tells you

Each code has its own webhook event, and both carry the same payload shape.
Delivery follows the standard webhook contract, so treat it as at least once and dedupe on eventId. An action doola never managed to deliver is still open and still blocking — see Reconciling.

Reading actions

Everything still open

One call, across every company you own. This is what a dashboard or a startup check should read.
Closed actions are excluded. total is the tenant-wide open count whatever page size you ask for, so size=1 is a cheap “is anything waiting on me?” check. size is capped at 100 — a larger value is clamped rather than rejected.

One company

A plain array under payload, unpaged, most recently changed first. Unlike the open list this one keeps resolved and rejected entries, which is what lets you tell “nothing was ever needed” apart from “something was needed and I missed it”.

One action, with history

Adds a history array: every step the action has been through, oldest first, including whether doola reached your endpoint and what you submitted.
submittedPayload appears on submitted steps only. It is a record of what you sent at that moment, not the company’s current state — read the company for that.

Reconciling

Webhooks can be missed — downtime on your side, or an endpoint doola disabled after repeated failures. An action left in delivery_failed is still open and still blocking that company, and no further webhook announces it. Guard against that with one call at startup and on a schedule:
Anything there you have no record of is work you missed. Compare total against what you received and page with page=1, page=2, and so on if you ever hold more than 100 open actions at once; for most tenants this is a single request no matter how many companies you have.

Testing

The sandbox playground cannot raise a required action today. To exercise the flow end to end in sandbox, ask doola to raise one on a sandbox company at engineering@doola.com — the webhook, the reads, and the resolution endpoint then behave exactly as they do in production. The reads are safe to build against meanwhile: a company with nothing outstanding returns an empty list.

Errors

Branch on error.code, never on the message. The 400-level codes below come from submitting a resolution; the 404s are returned by the reads as well. Checks run in a fixed order — body shape, company scope, action scope, actionCode match, resolvability, then whether the action is still open — so a request with more than one problem reports the first failure in that list. A closed SS-4 reset therefore answers 422, not 409. Anything that is not yours is a 404, never a 403 — a 403 would confirm the ID exists, which is enough to enumerate another partner’s companies. See Errors for the response envelope and the global codes that any endpoint can return.