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

# Imported company actions

> Handle IMPORT_DOCUMENTS_MISSING by uploading the missing documents, and IMPORT_INFO_REQUIRED by sending the corrections doola asks for.

Two required actions belong to [imported companies](https://docs.doola.com/api/import-company.md). Both are part of doola's review of the import, and both are announced by their own webhook. See [Required actions](https://docs.doola.com/api/required-actions.md) for the payload, the status model, and how to read actions back.

| actionCode | Webhook | You |
| - | - | - |
| `IMPORT_DOCUMENTS_MISSING` | `company_import_documents_missing` | Upload the missing documents. The action closes on its own |
| `IMPORT_INFO_REQUIRED` | `company_import_info_required` | Send the corrections and documents it asks for through the resolution endpoint |

## Missing documents

`IMPORT_DOCUMENTS_MISSING` is raised when an import is still at `AWAITING_DOCUMENTS` a day after it was created. doola checks once a day, and raises at most one per import.

`requestedDocumentTypes` is empty for this code. Read `documentRequirements` on the company for what is still missing: every entry with `status: "missing"` still needs uploading. The `reason` lists what was missing when the action opened, for example `Upload the missing documents to continue: ArticlesOfOrganization, EinLetter.`, and is not updated as documents arrive.

To clear it, [upload each missing document](https://docs.doola.com/api/import-company.md#uploading-the-documents). Once the last one is on file, the action closes as `resolved` and the import moves to `IN_REVIEW`. There is nothing to submit: posting a resolution for this action answers `422 E_REQUIRED_ACTION_NOT_RESOLVABLE`.

If the documents never arrive, nothing else happens. The import stays at `AWAITING_DOCUMENTS` and the action stays open.

## More information needed

`IMPORT_INFO_REQUIRED` is raised when doola's review finds something on the imported company that needs correcting. The action says exactly what it needs:

* **`requestedFieldIds`**: the company fields to send back, corrected.
* **`requestedDocumentTypes`**: the document types to upload.

Either list can be empty, but never both. The `reason` is built from the same picks, for example `Update these company details: EIN, company addresses. Upload: EIN letter.`

```json theme={null}
{
  "eventId": "3LbA1s7tU0vW3xY6zA9bC2dE5fG",
  "eventName": "company_import_info_required",
  "eventPayload": {
    "doolaCompanyId": "3LaZ7cV2bN5mQ8wE1rT4yU6iO9p",
    "requiredActionId": "3LbA1qZx9mW2nT7vR4kP8sY6hJd",
    "actionCode": "IMPORT_INFO_REQUIRED",
    "actionName": "More information needed for the import",
    "reason": "Update these company details: EIN, company addresses. Upload: EIN letter.",
    "requestedFieldIds": ["ein", "addresses"],
    "requestedDocumentTypes": ["EinLetter"]
  },
  "timestamp": 1793700902000
}
```

The webhook leaves out `requestedFieldIds` or `requestedDocumentTypes` when it is empty. The required-action reads always return both.

### The flow

```mermaid theme={null}
sequenceDiagram
    participant U as Your user
    participant P as Your backend
    participant D as doola API

    D-->>P: webhook company_import_info_required
    P->>U: Ask for the requested details and documents
    U->>P: Corrections and files
    P->>D: Upload each requested document
    D-->>P: Document ids
    P->>D: Submit resolution with importCorrections and documentIds
    D-->>P: Action resolved, company updated
    Note over D: doola continues the review
```

### Field ids

`requestedFieldIds` uses these ids. Each is sent back under `importCorrections` with the same key, except `legalName`, which is sent as `nameOptions`.

| Field id | Send as | Entity types | Rule |
| - | - | - | - |
| `legalName` | `nameOptions` | LLC, CCorp | Exactly one entry. The ending must belong to the company's entity type |
| `state` | `state` | LLC, CCorp | A two-letter US state code |
| `formationFilingNumber` | `formationFilingNumber` | LLC, CCorp | At most 255 characters |
| `formationFilingDate` | `formationFilingDate` | LLC, CCorp | `YYYY-MM-DD`, not in the future |
| `ein` | `ein` | LLC, CCorp | `NN-NNNNNNN` |
| `addresses` | `addresses` | LLC, CCorp | One `business` and one `mailing` entry, both `provider: customer` |
| `responsibleParty` | `responsibleParty` | LLC, CCorp | Same rules as on the import |
| `members` | `members` | LLC | Ownership totals 100 |
| `managementType` | `managementType` | LLC | `MEMBER_MANAGED` or `MANAGER_MANAGED`. Always requested and sent with `managers` |
| `managers` | `managers` | LLC | At least one for `MANAGER_MANAGED`, an empty list for `MEMBER_MANAGED` |
| `executiveMembers` | `executiveMembers` | CCorp | At least one President, Secretary, Treasurer and Director |
| `ccorpValuation` | `ccorpValuation` | CCorp | `noOfShares` and `shareValue`, both above 0 |
| `industry` | `industry` | LLC, CCorp | An exact label from the NAICS reference |
| `description` | `description` | LLC, CCorp | At most 50 characters |
| `registeredAgent` | `registeredAgent` | LLC, CCorp | `name` and a complete `address` |

`requestedDocumentTypes` uses `ArticlesOfOrganization`, `EinLetter`, `OperatingAgreement` (LLC) and `CorporateBylaws` (CCorp).

### Sending the corrections

First [upload each requested document](https://docs.doola.com/api/import-company.md#uploading-the-documents) and keep the returned `id`. Then call the resolution endpoint with `importCorrections` and `documentIds`:

```bash theme={null}
curl https://api.test.doola.com/v1/partner/companies/{companyId}/required-actions/{requiredActionId}/resolution \
  -X POST \
  -H "Authorization: dk_test_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "actionCode": "IMPORT_INFO_REQUIRED",
    "importCorrections": {
      "ein": "99-7654321",
      "addresses": [
        { "provider": "customer", "type": "business", "address": { "line1": "456 Corrected Ave", "city": "Casper", "state": "WY", "postalCode": "82601", "country": "USA" } },
        { "provider": "customer", "type": "mailing",  "address": { "line1": "456 Corrected Ave", "city": "Casper", "state": "WY", "postalCode": "82601", "country": "USA" } }
      ]
    },
    "documentIds": ["3LbB2tE5fG8hI1jK4lM7nO0pQ3r"]
  }'
```

**1. Send exactly the requested fields**

Every id in `requestedFieldIds` must be in `importCorrections`, and nothing else. A missing field answers `E_REQUIRED_ACTION_FIELD_MISSING`, an extra one `E_REQUIRED_ACTION_FIELD_NOT_REQUESTED`. A blank text value counts as not sent, so a requested field sent blank is refused as missing.

**2. Cover every requested document type**

`documentIds` holds up to 10 ids of documents on this company. Together they must cover every type in `requestedDocumentTypes`. Adding an EIN to a company that had none also needs an `EinLetter`, even when none was requested.

**3. Follow the import's rules**

Each value follows the rule the [import](https://docs.doola.com/api/import-company.md#fields) applies to the same field. `nameOptions`, `addresses` and `companyDetails` at the top level of the body belong to other action codes and are refused here.

The response is the action, already `resolved`, with its full `history`. Its `submitted` step echoes what you sent, with every SSN masked. The corrections are on the company at once: read it back to see them. The import's status does not change; doola continues its review.

The endpoint takes no `Idempotency-Key`. After a timeout, read the action back instead of retrying: once it is closed, a second call answers `409 E_REQUIRED_ACTION_CLOSED`.

### Lists and people

A list you send replaces what doola holds. A person you leave out is removed.

Every person on the company comes back from [Get a company](https://docs.doola.com/api/api-reference/companies/get-a-company.md) with an `id`: the `responsibleParty`, each member, each executive member and each manager. To keep a person, send them back with that `id`:

* **Their SSN stays as it is** when you send it back masked, exactly as the company returned it (`****-**-6789`), or leave it out. A masked SSN whose last four digits differ answers `400 E_REQUEST_BODY_INVALID`.
* **To change their SSN,** send the new value in full.
* **A person without an `id` is new** and has no SSN unless you send one. A masked SSN on a new member or manager answers `400 E_REQUEST_BODY_INVALID`.
* **An `id` must belong to a person of the same kind on this company,** and appear once. Anything else answers `400 E_VALIDATION_FAILED` under `importCorrections.<field>`.

```json theme={null}
{
  "actionCode": "IMPORT_INFO_REQUIRED",
  "importCorrections": {
    "managementType": "MANAGER_MANAGED",
    "managers": [
      {
        "id": "3LPpQ9mW2nT7vR4kP8sY6hJdA1b",
        "legalFirstName": "Grace",
        "legalLastName": "Hopper",
        "email": "grace.hopper@example.com",
        "ssn": "****-**-7890",
        "address": { "line1": "251 W 30th St", "city": "New York", "state": "NY", "postalCode": "10001", "country": "USA", "phone": "+12125550100" }
      }
    ]
  },
  "documentIds": []
}
```

### Changing the state or filing number

When a correction changes `state`, `formationFilingNumber` or both, the pair the company ends up with is checked by the same rule as the [import](https://docs.doola.com/api/import-company.md). If another company already holds it, the answer is `409 E_COMPANY_ALREADY_REGISTERED` and nothing changes. As on the import, the message names the other company only when it is one of yours, and an archived company never counts.

### After doola verifies the import

Verification closes any `IMPORT_INFO_REQUIRED` still open, as `resolved`. A correction that arrives after the import was verified answers `409 E_REQUIRED_ACTION_CLOSED` with the message `the import was verified after this action was raised`, and changes nothing. If doola later takes the import back to `IN_REVIEW` and needs more, it can raise a new action.

### After doola applies for the EIN

Once doola has applied for the company's EIN, the application carries the company's details as they are. Until the IRS issues the EIN, a correction answers `409 E_REQUIRED_ACTION_CLOSED` with the message `doola already applied for this company's EIN with its details as they are`, and changes nothing. This holds even when doola takes the import back to `IN_REVIEW`, and doola raises no new `IMPORT_INFO_REQUIRED` in that time.

## Errors

Checks run in a fixed order: body shape, company and action scope, `actionCode` match, then the correction checks. Any refusal changes nothing, and the action stays open.

| HTTP | Code | When |
| - | - | - |
| 400 | `E_VALIDATION_FAILED` | A value breaks the import's rule for that field. `error.fields["importCorrections.<field>"]` carries the field's code, for example `E_EIN_INVALID`, `E_STATE_INVALID`, `E_ADDRESSES_INVALID`, `E_NAME_OPTIONS_INVALID`, `E_INDUSTRY_INVALID` or `E_MANAGERS_INVALID`. Also a person `id` the company does not have or sent twice, `managers` without `managementType`, more than 10 `documentIds`, or another action code's fields |
| 400 | `E_REQUIRED_ACTION_CODE_MISMATCH` | `actionCode` does not match the action |
| 400 | `E_REQUIRED_ACTION_FIELD_NOT_REQUESTED` | A field the action did not request was sent |
| 400 | `E_REQUIRED_ACTION_FIELD_MISSING` | A requested field was not sent, or was sent blank |
| 400 | `E_REQUIRED_ACTION_DOCUMENT_MISSING` | `documentIds` leave a requested type uncovered, or an EIN is added without an `EinLetter` |
| 400 | `E_REQUEST_BODY_INVALID` | A masked SSN that does not match the stored person's, or a masked SSN on a new member or manager |
| 404 | `E_COMPANY_NOT_FOUND` | No company with this ID belongs to your tenant |
| 404 | `E_REQUIRED_ACTION_NOT_FOUND` | No action with this ID on this company |
| 404 | `E_COMPANY_DOCUMENT_NOT_FOUND` | A document id is not a current document on this company |
| 409 | `E_COMPANY_ALREADY_REGISTERED` | Another company already holds the state and filing number this company would end up with |
| 409 | `E_REQUIRED_ACTION_CLOSED` | The action is already closed, doola verified the import after the action was raised, or doola applied for the company's EIN and the IRS has not issued it yet |
| 422 | `E_REQUIRED_ACTION_NOT_RESOLVABLE` | The action is `IMPORT_DOCUMENTS_MISSING`, which closes on its own |

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.