> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doola.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox playground

> Complete formation and EIN issuance on demand in sandbox, and receive every webhook without waiting on the state or the IRS.

In production, two formation milestones happen on timelines you cannot control: the state confirms the formation, and the IRS issues the EIN. The sandbox playground gives you an endpoint for each, so you can drive a test company through the full lifecycle and receive every webhook on your endpoint in minutes, with no doola involvement.

<Info>
  **Sandbox only.** The playground exists only on `https://api.test.doola.com`; the routes do not exist in production. Authenticate with your sandbox API key (`dk_test_...`), like any other request.
</Info>

## The two milestones

| Endpoint                                                                 | Simulates                          | Webhooks fired                                                                                                                                                    |
| ------------------------------------------------------------------------ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /v1/partner/playground/companies/{companyId}/formation/complete`   | The state confirming the formation | `company_formation_completed`, `document_aoo_uploaded`, plus `document_corporatebylaws_uploaded` for a CCorp or `document_operatingagreement_uploaded` for an LLC |
| `POST /v1/partner/playground/companies/{companyId}/eincreation/complete` | The IRS issuing the EIN            | `company_ein_issued`, `document_einletter_uploaded`                                                                                                               |

Each endpoint runs the same operations production runs when the real milestone happens. Webhooks are emitted by the normal pipeline: signed, filtered by your event subscriptions, retried on failure, and visible in the Partner Portal delivery logs. Documents go through the real upload flow, and service statuses advance exactly as they do in production. The playground never fabricates an event, so what you build against it holds in production.

## Walkthrough

You need a sandbox API key and a webhook endpoint configured in the Partner Portal (see [Webhooks](/api/webhooks#setup)). If you just want to watch events arrive before wiring up your backend, a request inspector such as webhook.site works fine as the endpoint.

<Steps>
  <Step title="Create a customer and a company">
    Use the regular [Create customer and Create company](/api/introduction#your-first-call) calls with your sandbox key. Shortly after the company is created, `company_formation_submitted` arrives at your webhook endpoint and `formationSubmissionStatus` becomes `SUBMITTED`. Nothing playground-specific yet: that event follows the normal create flow, in sandbox as in production, which is why the playground has no endpoint for it.
  </Step>

  <Step title="Complete the formation">
    Trigger the "state confirms formation" milestone:

    ```bash theme={null}
    curl https://api.test.doola.com/v1/partner/playground/companies/{companyId}/formation/complete \
      -X POST \
      -H "Authorization: dk_test_your_api_key_here"
    ```

    ```json theme={null}
    {
      "payload": {
        "doolaCompanyId": "31pLD0Tq2lm2FsgRBoHv4x3BpzZ",
        "service": "Formation",
        "triggeredEvents": ["company_formation_completed", "document_aoo_uploaded"]
      },
      "error": null
    }
    ```

    Your endpoint receives `company_formation_completed` and `document_aoo_uploaded`. On the company, `formationFilingDate` is set, the Articles of Organization appear in the documents list, and the **Formation** service advances to `Completed`. `triggeredEvents` additionally lists the entity type's governance document event — `document_corporatebylaws_uploaded` for a **CCorp**, `document_operatingagreement_uploaded` for an **LLC**: doola generates the governance document shortly after the Articles are processed, and the event and document follow, exactly as in production.
  </Step>

  <Step title="Complete EIN creation">
    Trigger the "IRS issues the EIN" milestone:

    ```bash theme={null}
    curl https://api.test.doola.com/v1/partner/playground/companies/{companyId}/eincreation/complete \
      -X POST \
      -H "Authorization: dk_test_your_api_key_here"
    ```

    ```json theme={null}
    {
      "payload": {
        "doolaCompanyId": "31pLD0Tq2lm2FsgRBoHv4x3BpzZ",
        "service": "EinCreation",
        "triggeredEvents": ["company_ein_issued", "document_einletter_uploaded"]
      },
      "error": null
    }
    ```

    Your endpoint receives `company_ein_issued` and `document_einletter_uploaded`. On the company, `ein` is populated with the test value `12-3456789`, the EIN letter appears in the documents list, and the **EinCreation** service advances to `Completed`.
  </Step>

  <Step title="Verify">
    Fetch the company and confirm `formationFilingDate`, `ein`, and the `services[].status` values; list its documents and download each one; and check the delivery log in the Partner Portal, which records every attempt with its HTTP status.
  </Step>
</Steps>

Call the endpoints in this order to mirror the real sequence. The order is not enforced, but a formation that gains an EIN before it is formed is not a state production will ever show you.

## What to expect

* **Statuses advance asynchronously.** The Formation and EinCreation `status` values (see [Company services](/api/company-services)) are derived by doola's systems moments after each call, not atomically within the response. React to the webhooks, or allow a short delay before asserting on the company, rather than asserting synchronously.
* **Documents are placeholders.** The Articles of Organization and EIN letter are placeholder PDFs, but they flow through the real pipeline: list them and fetch download URLs exactly as in production. A CCorp's Corporate Bylaws and an LLC's Operating Agreement are generated from the company's real formation data, exactly as in production.
* **Test values are fixed.** The EIN is always `12-3456789`, and `formationFilingDate` is the date you made the call. A test note also appears in the company's `adminNotes`.
* **Repeat calls re-fire webhooks.** Calling a playground endpoint again re-runs the milestone: `company_formation_completed` fires again, and the document events fire again with a fresh `documentId`. That makes repeat calls a handy way to re-test your handler and its idempotency. The exception is `company_ein_issued`, which fires only on the first issuance, exactly as in production — a repeat `eincreation/complete` therefore lists only `document_einletter_uploaded` in `triggeredEvents`.

## What the playground does not simulate

The playground models the standard US-founder flow. It has no endpoint for:

* `company_formation_failed` and `company_filing_date_updated`
* `document_mail_uploaded` (business mail)
* The non-US founder signing milestones (the `signature_*` and SS-4 / Form 8821 document events); see [Non-US founders](/api/non-us-formation)

## Errors

| HTTP | Code                  | Meaning                                                                                                                              |
| ---- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| 404  | `E_COMPANY_NOT_FOUND` | No company with this ID exists for the authenticated partner. The playground never reveals whether the ID belongs to another tenant. |

The [global error codes](/api/errors#global-error-reference) apply as usual. In production the routes themselves do not exist, so any call there returns a plain 404.
