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

# Annual Report Filing

> Read what a state asks and charges, put a company's annual report on file, confirm it, and follow it to completion.

Nearly every US state requires a company to file an annual report to stay in good standing: the state's yearly check that the company still exists and that the details it holds are current. What it asks, what it costs, and whether it is required at all vary by state and by entity type. Missing one is expensive — states charge late fees, and a company that stays delinquent can eventually be dissolved.

doola tells you what the state asks and what it charges, you collect the answers and the fee from your customer, and doola files the report with the state the company was formed in. One report per company per fiscal year, in six endpoints:

| Step        | Endpoint                                         | What it does                                      |
| ----------- | ------------------------------------------------ | ------------------------------------------------- |
| 1. Discover | `GET …/annual-reports/requirements`              | The fields to collect from your customer          |
| 2. Discover | `GET …/annual-reports/state-fees`                | What the state charges                            |
| 3. Submit   | `POST …/annual-reports`                          | Puts the report on file and fixes its price       |
| 4. Confirm  | `POST …/annual-reports/{annualReportId}/confirm` | Hands the report to doola to file                 |
| 5. Follow   | `GET …/annual-reports`                           | Lists the company's reports and where each stands |
| 6. Follow   | `GET …/annual-reports/{annualReportId}`          | Reads one report, with its answers                |

Every path sits under `/v1/partner/companies/{companyId}/compliance`.

<Info>
  **doola charges nothing through this API.** `priceInCents` is the state fee doola settles with you outside it. Submitting and confirming are two separate calls so you can collect from your own customer on your own timing, in between.
</Info>

## The flow

```mermaid theme={null}
sequenceDiagram
    participant P as Your backend
    participant D as doola API
    participant O as doola Ops / State

    Note over P,D: Discovery
    P->>D: GET …/annual-reports/requirements
    D-->>P: state, entityType, fiscalYear, dueDate, fields
    P->>D: GET …/annual-reports/state-fees
    D-->>P: priceInCents, isFilingRequired, isMinimum

    Note over P,D: Submission — nothing charged
    P->>D: POST …/annual-reports (fiscalYear, answers, companyDetails)
    D-->>P: status: FILLED, priceInCents fixed

    Note over P,D: Confirmation — on your timing
    P->>D: POST …/annual-reports/{annualReportId}/confirm
    D-->>P: status: IN_PROGRESS, handed to doola
    D-->>P: webhook company_annual_report_submitted

    Note over D,O: doola files with the state
    O-->>D: Report filed
    D-->>P: status: FILING_COMPLETED
    D-->>P: webhook company_annual_report_completed
```

<Note>
  While a report is still `FILLED`, calling `POST …/annual-reports` again replaces it whole. Resend every answer and every `companyDetails` correction: anything you leave out is dropped, not carried over. See [Submitting twice](#submitting-twice).
</Note>

<Note>
  [The compliance calendar](/api/compliance/calendar) tells you *when* a report is due. The endpoints on this page tell you what to collect, what it costs, and where a report stands.
</Note>

## Requirements: what to collect

<Info>
  This endpoint is **read-only**. It describes what to collect; it neither starts a filing nor stores anything.
</Info>

An annual report asks for two kinds of information: questions the state puts to the company, and company details doola already holds. This endpoint returns both as one ordered list, so you render the list you are given rather than deriving it from the state yourself.

Most states ask no questions at all. For those companies the response carries only the company details, which is the common case rather than an edge one.

```
GET /v1/partner/companies/{companyId}/compliance/annual-reports/requirements
```

| Query parameter | Meaning                                                                                                                                                                    |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fiscalYear`    | Year the report covers, `2000`–`2100`. Defaults to the current year. It is echoed back so you can tag what you collect; the field list itself does not vary by year today. |

A Wyoming LLC, abbreviated. The full schema is in the **Annual Report Filing** section of the API reference.

```json theme={null}
{
  "doolaCompanyId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhJ",
  "state": "WY",
  "entityType": "LLC",
  "fiscalYear": 2026,
  "isFilingRequired": true,
  "dueDate": null,
  "fields": [
    {
      "fieldId": "Q16",
      "label": "Do you have any assets in the state of Wyoming?",
      "type": "RADIO",
      "group": "QUESTION",
      "required": true,
      "affectsFee": true,
      "options": ["Yes", "No"],
      "dependsOn": null
    },
    {
      "fieldId": "Q17",
      "label": "Liquid cash resources in Wyoming (bank balances, petty cash)",
      "type": "AMOUNT",
      "group": "QUESTION",
      "required": true,
      "affectsFee": true,
      "options": null,
      "dependsOn": { "fieldId": "Q16", "answer": "Yes" }
    },
    {
      "fieldId": "companyName",
      "label": "Company name",
      "type": "TEXT",
      "group": "COMPANY_DETAIL",
      "required": false,
      "affectsFee": false,
      "options": null,
      "dependsOn": null
    }
  ]
}
```

| Field              | Meaning                                                                                                                                                                                            |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `doolaCompanyId`   | The company the requirements were read for.                                                                                                                                                        |
| `state`            | US state the report is filed in.                                                                                                                                                                   |
| `entityType`       | `LLC` or `CCorp`. The field list applies to this entity type only.                                                                                                                                 |
| `fiscalYear`       | The year you asked for, or the current year when you did not send one.                                                                                                                             |
| `isFilingRequired` | Whether the state requires an annual report for this entity type at all. `false` comes with an empty `fields` list. See [When no report is filed at all](#when-no-report-is-filed-at-all).         |
| `dueDate`          | Due date (`yyyy-MM-dd`) from the [compliance calendar](/api/compliance/calendar). `null` until the company's formation is complete, because the calendar dates the report from the formation date. |
| `fields`           | The fields to collect, in the order to present them.                                                                                                                                               |

### Field groups

Every field carries a `group`. Read the `group` rather than guessing from the `fieldId`. Questions come first, then company details.

| Group            | Where it comes from                     | What to do                                                                                                                                                              |
| ---------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `QUESTION`       | The state asks it. doola has no answer. | Collect it.                                                                                                                                                             |
| `COMPANY_DETAIL` | Company data doola already holds.       | Nothing, unless `required` is `true`: then doola does not hold it and cannot file without it. Today that is the phone number and physical address of a Delaware C-corp. |

### Rendering a field

| Field        | Meaning                                                                                                                                                                                                                                       |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fieldId`    | Key to send the answer back under, as `answers[].fieldId`.                                                                                                                                                                                    |
| `label`      | Text to show the customer.                                                                                                                                                                                                                    |
| `type`       | One of `TEXT`, `NUMBER`, `SELECT`, `RADIO`, `AMOUNT`, `DATE`, `BOOLEAN`, `ADDRESS`. `ADDRESS` is a structured address, not a string. Nothing uses `DATE` or `BOOLEAN` today; they are published so adding one later is not a breaking change. |
| `options`    | Allowed values for `SELECT` and `RADIO`, `null` otherwise.                                                                                                                                                                                    |
| `required`   | Whether the filing is rejected without the field.                                                                                                                                                                                             |
| `affectsFee` | Whether the state's fee is computed from this field. See [Which answers move the fee](#which-answers-move-the-fee).                                                                                                                           |
| `dependsOn`  | Set when the field only applies given another field's answer: `fieldId` names a field in the same list, `answer` is the value it must carry. Hide the field until then.                                                                       |

Treat the list as data. New `type` values and new fields are added over time, so a client that switches on a closed set of ids will break; one that renders whatever it is handed will not.

<Note>
  Do not derive the requirements from the [compliance calendar](/api/compliance/calendar), or the other way round. They answer different questions from different sources, and for a small number of states they do not line up: a tracked due date does not promise a field list here, and the reverse holds too.
</Note>

## State fees: what it costs

<Info>
  This endpoint is **read-only**. It reports a price; it neither starts a filing, stores anything, nor charges anyone.
</Info>

There is nothing to send and nothing to collect first: one call, one amount.

```
GET /v1/partner/companies/{companyId}/compliance/annual-reports/state-fees
```

No body, no query parameters. The fee does not vary by year today.

```json theme={null}
{
  "state": "FL",
  "entityType": "LLC",
  "priceInCents": 13875,
  "isFilingRequired": true,
  "isMinimum": false
}
```

| Response field     | Meaning                                                                                                                           |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `state`            | US state the report is filed in.                                                                                                  |
| `entityType`       | `LLC` or `CCorp`. The quote applies to this entity type only.                                                                     |
| `priceInCents`     | The state fee in whole US cents. `13875` is \$138.75. Never `null`; a state that charges nothing reports `0`.                     |
| `isFilingRequired` | Whether the state requires an annual report at all. See [When no report is filed at all](#when-no-report-is-filed-at-all).        |
| `isMinimum`        | `true` when `priceInCents` is the state's floor rather than the exact fee. See [A floor is not a quote](#a-floor-is-not-a-quote). |

Read both flags before acting on `priceInCents`:

* **`isFilingRequired`**: is there a report to file at all? A zero on its own is ambiguous.
* **`isMinimum`**: is this the exact fee, or the state's floor?

This amount is a quote, read off what doola holds about the company. The price that counts is fixed when the report is [submitted](#submitting-the-report), from the figures the submission carries, and comes back on it as `priceInCents`. Where doola already holds every figure the state's formula needs, the two are the same number.

### A floor is not a quote

Some reports cannot be priced exactly before the figures exist: Wyoming's, from its asset worksheet, and a Delaware C-corp's when doola holds no authorized share count. Rather than refusing to answer, the endpoint reports the state's floor and sets `isMinimum: true`:

```json theme={null}
{
  "state": "WY",
  "entityType": "LLC",
  "priceInCents": 6225,
  "isFilingRequired": true,
  "isMinimum": true
}
```

Wyoming's floor is the state's own minimum plus its fixed processing fee, so it is a real charge and the final amount is never below it. The submission settles the exact amount: send the Wyoming asset answers, or a Delaware C-corp's `authorizedShares` in `companyDetails`, and the report is priced from them.

A Delaware C-corp whose share count doola already holds is priced exactly, so `isMinimum` is `false` even though the fee is computed from a formula. Branch on `isMinimum`, never on the state code: a state joining this list is not a breaking change.

### Which answers move the fee

`affectsFee: true` on a requirements field marks a figure the state computes its fee from: the Wyoming asset answers, and the authorized share count on a Delaware C-corp. It is `false` on every field for almost every company, because most states price the report from data doola already holds.

`affectsFee` and `isMinimum` answer different questions. `affectsFee` says the state's formula reads that field. `isMinimum` says doola does not hold the figure yet, so the quote is only the floor. A Delaware C-corp with its share count on file has `affectsFee: true` on the share count and `isMinimum: false` on the quote.

Use `affectsFee` to tell the customer which answers change what they pay. Do not use it to decide whether to collect a field; that is `required`.

## When no report is filed at all

Whether a report is filed depends on the **state and the entity type together**. Alabama and Ohio require none from either, while in New Mexico and South Carolina only the `LLC` is exempt: a `CCorp` in either files and pays a fixed fee.

Both reads answer `200` and publish the same `isFilingRequired: false`, so they never disagree. The requirements come back with an empty `fields` list:

```json theme={null}
{
  "doolaCompanyId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhJ",
  "state": "OH",
  "entityType": "LLC",
  "fiscalYear": 2026,
  "isFilingRequired": false,
  "dueDate": null,
  "fields": []
}
```

The state fees come back with `priceInCents: 0`. Some states file an annual report and charge nothing for it; others file no annual report at all. Both report `0`, and only `isFilingRequired` tells them apart.

|                    | `isFilingRequired` | `priceInCents` | What to do                          |
| ------------------ | ------------------ | -------------- | ----------------------------------- |
| Most companies     | `true`             | the fee        | Collect the fee, file the report    |
| Filed at no charge | `true`             | `0`            | File the report, charge nothing     |
| No report to file  | **`false`**        | `0`            | Nothing to file, nothing to collect |

<Warning>
  Branch on `isFilingRequired`, never on `priceInCents === 0`. Treating a no-report company as free to file would have you collect answers for a filing that cannot be made. Submitting for such a company answers `422 E_STATE_NOT_SUPPORTED`.
</Warning>

## Submitting the report

<Info>
  This call **records** the report and fixes its price. It does not start the filing: that is [confirming](#confirming-the-report), a separate call on your own timing.
</Info>

Read [the requirements](#requirements-what-to-collect) first. This call takes the answers to the questions they published, plus any corrections to the company details doola holds.

```
POST /v1/partner/companies/{companyId}/compliance/annual-reports
```

A Wyoming LLC with no assets in the state, also correcting its phone number:

```json theme={null}
{
  "fiscalYear": 2026,
  "answers": [
    { "fieldId": "Q16", "value": "No" }
  ],
  "companyDetails": {
    "phoneNumber": "+13075550100"
  }
}
```

| Request field    | Meaning                                                                                                                                                                                                                                                  |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fiscalYear`     | Year the report covers, `2000`–`2100`. Defaults to the current year.                                                                                                                                                                                     |
| `answers`        | One entry per question the requirements published, keyed by `fieldId`. Omit for a state that asks nothing, which is most of them.                                                                                                                        |
| `companyDetails` | Corrections to the company details doola holds, keyed by the `COMPANY_DETAIL` field ids: `companyName`, `address`, `mailingAddress`, `physicalAddress`, `phoneNumber`, `authorizedShares`, `issuedShares`, `perValuedShares`. Omit when nothing changed. |

A key in `companyDetails` means "use this instead of what doola has". Leaving it out means "keep what doola has"; you cannot clear a value. An address replaces the one on file whole, so it takes the full address object (`line1`, `line2`, `city`, `state`, `postalCode`, `country`), and a partial one is rejected rather than merged.

The response is `201` with the report on file:

```json theme={null}
{
  "annualReportId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhJ",
  "doolaCompanyId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhK",
  "fiscalYear": 2026,
  "state": "WY",
  "entityType": "LLC",
  "status": "FILLED",
  "priceInCents": 6225,
  "submittedAt": null,
  "createdAt": "2026-02-01T09:00:00Z",
  "updatedAt": "2026-02-01T09:00:00Z",
  "answers": [
    { "fieldId": "Q16", "value": "No" }
  ],
  "isReplaced": false
}
```

This is the same report shape [the reads](#reading-reports-back) return, plus `isReplaced`, so one type covers submitting, confirming and reading.

| Response field   | Meaning                                                                                                                       |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `annualReportId` | The report's id. Keep it: [confirming](#confirming-the-report) and [reading](#reading-reports-back) address the report by it. |
| `status`         | `FILLED` on a fresh submission. See [Status](#status).                                                                        |
| `priceInCents`   | The state fee in whole US cents, fixed now from what you sent. `0` where the state charges nothing.                           |
| `submittedAt`    | Date the report was handed to doola's filing pipeline (`yyyy-MM-dd`). `null` on a report that has only just been recorded.    |
| `createdAt`      | When the report was opened, as an ISO-8601 instant.                                                                           |
| `updatedAt`      | When it last changed, as an ISO-8601 instant.                                                                                 |
| `answers`        | The answers now on record, keyed by `fieldId`. Empty for a state that asks no questions.                                      |
| `isReplaced`     | `true` when this submission replaced a report already on file for the year. See [Submitting twice](#submitting-twice).        |

### What is accepted

Only what the requirements published for this company. The check runs against the same list `GET …/requirements` returns, so the two cannot disagree.

* An answer to a field the company was not offered is refused with `400`, naming the field. It is never dropped silently.
* A field behind a `dependsOn` gate is only demanded, and only accepted, while the gate is open. Answer Wyoming's `Q16` with `No` and none of its asset questions are asked for; send one anyway and it is refused.
* Every `required` field that applies has to be present. For a Delaware C-corp that is `phoneNumber` and `physicalAddress`, the two required details doola does not hold.
* Values are checked against the field's `type`: `NUMBER` and `AMOUNT` are non-negative decimals with at most two places, `SELECT` and `RADIO` take one of the published `options`, `DATE` is `yyyy-MM-dd`.
* `authorizedShares` and `issuedShares` are whole numbers. `perValuedShares` is money per share and keeps up to eight decimal places, enough for a \$0.0001 par value; a ninth is refused rather than rounded away.

### Submitting twice

One report per company per fiscal year. While the report is still `FILLED`, a second submission for the same year **replaces** it: the answers are replaced whole, the report keeps its `annualReportId`, its price is fixed again from the new figures, and the response is `200` with `isReplaced: true`. Company details reset too, so resend any correction you made the first time. That is how you correct a mistake, and how a Wyoming report moves from the floor to its exact amount.

Once the report has moved past `FILLED` (you confirmed it, or doola is already working on or has filed that year) it is not overwritten: a second submission answers `409 E_ANNUAL_REPORT_ALREADY_EXISTS`.

A `FILLED` report has no deadline. It waits until you confirm it or replace it.

## Confirming the report

<Info>
  This call hands the report to doola to file. Nothing is charged: confirming is you committing to the filing. Call it when your own customer has paid you, or whenever suits your flow.
</Info>

```
POST /v1/partner/companies/{companyId}/compliance/annual-reports/{annualReportId}/confirm
```

No body. It answers `200` with the same report shape the submission returns.

The report moves to `IN_PROGRESS`, doola starts the filing, and you receive `company_annual_report_submitted`. From then on the report can no longer be replaced.

* **Confirm every report, including one priced at `0`.** A state that charges nothing still has a report to file, and nothing happens until you confirm.
* **Confirming twice is safe.** A report already past `FILLED` is returned unchanged, and doola never files it twice.
* **The report must belong to the company in the path.** Any other report id answers `404 E_NOT_FOUND`.

## Reading reports back

<Info>
  These two endpoints are **read-only**. They show what the submission put on file and where doola has taken it since.
</Info>

A company has at most one annual report per fiscal year. The list tells you which reports doola holds and where each stands; the single read adds the answers on record for one of them.

### Listing a company's reports

```
GET /v1/partner/companies/{companyId}/compliance/annual-reports
```

```json theme={null}
[
  {
    "annualReportId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhJ",
    "doolaCompanyId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhK",
    "fiscalYear": 2026,
    "state": "WY",
    "entityType": "LLC",
    "status": "FILLED",
    "priceInCents": 6225,
    "submittedAt": null,
    "createdAt": "2026-09-16T10:12:44Z",
    "updatedAt": "2026-09-16T10:12:44Z"
  },
  {
    "annualReportId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhL",
    "doolaCompanyId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhK",
    "fiscalYear": 2025,
    "state": "WY",
    "entityType": "LLC",
    "status": "FILING_COMPLETED",
    "priceInCents": null,
    "submittedAt": null,
    "createdAt": "2025-02-03T09:00:12Z",
    "updatedAt": "2025-03-01T16:40:05Z"
  }
]
```

Newest fiscal year first. Every key is always present; a value doola does not hold is `null`, never dropped.

| Field            | Meaning                                                                                                                                            |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `annualReportId` | The report's id (KSUID), the same one the submission returned.                                                                                     |
| `doolaCompanyId` | The company the report belongs to.                                                                                                                 |
| `fiscalYear`     | Year the report covers.                                                                                                                            |
| `state`          | US state the report is filed in.                                                                                                                   |
| `entityType`     | `LLC` or `CCorp`.                                                                                                                                  |
| `status`         | Where the report stands. See [Status](#status).                                                                                                    |
| `priceInCents`   | The state fee fixed on the report, in whole US cents. `null` when doola has not priced it, as on a report the customer started in doola's own app. |
| `submittedAt`    | Date the report was handed to doola's filing pipeline (`yyyy-MM-dd`). Often `null` even for a filed report; read `status` instead.                 |
| `createdAt`      | When the report was opened, as an ISO-8601 instant. `null` if doola holds no timestamp.                                                            |
| `updatedAt`      | When it last changed, as an ISO-8601 instant. A status change moves it. `null` if doola holds no timestamp.                                        |

An empty list means doola holds nothing to show for the company, not that the company does not exist. A company that does not exist, or is not yours, is a `404`.

### Reading one report

```
GET /v1/partner/companies/{companyId}/compliance/annual-reports/{annualReportId}
```

```json theme={null}
{
  "annualReportId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhJ",
  "doolaCompanyId": "2Ns8vJqZ1lQwErTyUiOpAsDfGhK",
  "fiscalYear": 2026,
  "state": "WY",
  "entityType": "LLC",
  "status": "FILLED",
  "priceInCents": 6225,
  "submittedAt": null,
  "createdAt": "2026-09-16T10:12:44Z",
  "updatedAt": "2026-09-16T10:12:44Z",
  "answers": [
    { "fieldId": "Q16", "value": "No" }
  ]
}
```

The same fields as one entry of the list, plus `answers`. Most states ask no questions, so an empty list is the common case.

| Field     | Meaning                                                                                                                                                                                                                    |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fieldId` | The field id [the requirements](#requirements-what-to-collect) publish as `fields[].fieldId`. An answer stays on record after doola stops asking that question, so it may name a field the requirements no longer publish. |
| `value`   | The answer exactly as submitted, always a string whatever the field's `type`. `null` when no text is on record.                                                                                                            |

## Status

One vocabulary across every response on this page.

| Status                 | Meaning                                                                                                                                                                    |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FILLED`               | On file and not yet confirmed. Submitting again for the same year replaces it.                                                                                             |
| `IN_PROGRESS`          | doola's to resolve, nothing for you to do: confirmed and being filed, recorded by doola's operations team as not required for the year, or in checkout in doola's own app. |
| `AWAITING_INFORMATION` | doola needs something back before it can file.                                                                                                                             |
| `FILING_COMPLETED`     | Filed with the state. Nothing else will happen to it.                                                                                                                      |

A report the customer filed themselves, directly with the state, reads as `FILING_COMPLETED`: it **is** filed, and hiding it would let you think the year is unfiled and file it a second time.

Every report you submitted is listed under one of these statuses. The one report you will not see is one the customer opened in doola's own app that nobody has acted on yet: it is absent from the list and not readable by id either, so the two reads never disagree. New statuses may be added, so treat one you do not recognise as informational.

<Note>
  There is no channel yet for supplying what `AWAITING_INFORMATION` is waiting on. When one lands it will be a [required action](/api/required-actions), but no annual report action exists today, so do not poll for one.
</Note>

## Webhooks

You do not have to poll a report to completion. Three [webhook events](/api/webhooks) cover it:

| Event                             | When                                                                          |
| --------------------------------- | ----------------------------------------------------------------------------- |
| `company_annual_report_submitted` | You confirmed the report and doola started the filing.                        |
| `company_annual_report_completed` | The state has the report. Terminal: it never fires twice for the same report. |
| `document_annualreport_uploaded`  | The filed report is stored and ready to download.                             |

The first two carry `doolaCompanyId` only: [list the company's reports](#listing-a-companys-reports) to see which year moved. `document_annualreport_uploaded` arrives independently of the other two, so do not assume an order.

## Errors

| HTTP  | Code                             | Endpoints                        | When                                                                                                                                                                     |
| ----- | -------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400` | `E_VALIDATION_FAILED`            | requirements                     | `fiscalYear` is outside `2000`–`2100`.                                                                                                                                   |
| `400` | `E_VALIDATION_FAILED`            | submit                           | An answer or correction was not offered to this company, was missing, or was the wrong kind of value. The refused field is under `error.fields`, keyed by its `fieldId`. |
| `404` | `E_COMPANY_NOT_FOUND`            | all                              | The company does not exist, or is not owned by your partner account.                                                                                                     |
| `404` | `E_NOT_FOUND`                    | read one, confirm                | No such report is readable for that company.                                                                                                                             |
| `409` | `E_ANNUAL_REPORT_ALREADY_EXISTS` | submit                           | The report for this year is past `FILLED`: confirmed, being filed, or already filed.                                                                                     |
| `409` | `E_RESOURCE_CONFLICT`            | confirm                          | The report is in a status that cannot be confirmed.                                                                                                                      |
| `422` | `E_STATE_NOT_SUPPORTED`          | requirements, state fees, submit | doola holds no annual report data for the company's state and entity type. On submit, also a state that files no annual report: there is nothing to submit.              |

`404 E_NOT_FOUND` is deliberately undiscriminating: a report that does not exist and one that belongs to another company get the same answer, so an id you may not read is never confirmed to exist. Likewise a company that exists but is not yours is `404`, never `403`.

<Note>
  `422` should not occur for a company created through this API: every US state and DC is covered for both `LLC` and `CCorp`. A company whose state files no annual report is **not** a `422` on the two reads. They answer `200` with `isFilingRequired: false`.
</Note>

See [Errors](/api/errors) for the error envelope and the codes shared by every endpoint.
