> ## Documentation Index
> Fetch the complete documentation index at: https://www.1password.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# API conventions

> Conventions used across the 1Password Accounts API for Partners, including authentication, resource paths, pagination, filtering, and error handling.

The following conventions apply across the 1Password Accounts API for Partners.

## Authentication

The Accounts API authorizes requests with a bearer token. When your organization registers as a distributor, you'll receive an opaque bearer token, prefixed with `op_b_`. Include this token in the `Authorization` header of every request, prefixed with `Bearer`:

```
Authorization: Bearer <YOUR_API_TOKEN>
```

For example:

```shell theme={null}
curl --request GET \
  --url "https://api.1password.eu/v1/distributor-products" \
  --header "Authorization: Bearer <YOUR_API_TOKEN>"
```

<Warning>
  Treat your bearer token like a password. Store it securely (for example, in a 1Password vault) and never expose it in client-side code, logs, or source control.
</Warning>

If you need a new bearer token, [contact 1Password](mailto:msp@1password.com).

## Endpoints

The basic structure of an endpoint URL for the Accounts API includes the [base URL](#base-url) and the [endpoint path](#endpoint-path). The endpoint path includes the API endpoint version, the resource(s) you want to access, and any relevant path parameters.

### Base URL

All requests to the Accounts API use the 1Password.eu base URL, `https://api.1password.eu`, regardless of the [region of your 1Password account](https://support.1password.com/regions/) or your customers' accounts. The [`product_id`](/accounts-api/list-products) you provision determines the region where a customer's 1Password account is created.

All communication with the API is over HTTPS.

### Endpoint path

The endpoint path is appended to the base URL and includes the endpoint version, target resource path, and any path parameters. For example, the endpoint path to list usage for a specific customer would look like this:

```
/v1/distributor-customers/{distributor-customer}/usage
```

The `{distributor-customer}` path parameter is your own identifier for the customer, as defined in your marketplace system — 1Password doesn't validate it against a customer registry. Some list endpoints also accept `-` as a wildcard to query across all of your customers.

See the [API reference documentation](/accounts-api/reference) for more information about each endpoint.

## Requests

### Request methods

Requests to the Accounts API use standard HTTP methods:

| Method | Usage |
| - | - |
| `GET` | Retrieve resources. For example: [list entitlements](/accounts-api/list-entitlements), [customer usage](/accounts-api/list-customer-usage), or [products](/accounts-api/list-products). |
| `POST` | Create resources. For example: [create](/accounts-api/create-entitlement) or [link](/accounts-api/link-entitlement) an entitlement. |
| `PATCH` | Update specific fields of a resource. For example: [update a pending entitlement](/accounts-api/update-entitlement). |
| `DELETE` | Initiate removal of a resource. For example: [cancel an entitlement](/accounts-api/cancel-entitlement). |

### Request headers

```
Authorization: Bearer <YOUR_API_TOKEN>
Content-Type: application/json
```

* **`Authorization`**: Required on every request. Use this header with your bearer token to authenticate your API requests.
* **`Content-Type: application/json`**: Required for `POST` and `PATCH` requests. Use this header for requests that send a JSON body. `GET` and `DELETE` requests don't include a body.

### Request bodies

`POST` and `PATCH` requests send a JSON object in the request body. Check the [API reference documentation](/accounts-api/reference) for the fields each endpoint accepts.

The API silently ignores unknown fields in request bodies, so make sure your field names are correct. A misspelled field name is ignored without an error and the value isn't applied.

`GET` and `DELETE` requests don't include a request body.

## Query parameters

You can use query parameters in your API request as optional modifiers after the endpoint path. Use a `?` query separator at the end of the endpoint path, then add any query parameters you want to include, separated by a `&` query delimiter.

For example, if you want to retrieve a list of product usage data for all customers, you could use query parameters to [filter the results](#filtering) by billing cycle and set the maximum number of results to return per [page](#pagination):

```text theme={null}
GET https://api.1password.eu/v1/distributor-customers/-/usage?filter=billing_cycle == '2026-04'&max_page_size=20
```

Make sure your client URL-encodes query parameter values. Filter expressions contain spaces and special characters, so the request above is sent as:

```text theme={null}
GET https://api.1password.eu/v1/distributor-customers/-/usage?filter=billing_cycle%20%3D%3D%20%272026-04%27&max_page_size=20
```

Check the [API reference documentation](/accounts-api/reference) to discover which query parameters are available for each endpoint.

### Filtering

The following list endpoints accept a `filter` query parameter that uses [Common Expression Language (CEL) <Icon icon="arrow-up-right-from-square" />](https://github.com/google/cel-spec) syntax:

* [List entitlements](/accounts-api/list-entitlements): Filters on entitlement fields. For example, `status == 'active'` returns only active entitlements. When omitted, entitlements of all statuses are returned. See the [entitlement statuses](#entitlement-statuses) section to learn about all the possible `status` values.
* [List customer usage](/accounts-api/list-customer-usage): Filters by billing cycle using `billing_cycle == 'YYYY-MM'`. For example, `billing_cycle == '2026-04'`. When omitted, usage defaults to the current billing cycle in UTC. There's no lookback limit on historical billing cycles.

### Pagination

```shell theme={null}
curl --request GET \
  --url "https://api.1password.eu/v1/distributor-products?max_page_size=20&page_token=<NEXT_PAGE_TOKEN>" \
  --header "Authorization: Bearer <YOUR_API_TOKEN>"
```

All list endpoints (entitlements, customer usage, and products) support pagination. Use these query parameters to page through results:

* `max_page_size`: The maximum number of results to return per page. Defaults to 100; values above 100 are clamped to 100. Omitting the parameter or setting it to `0` uses the default.
* `page_token`: The token that identifies the page of results to return.

Each list response includes an opaque `next_page_token`. To retrieve the next page, send the same request with `page_token` set to that value. When `next_page_token` is empty, there are no more results.

The API uses cursor-based pagination. Each token marks where the previous page left off, so paging stays consistent even if results change between page requests. Items already returned aren't repeated on later pages, and items aren't skipped if others are created or cancelled while you page.

## Responses

The API returns JSON for all responses, except [rate-limit](#rate-limits) errors, which return plain text.

A successful request returns `200 OK`.

Create, update, and cancel operations return the affected entitlement in the response body, so you can read back its server-assigned fields, such as `id`, `create_time`, and the current `status`. Link operations return the entitlement inside an `entitlement` object. For example, a successful create request returns:

```json theme={null}
HTTP/2 200
date: Fri, 30 Oct 2026 12:34:56 GMT
content-type: application/json

{
  "path": "distributor-customers/cust_789xyz/entitlements/ent_abc123def456",
  "id": "ent_abc123def456",
  "customer_id": "cust_789xyz",
  "product_id": "1p-msp-us",
  "status": "pending",
  "contact_info": {
    "email": "admin@acme-corp.com",
    "company_name": "Acme Corporation"
  },
  "create_time": "2026-09-15T10:30:00Z"
}
```

List operations return a `results` array and a `next_page_token`. For example:

```json theme={null}
{
  "results": [
    {
      "path": "distributor-customers/cust_789xyz/entitlements/ent_abc123def456",
      "id": "ent_abc123def456",
      "customer_id": "cust_789xyz",
      "product_id": "1p-msp-us",
      "status": "active",
      "contact_info": {
        "email": "admin@acme-corp.com",
        "company_name": "Acme Corporation"
      },
      "create_time": "2026-09-15T10:30:00Z",
      "expire_time": "2026-09-20T10:30:00Z"
    }
  ],
  "next_page_token": ""
}
```

When a list request matches no results, the response returns an empty `results` array and an empty `next_page_token`.

```json theme={null}
{
  "results": [],
  "next_page_token": ""
}
```

Learn more about [error responses](#errors) and [paginated list responses](#pagination).

### Dates and times

Timestamps are returned in [RFC 3339 format <Icon icon="arrow-up-right-from-square" />](https://datatracker.ietf.org/doc/html/rfc3339), for example `2026-01-23T15:55:58Z`.

## Rate limits

Requests to the Accounts API are rate limited to 1,000 requests per minute, per distributor. There's no separate hourly limit.

If you exceed the allowed rate, the API returns a `429 Too Many Requests` response with a `Retry-After` header that indicates how long to wait before retrying. Unlike other error responses, the `429` response body is plain text, not JSON.

## Errors

The API uses standard HTTP status codes to indicate the result of a request. A `2xx` code indicates success. A `4xx` code indicates a problem with the request (for example, missing authentication or invalid input). A `5xx` code indicates an unexpected server error.

Most error responses include a JSON body with a machine-readable `code` and a human-readable `message`:

```json theme={null}
{
  "code": "not_found",
  "message": "The requested resource was not found."
}
```

| Status | Code | Meaning |
| - | - | - |
| `400` | `invalid_argument` | A request parameter or body field is invalid. |
| `401` | `unauthenticated` | Missing or invalid credentials. |
| `404` | `not_found` | The resource doesn't exist. |
| `409` | `already_exists` | The resource already exists — for example, an entitlement for the product already exists. |
| `500` | `internal` | An internal error occurred. Retry the request later. |

`429 Too Many Requests` responses don't use this JSON format. See the [rate limits](#rate-limits) section for more information about this error response.

## Entitlement statuses

An entitlement's `status` field reflects its position in the lifecycle:

| Status | Meaning |
| - | - |
| `pending` | The entitlement has been created and is waiting for the customer to activate it (or, for [linked entitlements](/accounts-api/link-entitlement), claim the entitlement code). Only pending entitlements can be [updated](/accounts-api/update-entitlement). |
| `active` | The entitlement is active and the product is provisioned. |
| `cancelling` | [Cancellation](/accounts-api/cancel-entitlement) has been initiated. Background processing completes it and transitions the status to `cancelled`. |
| `cancelled` | The entitlement has been cancelled. |
| `expired` | A [change-of-channel entitlement](/accounts-api/link-entitlement) whose entitlement code wasn't claimed within 5 days of creation. |


## Related topics

- [Get started with the 1Password Accounts API for Partners](/accounts-api/get-started.md)
- [1Password Accounts API for Partners](/accounts-api.md)
- [Reference for the 1Password Accounts API for Partners](/accounts-api/reference.md)
