---
title: "Billing"
description: "Every operation in this group: what it accepts, what it returns and the errors it can answer with."
url: "https://openemail.uk/docs/api/reference/billing"
area: "API"
category: "Reference"
---

# Billing

Every operation in this group: what it accepts, what it returns and the errors it can answer with.

## Operations

The plan of the workspace and what it costs, as Plans & Billing shows them: what the plan includes and how much of it is used, the plans on sale, pay as you go, every charge with its invoice, and the links that start a checkout or open the billing portal.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Nothing is paid through the API. Starting a checkout, opening the billing portal and adding a card for pay as you go each return a link to the billing provider's page, where the person pays, changes the card or cancels, as they do from the app.

### `GET /billing`

Read the plan

The plan of the workspace and what it includes: the billing interval, when it renews or ends and the next charge, how many domains it holds, how much of the sends and AI actions are used, and pay as you go. `metered` is false when billing is off on this install, and then nothing is capped.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Returns**

- `200` `Billing`: The plan and what it includes.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.get()`](https://openemail.uk/docs/sdk/reference/billing#get); CLI [`openemail billing get`](https://openemail.uk/docs/cli/reference/billing#billing-get); MCP [`getBilling`](https://openemail.uk/docs/mcp/tools/billing#getBilling).

### `GET /billing/plans`

List the plans

Every plan, cheapest first, with its price and what it includes. `available` says whether it is sold on this install, and `intervals` the billing intervals it is sold at.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Returns**

- `200` `BillingPlanList`: Every plan.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.listPlans()`](https://openemail.uk/docs/sdk/reference/billing#listPlans); CLI [`openemail billing list-plans`](https://openemail.uk/docs/cli/reference/billing#billing-list-plans); MCP [`listBillingPlans`](https://openemail.uk/docs/mcp/tools/billing#listBillingPlans).

### `GET /billing/usage`

Read the usage history

Sends and AI actions per day, and what pay as you go extras cost per month, as the Usage charts show them.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Query parameters**

- `days` (`integer | string`, default `30`): How many days back to go, 1 to 3660, or `all` for every day since the workspace was made. 30 by default.

**Returns**

- `200` `BillingUsage`: Usage per day and extras per month.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.getUsage()`](https://openemail.uk/docs/sdk/reference/billing#getUsage); CLI [`openemail billing get-usage`](https://openemail.uk/docs/cli/reference/billing#billing-get-usage); MCP [`getBillingUsage`](https://openemail.uk/docs/mcp/tools/billing#getBillingUsage).

### `GET /billing/alerts`

List the billing alerts

What the billing banner of the app would say now, most urgent first: a failed payment, paused pay as you go, sending or AI paused at a limit, a plan about to end, an allowance nearly used and a charge coming soon. An empty list means there is nothing to say.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Returns**

- `200` `BillingAlertList`: The alerts, most urgent first.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.listAlerts()`](https://openemail.uk/docs/sdk/reference/billing#listAlerts); CLI [`openemail billing list-alerts`](https://openemail.uk/docs/cli/reference/billing#billing-list-alerts); MCP [`listBillingAlerts`](https://openemail.uk/docs/mcp/tools/billing#listBillingAlerts).

### `GET /billing/countries`

List the billing countries

Every country a billing address can be in, as two-letter ISO 3166 codes, the values `country` takes on `PUT /billing/invoices/{orderId}/details`.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Returns**

- `200` `BillingCountryList`: Every country code.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.listCountries()`](https://openemail.uk/docs/sdk/reference/billing#listCountries); CLI [`openemail billing list-countries`](https://openemail.uk/docs/cli/reference/billing#billing-list-countries); MCP [`listBillingCountries`](https://openemail.uk/docs/mcp/tools/billing#listBillingCountries).

### `GET /billing/pay-as-you-go`

Read pay as you go

Whether usage past the allowances is billed, the monthly limit and what extras cost so far, the limits that can be chosen, the prices, and the current billing period of pay as you go once it is set up.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Returns**

- `200` `PayAsYouGo`: Pay as you go on this workspace.

**Errors**

- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.getPayAsYouGo()`](https://openemail.uk/docs/sdk/reference/billing#getPayAsYouGo); CLI [`openemail billing get-pay-as-you-go`](https://openemail.uk/docs/cli/reference/billing#billing-get-pay-as-you-go); MCP [`getPayAsYouGo`](https://openemail.uk/docs/mcp/tools/billing#getPayAsYouGo).

### `PATCH /billing/pay-as-you-go`

Turn pay as you go on or off

Turns pay as you go on or off, as the switch on Plans & Billing does. Off takes effect at once, and usage stops at the allowances. On takes effect at once when a card is already saved. The first time, `checkoutUrl` is a link where the person adds a card, and pay as you go starts once they have: call `POST /billing/pay-as-you-go/confirm` after they return. `activating` means a card was just saved and it is being turned on. `theme` and `locale` style the page the link opens.

Nothing is paid through the API. Starting a checkout, opening the billing portal and adding a card for pay as you go each return a link to the billing provider's page, where the person pays, changes the card or cancels, as they do from the app.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:write` scope.

- Scopes: `billing:write`.
- Asks an OAuth access token for a verification code.

**Request body**

- `theme` (`string`, one of `"light"`, `"dark"`): `light` or `dark`, for the page the link opens.
- `locale` (`string`, up to 35 characters): A language tag such as `de` or `pt-PT`, for the page the link opens.
- `enabled` (`boolean`, required): `true` to turn it on, `false` to turn it off.

**Returns**

- `200` `PayAsYouGoSwitch`: What happened.

**Errors**

- `403`: The key lacks the scope, or may not send as that address. `step_up_required`: the call was made with an OAuth access token that has not been verified in the last 60 minutes. Ask for a code with `POST /security/step-up`, send it to `POST /security/step-up/verify`, then repeat the call. The person can also choose Allow changes for 60 minutes on the app in Account settings, Connected apps, on the OpenEmail website. An API key is never asked for a code.
- `503`: `billing_not_configured`: pay as you go is not set up on this install.
- The errors every operation can return: `400`, `401`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.setPayAsYouGo()`](https://openemail.uk/docs/sdk/reference/billing#setPayAsYouGo); CLI [`openemail billing set-pay-as-you-go`](https://openemail.uk/docs/cli/reference/billing#billing-set-pay-as-you-go); MCP [`setPayAsYouGo`](https://openemail.uk/docs/mcp/tools/billing#setPayAsYouGo).

### `PUT /billing/pay-as-you-go/limit`

Set the pay as you go limit

Sets the monthly spending limit of pay as you go, one of the amounts `GET /billing/pay-as-you-go` lists in `limits`. Extras stop for the rest of a calendar month once it is reached.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:write` scope.

- Scopes: `billing:write`.
- Asks an OAuth access token for a verification code.

**Request body**

- `limitCents` (`integer`, required, one of `1000`, `2500`, `5000`, `10000`, `25000`, `50000`, `100000`, `250000`, `500000`): The monthly limit in US cents.

**Returns**

- `200` `PayAsYouGoLimit`: The limit.

**Errors**

- `403`: The key lacks the scope, or may not send as that address. `step_up_required`: the call was made with an OAuth access token that has not been verified in the last 60 minutes. Ask for a code with `POST /security/step-up`, send it to `POST /security/step-up/verify`, then repeat the call. The person can also choose Allow changes for 60 minutes on the app in Account settings, Connected apps, on the OpenEmail website. An API key is never asked for a code.
- `409`: `pay_as_you_go_not_enrolled`: pay as you go has never been set up on this workspace.
- The errors every operation can return: `400`, `401`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.setPayAsYouGoLimit()`](https://openemail.uk/docs/sdk/reference/billing#setPayAsYouGoLimit); CLI [`openemail billing set-pay-as-you-go-limit`](https://openemail.uk/docs/cli/reference/billing#billing-set-pay-as-you-go-limit); MCP [`setPayAsYouGoLimit`](https://openemail.uk/docs/mcp/tools/billing#setPayAsYouGoLimit).

### `POST /billing/pay-as-you-go/confirm`

Confirm pay as you go

Checks with the billing provider whether the card from a pay as you go checkout was saved, and records it, as the app does when the person comes back from the checkout. `enabled` says whether pay as you go is on now. It is safe to call again.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:write` scope.

- Scopes: `billing:write`.
- Asks an OAuth access token for a verification code.

**Returns**

- `200` `PayAsYouGoConfirmation`: Whether pay as you go is on.

**Errors**

- `403`: The key lacks the scope, or may not send as that address. `step_up_required`: the call was made with an OAuth access token that has not been verified in the last 60 minutes. Ask for a code with `POST /security/step-up`, send it to `POST /security/step-up/verify`, then repeat the call. The person can also choose Allow changes for 60 minutes on the app in Account settings, Connected apps, on the OpenEmail website. An API key is never asked for a code.
- The errors every operation can return: `400`, `401`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.confirmPayAsYouGo()`](https://openemail.uk/docs/sdk/reference/billing#confirmPayAsYouGo); CLI [`openemail billing confirm-pay-as-you-go`](https://openemail.uk/docs/cli/reference/billing#billing-confirm-pay-as-you-go); MCP [`confirmPayAsYouGo`](https://openemail.uk/docs/mcp/tools/billing#confirmPayAsYouGo).

### `POST /billing/checkout`

Start a checkout

Starts buying a paid plan for a workspace on Free, as choosing a plan in the app does, and returns the link to the checkout. Nothing is charged until the person pays there, and the plan starts once they have. A workspace that already pays for a plan changes it on the billing portal instead.

Nothing is paid through the API. Starting a checkout, opening the billing portal and adding a card for pay as you go each return a link to the billing provider's page, where the person pays, changes the card or cancels, as they do from the app.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:write` scope.

- Scopes: `billing:write`.
- Asks an OAuth access token for a verification code.

**Request body**

- `theme` (`string`, one of `"light"`, `"dark"`): `light` or `dark`, for the page the link opens.
- `locale` (`string`, up to 35 characters): A language tag such as `de` or `pt-PT`, for the page the link opens.
- `plan` (`string`, required, one of `"starter"`, `"business"`, `"enterprise"`): `starter`, `business` or `enterprise`.
- `interval` (`string`, one of `"month"`, `"year"`): `month` or `year`. Defaults to `month`.

**Returns**

- `200` `BillingCheckout`: The link to the checkout.

**Errors**

- `403`: The key lacks the scope, or may not send as that address. `step_up_required`: the call was made with an OAuth access token that has not been verified in the last 60 minutes. Ask for a code with `POST /security/step-up`, send it to `POST /security/step-up/verify`, then repeat the call. The person can also choose Allow changes for 60 minutes on the app in Account settings, Connected apps, on the OpenEmail website. An API key is never asked for a code.
- `409`: `plan_conflict`: the workspace already pays for a plan.
- `422`: `plan_unavailable`: the plan is not sold on this install, or not at that interval. `invalid_parameter`: the body did not validate.
- `503`: `billing_not_configured`: paid plans are not set up on this install.
- The errors every operation can return: `400`, `401`, `404`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.startCheckout()`](https://openemail.uk/docs/sdk/reference/billing#startCheckout); CLI [`openemail billing start-checkout`](https://openemail.uk/docs/cli/reference/billing#billing-start-checkout); MCP [`startPlanCheckout`](https://openemail.uk/docs/mcp/tools/billing#startPlanCheckout).

### `POST /billing/portal`

Open the billing portal

Returns a link to the billing portal, where the person changes or cancels the plan, updates the card and downloads past invoices, as Manage does in the app. The body is optional.

Nothing is paid through the API. Starting a checkout, opening the billing portal and adding a card for pay as you go each return a link to the billing provider's page, where the person pays, changes the card or cancels, as they do from the app.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:write` scope.

- Scopes: `billing:write`.
- Asks an OAuth access token for a verification code.

**Request body**

- `theme` (`string`, one of `"light"`, `"dark"`): `light` or `dark`, for the page the link opens.
- `locale` (`string`, up to 35 characters): A language tag such as `de` or `pt-PT`, for the page the link opens.

**Returns**

- `200` `BillingPortal`: The link to the billing portal.

**Errors**

- `403`: The key lacks the scope, or may not send as that address. `step_up_required`: the call was made with an OAuth access token that has not been verified in the last 60 minutes. Ask for a code with `POST /security/step-up`, send it to `POST /security/step-up/verify`, then repeat the call. The person can also choose Allow changes for 60 minutes on the app in Account settings, Connected apps, on the OpenEmail website. An API key is never asked for a code.
- `503`: `billing_not_configured`: billing is not set up on this install.
- The errors every operation can return: `400`, `401`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.openPortal()`](https://openemail.uk/docs/sdk/reference/billing#openPortal); CLI [`openemail billing open-portal`](https://openemail.uk/docs/cli/reference/billing#billing-open-portal); MCP [`openBillingPortal`](https://openemail.uk/docs/mcp/tools/billing#openBillingPortal).

### `GET /billing/invoices`

List the charges

Every charge of the workspace with its invoice, as History on Plans & Billing lists them. `page` and `limit` page through them, `total` counts them all, and `search` matches the plan, the invoice number, the charge id and the name billed. `metered` is false when billing is off on this install.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Query parameters**

- `page` (`integer`, at least 1, default `1`): Which page, from 1.
- `limit` (`integer`, at least 1, at most 100, default `25`): Charges per page, 1 to 100.
- `sort` (`string`, one of `"newest"`, `"oldest"`, default `"newest"`): Newest or oldest first.
- `search` (`string`, up to 120 characters): Words to look for.

**Returns**

- `200` `BillingInvoiceList`: A page of charges.

**Errors**

- `502`: `billing_unreachable`: the billing provider did not answer.
- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.listInvoices()`](https://openemail.uk/docs/sdk/reference/billing#listInvoices); CLI [`openemail billing list-invoices`](https://openemail.uk/docs/cli/reference/billing#billing-list-invoices); MCP [`listInvoices`](https://openemail.uk/docs/mcp/tools/billing#listInvoices).

### `GET /billing/invoices/{orderId}`

Get the invoice of a charge

The link to the invoice of one charge, as a PDF, and its file name. An invoice that was not written yet is written first, from the billing details on the charge or on the account, which can take a few seconds. The link is signed by the billing provider, downloads the PDF and stops working after a while, so fetch it again rather than keeping it.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:read` scope.

- Scopes: `billing:read`.

**Path parameters**

- `orderId` (`string`, required): The id of a charge, as `GET /billing/invoices` lists it.

**Returns**

- `200` `BillingInvoiceLink`: The link to the invoice.

**Errors**

- `409`: `billing_details_required`: the charge has no billing name and address yet. `invoice_unavailable`: a draft or void charge has no invoice.
- `502`: `billing_unreachable`: the billing provider did not answer.
- `504`: `invoice_not_ready`: the invoice is still being written.
- The errors every operation can return: `400`, `401`, `403`, `404`, `422`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.getInvoice()`](https://openemail.uk/docs/sdk/reference/billing#getInvoice); CLI [`openemail billing get-invoice`](https://openemail.uk/docs/cli/reference/billing#billing-get-invoice); MCP [`getInvoice`](https://openemail.uk/docs/mcp/tools/billing#getInvoice).

### `PUT /billing/invoices/{orderId}/details`

Save the billing details of a charge

Saves the name and address billed on a charge, as the Billing address dialog does, keeps the address for later charges, and starts writing its invoice. `invoice` is `ready` when the charge already had one, `started` when it is being written, and `refused` with the reason in `message`. Read it with `GET /billing/invoices/{orderId}`.

Billing belongs to the owner of the workspace. An API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is refused with `owner_only`, and a key or token limited to particular addresses or domains with `capability_unsupported`. Reading needs `billing:read`, every change needs `billing:write`, and an OAuth access token needs a verification code for every change.

Requires the `billing:write` scope.

- Scopes: `billing:write`.
- Asks an OAuth access token for a verification code.

**Path parameters**

- `orderId` (`string`, required): The id of a charge, as `GET /billing/invoices` lists it.

**Request body**

- `name` (`string`, required, 1 to 200 characters): Who is billed, up to 200 characters.
- `line1` (`string`, required, 1 to 200 characters): The street address, up to 200 characters.
- `line2` (`string`, up to 200 characters): A flat, suite or building, up to 200 characters.
- `city` (`string`, required, 1 to 120 characters): Up to 120 characters.
- `postalCode` (`string`, up to 40 characters): Up to 40 characters.
- `state` (`string`, up to 60 characters): The state or region, up to 60 characters. In the US and Canada, its two-letter code.
- `country` (`string`, required, one of `"AD"`, `"AE"`, `"AF"`, `"AG"`, `"AI"`, `"AL"`, `"AM"`, `"AO"`, `"AQ"`, `"AR"`, `"AS"`, `"AT"`, `"AU"`, `"AW"`, `"AX"`, `"AZ"`, `"BA"`, `"BB"`, `"BD"`, `"BE"`, `"BF"`, `"BG"`, `"BH"`, `"BI"`, `"BJ"`, `"BL"`, `"BM"`, `"BN"`, `"BO"`, `"BQ"`, `"BR"`, `"BS"`, `"BT"`, `"BV"`, `"BW"`, `"BY"`, `"BZ"`, `"CA"`, `"CC"`, `"CD"`, `"CF"`, `"CG"`, `"CH"`, `"CI"`, `"CK"`, `"CL"`, `"CM"`, `"CN"`, `"CO"`, `"CR"`, `"CV"`, `"CW"`, `"CX"`, `"CY"`, `"CZ"`, `"DE"`, `"DJ"`, `"DK"`, `"DM"`, `"DO"`, `"DZ"`, `"EC"`, `"EE"`, `"EG"`, `"EH"`, `"ER"`, `"ES"`, `"ET"`, `"FI"`, `"FJ"`, `"FK"`, `"FM"`, `"FO"`, `"FR"`, `"GA"`, `"GB"`, `"GD"`, `"GE"`, `"GF"`, `"GG"`, `"GH"`, `"GI"`, `"GL"`, `"GM"`, `"GN"`, `"GP"`, `"GQ"`, `"GR"`, `"GS"`, `"GT"`, `"GU"`, `"GW"`, `"GY"`, `"HK"`, `"HM"`, `"HN"`, `"HR"`, `"HT"`, `"HU"`, `"ID"`, `"IE"`, `"IL"`, `"IM"`, `"IN"`, `"IO"`, `"IQ"`, `"IS"`, `"IT"`, `"JE"`, `"JM"`, `"JO"`, `"JP"`, `"KE"`, `"KG"`, `"KH"`, `"KI"`, `"KM"`, `"KN"`, `"KR"`, `"KW"`, `"KY"`, `"KZ"`, `"LA"`, `"LB"`, `"LC"`, `"LI"`, `"LK"`, `"LR"`, `"LS"`, `"LT"`, `"LU"`, `"LV"`, `"LY"`, `"MA"`, `"MC"`, `"MD"`, `"ME"`, `"MF"`, `"MG"`, `"MH"`, `"MK"`, `"ML"`, `"MM"`, `"MN"`, `"MO"`, `"MP"`, `"MQ"`, `"MR"`, `"MS"`, `"MT"`, `"MU"`, `"MV"`, `"MW"`, `"MX"`, `"MY"`, `"MZ"`, `"NA"`, `"NC"`, `"NE"`, `"NF"`, `"NG"`, `"NI"`, `"NL"`, `"NO"`, `"NP"`, `"NR"`, `"NU"`, `"NZ"`, `"OM"`, `"PA"`, `"PE"`, `"PF"`, `"PG"`, `"PH"`, `"PK"`, `"PL"`, `"PM"`, `"PN"`, `"PR"`, `"PS"`, `"PT"`, `"PW"`, `"PY"`, `"QA"`, `"RE"`, `"RO"`, `"RS"`, `"RW"`, `"SA"`, `"SB"`, `"SC"`, `"SD"`, `"SE"`, `"SG"`, `"SH"`, `"SI"`, `"SJ"`, `"SK"`, `"SL"`, `"SM"`, `"SN"`, `"SO"`, `"SR"`, `"SS"`, `"ST"`, `"SV"`, `"SX"`, `"SZ"`, `"TC"`, `"TD"`, `"TF"`, `"TG"`, `"TH"`, `"TJ"`, `"TK"`, `"TL"`, `"TM"`, `"TN"`, `"TO"`, `"TR"`, `"TT"`, `"TV"`, `"TW"`, `"TZ"`, `"UA"`, `"UG"`, `"UM"`, `"US"`, `"UY"`, `"UZ"`, `"VA"`, `"VC"`, `"VE"`, `"VG"`, `"VI"`, `"VN"`, `"VU"`, `"WF"`, `"WS"`, `"YE"`, `"YT"`, `"ZA"`, `"ZM"`, `"ZW"`): A two-letter ISO 3166 code, one of those `listCountries` returns.

**Returns**

- `200` `BillingInvoiceDetails`: Saved.

**Errors**

- `403`: The key lacks the scope, or may not send as that address. `step_up_required`: the call was made with an OAuth access token that has not been verified in the last 60 minutes. Ask for a code with `POST /security/step-up`, send it to `POST /security/step-up/verify`, then repeat the call. The person can also choose Allow changes for 60 minutes on the app in Account settings, Connected apps, on the OpenEmail website. An API key is never asked for a code.
- `422`: `billing_address_rejected`: the billing provider refused the address. `invalid_parameter`: the body did not validate.
- `502`: `billing_unreachable`: the billing provider did not answer.
- The errors every operation can return: `400`, `401`, `404`, `500`, described in the [error catalog](https://openemail.uk/docs/api/errors).

Also available in: SDK [`billing.saveInvoiceDetails()`](https://openemail.uk/docs/sdk/reference/billing#saveInvoiceDetails); CLI [`openemail billing save-invoice-details`](https://openemail.uk/docs/cli/reference/billing#billing-save-invoice-details); MCP [`saveBillingDetails`](https://openemail.uk/docs/mcp/tools/billing#saveBillingDetails).

### Objects

#### `Billing`

`object`

- `object` (`string`, required, one of `"billing"`)
- `workspaceId` (`string`, required)
- `workspaceName` (`string`)
- `plan` (`string`, required, one of `"free"`, `"starter"`, `"business"`, `"enterprise"`)
- `planName` (`string`)
- `metered` (`boolean`, required): False when billing is off on this install, and then nothing is capped.
- `interval` (`string`, nullable, one of `"month"`, `"year"`): How often the plan is billed. Null on Free.
- `renewsAt` (`string`, nullable, format `date-time`): When the plan renews, or ends when `cancelAtPeriodEnd` is true.
- `cancelAtPeriodEnd` (`boolean`): The plan was cancelled and ends at `renewsAt`.
- `nextCharge` (`object`, nullable): The next charge of the plan, when one is due. `cents` is null until it is known.
  - `cents` (`integer`, nullable)
  - `currency` (`string`, nullable)
  - `at` (`string`, format `date-time`)
- `domains` (`object`)
  - `used` (`integer`, at least 0): Domains in the workspace.
  - `included` (`integer`, nullable, at least 0): Domains the plan includes. Null when there is no limit.
  - `canAdd` (`boolean`)
- `usage` (`object`)
  - `sends` (`object`)
    - `used` (`integer`, at least 0): Used so far.
    - `limit` (`integer`, nullable, at least 0): What the plan includes. Null when there is no limit.
    - `resetsAt` (`string`, format `date-time`): When the monthly sends start again.
  - `aiActions` (`object`)
    - `used` (`integer`, at least 0): Used so far.
    - `limit` (`integer`, nullable, at least 0): What the plan includes. Null when there is no limit.
    - `resetsAt` (`string`, format `date-time`): When the daily AI actions start again.
- `payAsYouGo` (`object`)
  - `available` (`boolean`): Whether the plan of the workspace can buy anything past its allowances.
  - `enabled` (`boolean`): Whether usage past the allowances is being billed now: switched on and not paused.
  - `suspended` (`boolean`): Paused because the last payment failed. Update the card on the billing portal to resume.
  - `enrolled` (`boolean`): Whether pay as you go has ever been set up, with a card, on this workspace.
  - `switchedOn` (`boolean`): Whether it is switched on, paused or not.
  - `coversSends` (`boolean`): Whether sends past the monthly allowance can be bought on this plan.
  - `coversAiActions` (`boolean`): Whether AI actions past the daily allowance can be bought on this plan.
  - `limitCents` (`integer`): The monthly spending limit in US cents. Extras stop once a calendar month reaches it.
  - `spentCents` (`integer`, at least 0): What extras cost this calendar month so far, in US cents.
  - `extraSends` (`integer`, at least 0): Sends past the allowance this month.
  - `extraAiActions` (`integer`, at least 0): AI actions past the allowance this month.
  - `estimatedCents` (`integer`, at least 0): What those extras come to, in US cents.
- `availablePlans` (`string[]`, one of `"free"`, `"starter"`, `"business"`, `"enterprise"`): The plans sold on this install.

#### `BillingAlert`

`object`

- `object` (`string`, required, one of `"billing_alert"`)
- `id` (`string`, required): Stays the same while the same thing is true, so a dismissed alert can stay dismissed.
- `kind` (`string`, required, one of `"payment_failed"`, `"pay_as_you_go_paused"`, `"sending_paused"`, `"spend_limit_reached"`, `"ai_used_up"`, `"plan_ending"`, `"sends_nearly_used"`, `"spend_nearly_reached"`, `"upcoming_charge"`)
- `severity` (`string`, required, one of `"blocked"`, `"warning"`, `"info"`)
- `target` (`string`, required, one of `"billing"`, `"usage"`): Which tab of Plans & Billing it is about: the plan or the usage.
- `planName` (`string`, nullable)
- `at` (`string`, nullable, format `date-time`): When it happens: the charge, the end of the plan or the reset.
- `cents` (`integer`, nullable)
- `currency` (`string`, nullable)
- `used` (`integer`, nullable)
- `limit` (`integer`, nullable)
- `payAsYouGo` (`boolean`): Whether pay as you go can lift the limit it is about.

#### `BillingAlertList`

`object`

- `object` (`string`, one of `"list"`)
- `data` (`BillingAlert[]`)

#### `BillingCheckout`

`object`

- `object` (`string`, one of `"checkout"`)
- `url` (`string`, format `uri`)

#### `BillingCountryList`

`object`

- `object` (`string`, one of `"list"`)
- `data` (`string[]`)

#### `BillingInvoice`

`object`

- `object` (`string`, required, one of `"invoice"`)
- `id` (`string`, required): The charge id the invoice calls take.
- `createdAt` (`string`, required, format `date-time`)
- `amountCents` (`integer`, required)
- `subtotalCents` (`integer`)
- `currency` (`string`, required)
- `status` (`string`, nullable, one of `"draft"`, `"pending"`, `"paid"`, `"refunded"`, `"partially_refunded"`, `"void"`)
- `paid` (`boolean`)
- `reason` (`string`): Why it was charged: a purchase, a renewal or a change.
- `invoiceNumber` (`string`, nullable)
- `invoiceReady` (`boolean`): Whether its invoice was written.
- `needsBillingDetails` (`boolean`): Its invoice needs a billing name and address first.
- `billingName` (`string`, nullable)
- `product` (`string`, nullable)
- `payAsYouGo` (`boolean`): A charge for pay as you go extras.
- `discount` (`object`, nullable)
  - `code` (`string`, nullable)
  - `name` (`string`, nullable)
  - `amountCents` (`integer`)
  - `percentOff` (`number`, nullable)

#### `BillingInvoiceDetails`

`object`

- `object` (`string`, one of `"invoice_details"`)
- `orderId` (`string`)
- `invoice` (`string`, one of `"ready"`, `"started"`, `"refused"`)
- `message` (`string`, nullable): Why the invoice could not be started, when `invoice` is `refused`.

#### `BillingInvoiceLink`

`object`

- `object` (`string`, one of `"invoice_link"`)
- `orderId` (`string`)
- `url` (`string`, format `uri`): The link is signed by the billing provider, downloads the PDF and stops working after a while, so fetch it again rather than keeping it.
- `fileName` (`string`)

#### `BillingInvoiceList`

`object`

- `object` (`string`, one of `"list"`)
- `data` (`BillingInvoice[]`)
- `total` (`integer`, at least 0): How many charges there are in all.
- `page` (`integer`, at least 1)
- `limit` (`integer`, at least 1)
- `hasMore` (`boolean`)
- `metered` (`boolean`): False when billing is off on this install.

#### `BillingPlan`

`object`

- `object` (`string`, required, one of `"plan"`)
- `id` (`string`, required, one of `"free"`, `"starter"`, `"business"`, `"enterprise"`)
- `name` (`string`, required)
- `available` (`boolean`, required): Whether it is sold on this install.
- `intervals` (`string[]`, required, one of `"month"`, `"year"`): The billing intervals it is sold at. Empty for Free.
- `monthlyPriceCents` (`integer`, at least 0): The price billed monthly, in US cents a month.
- `yearlyMonthlyPriceCents` (`integer`, at least 0): The price billed yearly, in US cents a month.
- `includedDomains` (`integer`, nullable, at least 0): Domains it includes. Null when there is no limit.
- `monthlySends` (`integer`, nullable, at least 0): Sends it includes each calendar month. Null when there is no limit.
- `dailyAiActions` (`integer`, nullable, at least 0): AI actions it includes each day. Null when there is no limit.
- `teamAccess` (`boolean`): Whether members can be added.
- `prioritySupport` (`boolean`)
- `extraSends` (`boolean`): Whether pay as you go can buy sends past the allowance.
- `extraAiActions` (`boolean`): Whether pay as you go can buy AI actions past the allowance.

#### `BillingPlanList`

`object`

- `object` (`string`, one of `"list"`)
- `data` (`BillingPlan[]`)

#### `BillingPortal`

`object`

- `object` (`string`, one of `"billing_portal"`)
- `url` (`string`, format `uri`)

#### `BillingUsage`

`object`

- `object` (`string`, required, one of `"usage_history"`)
- `days` (`object[]`, required)
  - `day` (`string`, format `date`)
  - `aiActions` (`integer`, at least 0): AI actions that day.
  - `aiExtra` (`integer`, at least 0): Of those, the ones past the daily allowance, billed by pay as you go.
  - `sends` (`integer`, at least 0): Emails sent that day.
- `months` (`object[]`, required)
  - `month` (`string`): The month, as YYYY-MM.
  - `extraSends` (`integer`, at least 0): Sends billed by pay as you go.
  - `extraAiActions` (`integer`, at least 0): AI actions billed by pay as you go.
  - `sendCents` (`integer`, at least 0): What the extra sends cost, in US cents.
  - `aiCents` (`integer`, at least 0): What the extra AI actions cost, in US cents.
  - `cents` (`integer`, at least 0): Both, in US cents.
- `dailyAiActions` (`integer`, nullable, at least 0): AI actions the plan includes each day. Null when there is no limit.
- `monthlySends` (`integer`, nullable, at least 0): Sends the plan includes each month. Null when there is no limit.

#### `PayAsYouGo`

`object`

- `object` (`string`, required, one of `"pay_as_you_go"`)
- `available` (`boolean`, required): Whether the plan of the workspace can buy anything past its allowances.
- `enabled` (`boolean`, required): Whether usage past the allowances is being billed now: switched on and not paused.
- `suspended` (`boolean`): Paused because the last payment failed. Update the card on the billing portal to resume.
- `enrolled` (`boolean`): Whether pay as you go has ever been set up, with a card, on this workspace.
- `switchedOn` (`boolean`): Whether it is switched on, paused or not.
- `coversSends` (`boolean`): Whether sends past the monthly allowance can be bought on this plan.
- `coversAiActions` (`boolean`): Whether AI actions past the daily allowance can be bought on this plan.
- `limitCents` (`integer`): The monthly spending limit in US cents. Extras stop once a calendar month reaches it.
- `spentCents` (`integer`, at least 0): What extras cost this calendar month so far, in US cents.
- `extraSends` (`integer`, at least 0): Sends past the allowance this month.
- `extraAiActions` (`integer`, at least 0): AI actions past the allowance this month.
- `estimatedCents` (`integer`, at least 0): What those extras come to, in US cents.
- `limits` (`integer[]`, required, one of `1000`, `2500`, `5000`, `10000`, `25000`, `50000`, `100000`, `250000`, `500000`): The monthly limits that can be chosen, in US cents.
- `prices` (`object`, required): What extras cost: `priceCents` US cents for every `unit`.
  - `sends` (`object`)
    - `unit` (`integer`)
    - `priceCents` (`integer`)
  - `aiActions` (`object`)
    - `unit` (`integer`)
    - `priceCents` (`integer`)
- `period` (`object`, nullable): The current billing period of pay as you go. Null until it is set up.
  - `endsAt` (`string`, format `date-time`)
  - `sends` (`integer`, at least 0): Extra sends in the period.
  - `aiActions` (`integer`, at least 0): Extra AI actions in the period.
  - `estimatedCents` (`integer`, at least 0): What they come to, in US cents.

#### `PayAsYouGoConfirmation`

`object`

- `object` (`string`, one of `"pay_as_you_go_confirmation"`)
- `enabled` (`boolean`)

#### `PayAsYouGoLimit`

`object`

- `object` (`string`, one of `"pay_as_you_go_limit"`)
- `limitCents` (`integer`)

#### `PayAsYouGoSwitch`

`object`

- `object` (`string`, one of `"pay_as_you_go_switch"`)
- `enabled` (`boolean`)
- `suspended` (`boolean`)
- `activating` (`boolean`): A card was just saved, and pay as you go is being turned on.
- `checkoutUrl` (`string`, nullable): Where the person adds a card, the first time pay as you go is turned on.
