# Business Made · Government e-filing

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /business-made/efile/connections/{program}

**IRS API connection**

`operationId: EfileController_getConnection`

Owner / ConfigAdmin / RootAdmin. The private key is never returned: `hasPrivateKey` and `publicKeyThumbprint` show which key is stored.

#### Signature

```http
GET /business-made/efile/connections/{program} (program: string) -> ConnectionView
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `program` | path | "iris" \| "tinm" \| "eservices" | yes | iris = IRIS 1099 filing; tinm = TIN Matching; eservices = other e-Services APIs. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | ConnectionView |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /business-made/efile/connections/{program}

**Save an IRS API connection**

`operationId: EfileController_saveConnection`

Fields: clientId, userId (full e-Services User ID from the Consent App), kid, tcc, env (test | prod), allowProduction, privateKeyPem. `privateKeyPem` is write-only: sent = replaced (must be an RSA PEM), omitted = kept, `clearPrivateKey: true` = removed. The key is sealed with FINANCE_ENCRYPTION_KEY. `env: prod` is refused unless `allowProduction` is true; turning `allowProduction` off returns the connection to test. Saving clears the cached token and the last test result.

#### Signature

```http
PUT /business-made/efile/connections/{program} (program: string, body) -> ConnectionView
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | EFILE_BAD_PRIVATE_KEY | The private key could not be read | Not a PEM RSA private key. | — |
| `412` | ENCRYPTION_KEY_MISSING | Storing an IRS private key needs FINANCE_ENCRYPTION_KEY on the server | The server cannot seal the key. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `program` | path | "iris" \| "tinm" \| "eservices" | yes | iris = IRIS 1099 filing; tinm = TIN Matching; eservices = other e-Services APIs. |

### Request body

```json
{
  "clientId": "4d81a0c6-…",
  "userId": "dasmith-345870",
  "kid": "my-kid",
  "env": "test",
  "privateKeyPem": "-----BEGIN PRIVATE KEY-----…"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | ConnectionView |
| `400` | The private key could not be read — Not a PEM RSA private key. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `412` | Storing an IRS private key needs FINANCE_ENCRYPTION_KEY on the server — The server cannot seal the key. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/efile/connections/{program}/test

**Test an IRS API connection**

`operationId: EfileController_testConnection`

Signs the client and user RS256 JWTs (Pub 5718 §3.1.2) and requests a fresh token from the IRS token endpoint of the connection’s environment. Returns the stage that failed and a plain-language message; the result is kept on the connection as `lastTest`.

#### Signature

```http
POST /business-made/efile/connections/{program}/test (program: string) -> TestResult
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `program` | path | "iris" \| "tinm" \| "eservices" | yes | iris = IRIS 1099 filing; tinm = TIN Matching; eservices = other e-Services APIs. |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | TestResult |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/efile/submissions

**E-file submissions**

`operationId: EfileController_listSubmissions`

Paged `bm_efile_submission` records, newest first. Filters and sorting are server-side.

#### Signature

```http
GET /business-made/efile/submissions (agency?: string, program?: string, status?: string, taxYear?: number, formType?: string, keyword?: string, page?: number, pageSize?: number, sort?: string, sortType?: string) -> { data: bm_efile_submission[], total, page, pageSize }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `agency` | query | "irs" \| "ssa" | — |  |
| `program` | query | "iris" \| "mef" \| "tinm" \| "efw2" | — |  |
| `status` | query | "draft" \| "ready" \| "submitted" \| "accepted" \| "partially_accepted" \| "rejected" \| "error" | — |  |
| `taxYear` | query | number | — |  |
| `formType` | query | string | — |  |
| `keyword` | query | string | — |  |
| `page` | query | number | — |  |
| `pageSize` | query | number | — |  |
| `sort` | query | string | — |  |
| `sortType` | query | "asc" \| "desc" | — |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { data: bm_efile_submission[], total, page, pageSize } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/efile/submissions/{id}

**An e-file submission**

`operationId: EfileController_getSubmission`

#### Signature

```http
GET /business-made/efile/submissions/{id} (id: string) -> bm_efile_submission
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | EFILE_NOT_FOUND | E-file submission not found | No such record. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | bm_efile_submission sk |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | bm_efile_submission |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | E-file submission not found — No such record. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/efile/submissions/{id}/files/{kind}

**Download a submission’s payload or acknowledgement**

`operationId: EfileController_downloadSubmissionFile`

The files carry full SSNs/TINs, so they are stored private and served only here, with `Cache-Control: no-store`. `payloadFileUrl` / `ackFileUrl` on the record hold this route.

#### Signature

```http
GET /business-made/efile/submissions/{id}/files/{kind} (id: string, kind: string) -> The file (attachment)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | EFILE_FILE_NOT_FOUND | This submission has no payload file | Nothing attached, or missing from storage. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | bm_efile_submission sk |
| `kind` | path | "payload" \| "ack" | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The file (attachment) |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | This submission has no payload file — Nothing attached, or missing from storage. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/efile/tinm/check

**Interactive TIN Matching (up to 25 payees)**

`operationId: TinmController_check`

Owner / ConfigAdmin / RootAdmin. Each valid payee is checked with the IRS at once; payees without a usable name or 9-digit TIN are reported and not sent. Each answer is written on the payee record as `tinMatch`. Uses the org’s tinm connection (TEST unless the owner allowed production).

#### Signature

```http
POST /business-made/efile/tinm/check (body) -> { env, checked, matched, results: Result[] }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | TINM_TOO_MANY | An interactive check takes at most 25 payees | More than 25 payees. | — |
| `412` | EFILE_CONNECTION_INCOMPLETE | The IRS TIN Matching connection is not set up | No tinm connection, or fields missing. | — |
| `424` | IRS_TOKEN_FAILED | The IRS refused the token request | Key, User ID or consent problem. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

```json
{
  "payees": [
    {
      "datatype": "bm_employee",
      "id": "665f1c…"
    },
    {
      "name": "Example Payee LLC",
      "tin": "000000001",
      "tinType": "ein"
    }
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { env, checked, matched, results: Result[] } |
| `400` | An interactive check takes at most 25 payees — More than 25 payees. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `412` | The IRS TIN Matching connection is not set up — No tinm connection, or fields missing. |
| `424` | The IRS refused the token request — Key, User ID or consent problem. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/efile/tinm/bulk

**Bulk TIN Matching (up to 100,000 payees)**

`operationId: TinmController_bulk`

Builds the Pub 2108A request file (TIN TYPE;TIN;NAME;ACCOUNT, one line per payee; duplicates and invalid payees left out and listed), keeps it privately on a new bm_efile_submission (program tinm) and uploads it. `scope: all_1099_payees` takes every contractor and every vendor marked 1099. Results arrive in the IRS SOR mailbox within 24 hours and are collected by the hourly `tinm-results` job or GET …/results.

#### Signature

```http
POST /business-made/efile/tinm/bulk (body) -> { submission, env, sent, notSent: [{ code, message, recordRef }] }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | TINM_NO_PAYEES | Send the payees to check | No payees and no scope, or the scope has none. | — |
| `412` | EFILE_CONNECTION_INCOMPLETE | The IRS TIN Matching connection is not set up | No tinm connection, or fields missing. | — |
| `424` | IRS_TOKEN_FAILED | The IRS refused the token request | Key, User ID or consent problem. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

```json
{
  "scope": "all_1099_payees",
  "taxYear": 2026
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { submission, env, sent, notSent: [{ code, message, recordRef }] } |
| `400` | Send the payees to check — No payees and no scope, or the scope has none. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `412` | The IRS TIN Matching connection is not set up — No tinm connection, or fields missing. |
| `424` | The IRS refused the token request — Key, User ID or consent problem. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/efile/tinm/submissions/{id}/results

**Results of a bulk TIN Matching request**

`operationId: TinmController_results`

While the request waits (status submitted), the IRS SOR mailbox is checked first. Once the result file is in, it is stored privately as the submission’s acknowledgement, each payee’s result is written on their record (only if their TIN still ends in the digits checked) and the submission becomes accepted. TINs are masked.

#### Signature

```http
GET /business-made/efile/tinm/submissions/{id}/results (id: string) -> { id, status, env, ready, message?, summary: { total, matched, notMatched, byCode }, results: Result[], notSent }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | EFILE_NOT_FOUND | E-file submission not found | No such record. | — |
| `400` | TINM_NOT_TINM | This submission is not a TIN Matching request | Another program’s submission. | — |
| `424` | SOR_NOT_AUTHORIZED | The IRS refused access to the e-Services mailbox (SOR) | The user cannot read the SOR mailbox. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | bm_efile_submission sk (program tinm) |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { id, status, env, ready, message?, summary: { total, matched, notMatched, byCode }, results: Result[], notSent } |
| `400` | This submission is not a TIN Matching request — Another program’s submission. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | E-file submission not found — No such record. |
| `424` | The IRS refused access to the e-Services mailbox (SOR) — The user cannot read the SOR mailbox. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/efile/iris/{taxYear}/prepare

**Prepare an IRIS 1099 transmission (build and validate only)**

`operationId: IrisController_prepare`

Builds the IRIS A2A XML (Pub 5718, TY2025 schema 2.0.3) from the year’s bm_tax_form records of the form type (payee name/TIN/address from the signed W-9, else the contractor record; payer from the employer tax setup) and checks the IRS rules that can be checked locally: TINs, names, addresses, amounts, counts, TCC, Software ID, and the test-system rule that payer and payee TINs start with 000. The XML is stored privately on the open draft/ready submission for that year and form (created if there is none). Status becomes `ready`, or `draft` with `errors`. Body: { formType?: "1099-NEC" (default) | "1099-MISC", softwareId?, transmitter? }. Optional `transmitter` { tin, name, companyName, companyAddress { line1, line2, city, state, zip }, contactName, contactEmail, contactPhone } — the TCC holder’s details as on its IRIS TCC application. Defaults: the IRIS connection’s saved `transmitter`, else the payer (Issuer role). The TCC is always the IRIS connection’s. `softwareId` defaults to the server’s IRIS_SOFTWARE_ID.

#### Signature

```http
POST /business-made/efile/iris/{taxYear}/prepare (taxYear: number, body) -> { submission, recordCount, errors[], warnings[], totals }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `412` | IRIS_TEST_ONLY | IRIS filing is TEST only in this build | The IRIS connection is on production. | — |
| `400` | IRIS_FORM_UNSUPPORTED | IRIS filing here supports 1099-NEC and 1099-MISC. | Another form type. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `taxYear` | path | number | yes |  |

### Request body

```json
{
  "formType": "1099-NEC"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { submission, recordCount, errors[], warnings[], totals } |
| `400` | IRIS filing here supports 1099-NEC and 1099-MISC. — Another form type. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `412` | IRIS filing is TEST only in this build — The IRIS connection is on production. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /business-made/efile/iris/submissions/{id}/transmit

**Send an IRIS transmission to the IRS test system**

`operationId: IrisController_transmit`

Rebuilds the file from current data with a new Unique Transmission ID (UUID:IRIS:TCC::A), stores it, gets the IRIS bearer token and POSTs it as multipart/form-data (`file`, text/xml) to the IRIS ATS intake endpoint. On success the submission is `submitted` with the Receipt ID and UTID, and the org’s `iris-acks` queue job is scheduled. Allowed from ready, draft (re-validated), error and rejected. Body: { softwareId?, transmitter? }.

#### Signature

```http
POST /business-made/efile/iris/submissions/{id}/transmit (id: string, body) -> { submission }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `422` | IRIS_VALIDATION_FAILED | The file has N error(s) to fix before it can be sent. | Local rules failed; `errors` lists them. | — |
| `424` | IRIS_NOT_ENABLED | IRIS is not enabled on this API client, or there is no IRIS TCC for it yet. | The IRS gateway refused the call (401/403 / scope). | — |
| `409` | IRIS_ALREADY_SENT | Already with the IRS | Submitted or accepted. | — |
| `502` | IRIS_NETWORK | Could not reach the IRIS test system | Network failure or timeout. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | bm_efile_submission sk (program iris) |

### Request body

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { submission } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `409` | Already with the IRS — Submitted or accepted. |
| `422` | The file has N error(s) to fix before it can be sent. — Local rules failed; `errors` lists them. |
| `424` | IRIS is not enabled on this API client, or there is no IRIS TCC for it yet. — The IRS gateway refused the call (401/403 / scope). |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |
| `502` | Could not reach the IRIS test system — Network failure or timeout. |

## POST /business-made/efile/iris/submissions/{id}/refresh

**Ask the IRS for the acknowledgement now**

`operationId: IrisController_refresh`

POSTs a transStatusOrAckRequest (Receipt ID, else UTID; searchTypeCd A) to the IRIS ATS status endpoint. Accepted and Accepted with Errors → `accepted`, Partially Accepted → `partially_accepted`, Rejected → `rejected`; the ack is stored privately and each error is kept as { code, message, recordRef = bm_tax_form sk }. Processing leaves it `submitted`; Not Found for more than a day → `error`. The `iris-acks` queue job does the same on its own back-off.

#### Signature

```http
POST /business-made/efile/iris/submissions/{id}/refresh (id: string) -> { submission, final, irsStatus }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `409` | IRIS_NOT_SUBMITTED | Only a transmission that was sent to the IRS has an acknowledgement. | Not sent yet. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | bm_efile_submission sk (program iris) |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { submission, final, irsStatus } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `409` | Only a transmission that was sent to the IRS has an acknowledgement. — Not sent yet. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /business-made/efile/iris/submissions/{id}/ack

**The IRS acknowledgement of an IRIS transmission**

`operationId: IrisController_ack`

The acknowledgement as recorded (asks the IRS first while the transmission is still `submitted`). Never the raw ack (it can echo TINs): download it through the e-file file route.

#### Signature

```http
GET /business-made/efile/iris/submissions/{id}/ack (id: string) -> Acknowledgement view
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `id` | path | string | yes | bm_efile_submission sk (program iris) |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Acknowledgement view |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

