Skip to main content
Formation is asynchronous. Rather than polling, subscribe to webhook events to learn when a formation progresses and when documents become available.

Setup

1

Get your signing secret

doola provisions your tenant and generates your webhook signing secret. It is shown once at creation, so store it securely. Email engineering@doola.com to get set up or to rotate it.
2

Configure your endpoint

Set your webhook URL in the doola Partner Portal. The URL must be HTTPS. Each environment has its own tenant, so configure sandbox and production separately.
To see real deliveries end to end without waiting on an actual formation, use the Sandbox playground: it completes the formation and EIN milestones on demand and fires the events below through the normal pipeline.

Verifying the signature

doola sends a POST with an X-Doola-Signature header: an HMAC SHA256 hex digest of the raw request body, keyed with your webhook secret. (HTTP header names are case-insensitive; many frameworks lowercase them to x-doola-signature on the way in.)
Always use a constant time comparison (timingSafeEqual or compare_digest). Plain string equality is vulnerable to timing attacks.

Payload

Every delivery is a POST with the same envelope. Only eventPayload changes shape from event to event.

Events

You may occasionally receive duplicate document_* events for the same document, for example after doola re-issues a document. Handle uploads idempotently using documentId.
The four SS-4 events fire only for non-US founders, who must sign an SS-4 before the IRS issues the EIN. The three form8821 events mirror the three SS-4 signing milestones — completed, uploaded, and reminder — and fire only for a non-US founder who also requested an expedited EIN, where a signed Form 8821 authorizes doola to retrieve the EIN letter from the IRS. In each pair, signature_*_completed fires the instant the founder signs; document_*_uploaded fires once the signed PDF is stored and downloadable. signature_ss4_reset has no Form 8821 counterpart: it fires only when a non-US founder had already signed and a later name change voided that signature. See Non-US founders for the full flow.
company_ein_issued and document_einletter_uploaded both signal EIN issuance, at two distinct moments: company_ein_issued fires when doola records the EIN on the company (fetch the company to read the ein field), and document_einletter_uploaded fires once the IRS confirmation letter is stored and downloadable. They arrive independently, so do not assume an order. company_ein_issued fires only on the first issuance; a later correction to the EIN value does not re-fire it.
company_name_options_required and signature_ss4_reset announce a required action — something doola needs from you before that company’s formation can continue. They are the only events that block progress until you act. Both carry a requiredActionId: key your records on it and read the action against it. Only company_name_options_required is answered through the resolution endpoint; an SS-4 reset closes itself once the replacement signature completes. An action you never received, because your endpoint was down, stays open and is readable from the open list.
The two governance-document events are entity-type specific: document_corporatebylaws_uploaded fires for CCorp companies only, and document_operatingagreement_uploaded fires for LLC companies only. doola generates the governance document shortly after the Articles of Organization are processed, so each event typically arrives soon after document_aoo_uploaded.

Example payloads

A sample delivery for every event. Within eventPayload, only the fields relevant to that event are present; inapplicable fields are omitted entirely rather than sent as null, so parse defensively. eventPayload itself is null only for partner_webhook_disabled.

Payload fields

doolaCompanyId is on every company- and document-scoped payload. The rest appear only on the events noted below:

Delivery and retries

If your endpoint does not return a 2xx, doola retries up to 5 times: at 1 minute, 15 minutes, 1 hour, 12 hours, and 24 hours after the previous attempt. Treat every delivery as at least once. After all retries fail, doola automatically disables your endpoint and sends a final partner_webhook_disabled event. Fix your endpoint and re-enable it in the Partner Portal. Re-enabling is a deliberate partner action, so you confirm the endpoint is healthy before traffic resumes. Every delivery attempt (timestamp, event, HTTP status, attempt number) is visible in the Partner Portal.