> ## 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.

> ## Agent Instructions
> Authenticate with the raw API key in the Authorization header. Never add a Bearer prefix.
> Use the sandbox base URL https://api.test.doola.com and a dk_test_ key in examples unless the user asks for production.
> Send an Idempotency-Key header on POST /v1/partner/customers, POST /v1/partner/companies, POST /v1/partner/companies/import, POST /v1/partner/companies/{companyId}/services and POST /v1/partner/companies/{companyId}/documents. No other endpoint takes one.
> Every response is wrapped as {payload, error}. Read fields from payload and branch on error.code, never on the message.
> Drive formation progress from webhooks plus a reconciliation sweep, never a polling loop.
> Embedded SDK (@doola/js): the dk_ key stays on the server and mints customer sessions; the browser gets only a pk_ key and the session. onFormed carries only companyId and can fire more than once. Before charging, read the company with the dk_ key, require formationSubmissionStatus AWAITING_PAYMENT, check the owner's email, and price on the server. Then POST payment-confirmed, which answers 200 with an empty body, and replace the SDK element with a new doola.create() (never append a second one).
> The doola Formation MCP server at https://mcp.doola.com is for founders forming their own company with their own doola account. Partners integrate the Partner API or the Embedded SDK. The /mcp endpoint on this docs site only searches these docs.
> For a full capability summary with the rules above, read https://docs.doola.com/skill.md.

# Add a service

> Order an EIN for a company that already exists, whether doola formed it or you imported it.

You can order a service for a company after it exists. Today that is the EIN: `EinCreation` is the only service you can add. `Formation` and `RegisteredAgent` exist only as part of forming a company, and `AiCofounder` comes with every company.

Use it when a company was [created without an EIN](https://docs.doola.com/api/company-services.md#a-company-without-an-ein), or when you [imported](https://docs.doola.com/api/import-company.md) a company that has no EIN yet.

## Adding the EIN

```bash theme={null}
curl https://api.test.doola.com/v1/partner/companies/{companyId}/services \
  -X POST \
  -H "Authorization: dk_test_your_api_key_here" \
  -H "Idempotency-Key: add-ein-31pLD0Tq2lm2FsgRBoHv4x3BpzZ" \
  -H "Content-Type: application/json" \
  -d '{
    "services": [
      { "service": "EinCreation", "variant": "Standard" }
    ]
  }'
```

| Field | Values | Notes |
| - | - | - |
| `services` | Array, at least one entry | Required. Each service may appear once |
| `services[].service` | `EinCreation` | Case-sensitive |
| `services[].variant` | `Standard`, `Expedite` | Optional. `Standard` is the default. `Expedite` requests the [expedited EIN](https://docs.doola.com/api/expedited-ein.md), available only when no member, executive member or responsible party supplies a valid SSN |

The call is all or nothing: if any service cannot be added, none is.

The response is `201` with every service on the company:

```json theme={null}
{
  "payload": {
    "doolaCompanyId": "31pLD0Tq2lm2FsgRBoHv4x3BpzZ",
    "services": [
      { "name": "Formation", "variant": "NONE", "status": "InProgress", "subStatus": "WaitingForRaToSucceed" },
      { "name": "RegisteredAgent", "variant": "NONE", "status": "NotStarted", "subStatus": "WaitingForFormation" },
      { "name": "AiCofounder", "variant": "NONE", "status": "Active", "subStatus": null },
      { "name": "EinCreation", "variant": "NONE", "status": "NotStarted", "subStatus": "WaitingForFilingServiceToComplete" }
    ]
  },
  "error": null
}
```

A standard EIN reads `variant: "NONE"`. The status shown is the one the EIN was added with. Read the company for its current status.

## When the EIN starts

| The company | What happens |
| - | - |
| doola is still forming it | The EIN waits at `NotStarted` / `WaitingForFilingServiceToComplete` and starts when formation completes, as it does for a company created with an EIN |
| doola has formed it | The EIN starts right away |
| You imported it and doola has not verified the import yet | The EIN waits at `NotStarted` / `WaitingForFilingServiceToComplete` and starts when the import is verified. See [Import a company](https://docs.doola.com/api/import-company.md#ordering-an-ein) |
| You imported it and doola has verified the import | The EIN starts right away |

Once the EIN starts, the usual EIN flow applies. A founder without a valid SSN signs an SS-4: the company's `signatureRequirements` lists it from the moment you add the EIN, so read the company and follow the [signing guide](https://docs.doola.com/api/non-us-formation.md). Watch `company_ein_issued` and `document_einletter_uploaded` for the result, as for any other company. No webhook fires for the addition itself.

## Idempotency

`Idempotency-Key` is required. Retrying with the same key and body returns the first response and adds nothing twice. If the call fails, the key is released, so fix the request and retry with the same key. A new key for an EIN that was already added answers `409 E_SERVICE_ALREADY_ADDED`.

## Errors

Branch on `error.code`, never on the message.

| HTTP | Code | When |
| - | - | - |
| 400 | `E_VALIDATION_FAILED` | The `services` list is missing, empty, names a service that cannot be added (`Formation`, `RegisteredAgent`, `AiCofounder` or an unknown name), lists a service twice, or carries a `variant` other than `Standard` or `Expedite`. `error.fields.services.code` is `E_SERVICE_SELECTION_INVALID`, and the message names the rule |
| 400 | `E_MALFORMED_JSON` | The request has no body, or the body is not JSON |
| 400 | `E_IDEMPOTENCY_KEY_REQUIRED` | The `Idempotency-Key` header is missing |
| 400 | `E_EXPEDITED_EIN_NOT_ELIGIBLE` | `Expedite` was requested, but a member, executive member or responsible party supplies a valid SSN. Retry with `Standard` |
| 404 | `E_NOT_FOUND` | No company with this ID belongs to your tenant |
| 409 | `E_COMPANY_NOT_ACTIVE` | The company's formation was cancelled or failed |
| 409 | `E_SERVICE_ALREADY_ADDED` | The company already has this service |
| 409 | `E_EIN_ALREADY_ISSUED` | The company already has an EIN number |
| 409 | `E_IDEMPOTENCY_KEY_REUSED` | The key was used before with a different body |
| 409 | `E_IDEMPOTENCY_IN_PROGRESS` | A request with the same key is still running |

Once the body is valid, doola checks the company in this order and reports the first failure: `E_COMPANY_NOT_ACTIVE`, `E_SERVICE_ALREADY_ADDED`, `E_EIN_ALREADY_ISSUED`, then `E_EXPEDITED_EIN_NOT_ELIGIBLE`. A refused request changes nothing.

See [Errors](https://docs.doola.com/api/errors.md) for the response envelope and the global codes any endpoint can return.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.