> ## 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 Users API, including authorization, endpoint paths, request headers, pagination, filtering, rate limits, and error handling.

The conventions below apply across the 1Password Users API, where applicable, including how to authorize requests, structure requests, and interpret responses and errors.

The Users API is a REST-style API that supports standard HTTP methods and follows the [OpenAPI 3.1.0 specification <Icon icon="arrow-up-right-from-square" />](https://spec.openapis.org/oas/v3.1.0.html). All communication between clients and servers is over HTTPS.

## Authorization

The Users API uses the [OAuth 2.0 authorization framework](https://datatracker.ietf.org/doc/html/rfc6749) to allow an application to act on behalf of your organization. The authorization process uses the [client credentials grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4) flow to issue access tokens to authenticated clients:

1. [Create an OAuth application](/users-api/authorization#create-an-oauth-application) in your 1Password account to generate scoped client credentials.

2. Make a POST call to the [OAuth 2.0 token request endpoint](/users-api/request-access-token) that includes your client credentials to request a scoped access token.

3. Send the access token in the `Authorization` header when calling the Users API endpoints, prefixed with `Bearer`:

   ```
   Authorization: Bearer <YOUR_ACCESS_TOKEN>
   ```

4. Request a new token when the current one expires, or revoke a token when it's no longer needed.

Access tokens have a limited lifespan of 15 minutes (900 seconds), after which the client needs to request a new access token.

Learn more about [how to authorize your integrations using OAuth 2.0](/users-api/authorization).

## Endpoints

The basic structure of an endpoint URL for the Users API includes the base URL and the endpoint path. The endpoint path includes the API endpoint version, the resource(s) you want to access, and any relevant path and query parameters.

### Base URLs

The base URL of an endpoint URL indicates the server that hosts the environment you want to work in. Use the base URL that matches the [region of the 1Password account](https://support.1password.com/regions/) you want to access.

| Base URL | Description |
| - | - |
| `https://api.1password.com` | Server for working with accounts hosted in the 1Password.com region. |
| `https://api.1password.ca` | Server for working with accounts hosted in the 1Password.ca region. |
| `https://api.1password.eu` | Server for working with accounts hosted in the 1Password.eu region. |
| `https://api.ent.1password.com` | Server for working with accounts hosted on ent.1password.com. |

Integrations should be designed to allow the base URL to be configurable to accommodate accounts in different regions.

### Endpoint paths

Endpoint paths are appended to the base URL and include the endpoint version, target resource path, and any path parameters. For example, the endpoint path to retrieve a single user in a 1Password account looks like this:

```
/v1/accounts/{account}/users/{user}
```

The `{account}` path parameter is the unique identifier of the 1Password account, and the `{user}` path parameter is the unique identifier of the user. Both are 26-character uppercase IDs, for example `WX52YXL2MVEPBK43P3R4XMWKXI`. A malformed ID returns `400 Bad Request`, and an ID that doesn't exist returns `404 Not Found`.

The path may also include a custom action, which is indicated by a colon (`:`) separator followed by an action verb. For example: `:suspend` or `:reactivate`. Custom actions are placed at the end of the endpoint path and before any query parameters:

```
POST https://api.1password.eu/v1/accounts/{account}/users/{user}:suspend
```

Endpoint paths are matched exactly. Don't add a trailing slash, and don't include the `:suspend` or `:reactivate` action on endpoints that don't support it.

Check the [API reference documentation](/users-api/reference) for more information about the available endpoints.

## Requests

### Request methods

Requests to the Users API use standard HTTP methods:

| Method | Usage |
| - | - |
| `GET` | Retrieve resources. For example: [list users](/users-api/list-users) or [get a user](/users-api/get-user). |
| `POST` | Perform an action on a resource. For example: [suspend](/users-api/suspend-user) or [reactivate](/users-api/reactivate-user) a user. |

The Users API accepts JSON over HTTPS only. Requests that use gRPC or Connect protocols return `415 Unsupported Media Type`.

### Request headers

* **`Authorization`**: Your OAuth access token, prefixed with `Bearer`. Required on every request. See [Authorization](#authorization).
* **`User-Agent`**: Recommended. Send an identifiable `User-Agent` header in the format `<CompanyOrProductName>/<version>` so requests can be attributed to a specific integration. This helps with support and troubleshooting, and with analytics on integration usage.

```
Authorization: Bearer <YOUR_ACCESS_TOKEN>
User-Agent: AcmeSOAR/1.0.0
```

Requests to the OAuth API endpoints send their parameters as a URL-encoded form and require a `Content-Type: application/x-www-form-urlencoded` header. Learn more about [requesting an access token](/users-api/authorization#request-an-access-token).

### Request bodies

Users API requests don't include a request body. The [suspend](/users-api/suspend-user) and [reactivate](/users-api/reactivate-user) actions identify the target user in the endpoint path.

## 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, you can list users in an account and use query parameters to [filter the results](#filtering) to active users and set the maximum number of results to return per [page](#pagination):

```text theme={null}
GET https://api.1password.com/v1/accounts/{account}/users?filter=user.isActive()&max_page_size=100
```

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

```text theme={null}
GET https://api.1password.com/v1/accounts/{account}/users?filter=user.isActive%28%29&max_page_size=100
```

Check the [API reference documentation](/users-api/reference) for more information about the available query parameters for each endpoint. A request that includes a query parameter the endpoint doesn't support returns `400 Bad Request`.

### Filtering

The [list users](/users-api/list-users) endpoint accepts a `filter` query parameter to return only users in a specific [state](#user-states):

* `user.isActive()` returns only active users.
* `user.isSuspended()` returns only suspended users.

Filter values are case-sensitive and must match exactly. When the filter is omitted or empty, both active and suspended users are returned. Any other value returns `400 Bad Request` with an `invalid_argument` error, for example: `invalid filter "user.isDeleted()": must be "user.isActive()" or "user.isSuspended()"`.

### Pagination

The [list users](/users-api/list-users) endpoint supports token-based pagination. Use these query parameters to page through results:

* `max_page_size`: The maximum number of users to return per page. Defaults to 100 when omitted or set to `0`. The maximum is 1000; values greater than 1000 are limited to 1000, and negative values return `400 Bad Request`.
* `page_token`: The token that identifies the page of results to return.

If more than one page of results is available, the response includes an opaque `next_page_token`. To retrieve the next page, send the same request with `page_token` set to that value. Repeat until the response no longer includes a `next_page_token`. A page with no results is returned as an empty JSON object (`{}`), so treat a missing `results` field as an empty list.

When you send a `page_token`, include the same `filter` value as the original request; the token doesn't store it. `max_page_size` is ignored on requests that include a `page_token`, because the page size is fixed by the token. Page tokens don't expire. If users are added, suspended, or reactivated while you page through results, some users may shift between pages.

```shell theme={null}
curl --request GET \
  --url "https://api.1password.com/v1/accounts/<account_id>/users?max_page_size=100&page_token=<NEXT_PAGE_TOKEN>" \
  --header "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
  --header "User-Agent: <CompanyOrProductName>/<version>"
```

## Responses

The API returns JSON (`application/json`) for all responses.

A successful request returns `200 OK`. The [suspend](/users-api/suspend-user) and [reactivate](/users-api/reactivate-user) actions return the updated user in the response body, so you can read back the user's current `state`.

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 `2024-01-15T10:30:00Z`.

## Rate limits

Requests to the Users API are rate limited per 1Password account and per endpoint:

* 100 requests per minute
* 6,000 requests per hour

Every response from the Users API includes `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` headers that report the current limit, how many requests remain in the window, and when the window resets (as a Unix timestamp in seconds). Rate limits are applied before a request's scopes are checked, so requests that return `403 Forbidden` also count toward the limit. Requests that are rejected because the access token is missing or invalid (`401 Unauthorized`) don't reach the API, so they don't include the `RateLimit-*` headers and don't count toward the limit.

Requests to the [OAuth API endpoints](/users-api/authorization#authorization-endpoints) (token, introspection, and revocation) are rate limited separately. The limits are shared across the three endpoints:

* Per OAuth application: 60 requests per minute and 3,600 requests per hour
* Per 1Password account: 600 requests per minute and 36,000 requests per hour

If you exceed the allowed rates, the API returns a `429 Too Many Requests` response with a `Retry-After` header that indicates how long to wait, in seconds, before retrying. Rate-limited Users API responses use the standard [error format](#errors) with the `resource_exhausted` code and include the `RateLimit-*` headers with `RateLimit-Remaining: 0`. Rate-limited OAuth API responses include a JSON error body with the `slow_down` error code.

## 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 authorization or invalid input). A `5xx` code indicates an unexpected server error.

Error responses use a consistent format with a machine-readable `code` and a human-readable `message`:

```json theme={null}
{
  "code": "invalid_argument",
  "message": "invalid filter \"user.isDeleted()\": must be \"user.isActive()\" or \"user.isSuspended()\""
}
```

<Warning>
  The error response format, including the `code` and `message` fields, is provisional and may change in a future release. Use the HTTP status code to handle errors in your integration, and don't rely on the text of the `message` field.
</Warning>

| Status | Code | Meaning |
| - | - | - |
| `400 Bad Request` | `invalid_argument` | A request parameter is invalid. For example, an unsupported `filter` value, an unsupported query parameter, an invalid `page_token`, a negative `max_page_size`, a malformed account or user ID, or a malformed `Authorization` header (`malformed authorization header`). Also returned when the target user is a service account (`user_is_service_account`), which can't be suspended or reactivated. |
| `400 Bad Request` | `failed_precondition` | The user can't be [suspended](/users-api/suspend-user) or [reactivated](/users-api/reactivate-user) in their current state, for example because they're pending confirmation (`user_not_suspendable`, `user_not_reactivatable`). |
| `401 Unauthorized` | `unauthenticated` | The request doesn't include a valid access token. The `Authorization` header is missing (`authentication required`), or the token is invalid, expired, or revoked (`invalid access token`). Also returned for tokens that weren't issued by the [OAuth API](/users-api/authorization), such as tokens from the legacy OAuth service. [Request a new access token](/users-api/authorization#request-an-access-token). |
| `403 Forbidden` | `permission_denied` | The access token doesn't include the [scope](/users-api/authorization#scopes) required for the endpoint, the account ID in the path doesn't belong to the OAuth application's account (`account_uuid_mismatch`), or the action isn't allowed for the target user, for example when [suspending](/users-api/suspend-user#restrictions) the last remaining owner of an account. |
| `404 Not Found` | `not_found` | The user doesn't exist. |
| `415 Unsupported Media Type` | `invalid_argument` | The request used a gRPC or Connect content type. The API accepts JSON only. |
| `429 Too Many Requests` | `resource_exhausted` | The rate limit was exceeded. See [Rate limits](#rate-limits). |
| `500 Internal Server Error` | `internal` | An unexpected error occurred. Retry the request later. |
| `503 Service Unavailable` | `unavailable` | The service is temporarily unavailable. Retry the request later. |

Requests with a missing, invalid, expired, or revoked access token are rejected before they reach the API. The response is `401 Unauthorized` with the `unauthenticated` code and a `WWW-Authenticate: Bearer` header. When a token was sent but isn't valid, the header also includes `error="invalid_token"`:

```http theme={null}
HTTP/2 401
Content-Type: application/json
WWW-Authenticate: Bearer realm="1Password", error="invalid_token", error_description="invalid access token"

{
  "code": "unauthenticated",
  "message": "invalid access token"
}
```

A malformed `Authorization` header, for example `Bearer` with no token or a token followed by extra text, returns `400 Bad Request` with the `invalid_argument` code and a `WWW-Authenticate: Bearer` header that includes `error="invalid_request"`. These responses don't include the `RateLimit-*` headers. [Request a new access token](/users-api/authorization#request-an-access-token) if the token has expired.

## Audit events

[User lifecycle actions](/events-api/beta/audit-events#user-lifecycle) performed through the Users API are recorded in your account's audit log and identify `Oauth app` as the actor. Suspending a user generates a `user.suspend` audit event, and reactivating a user generates a `user.reactivate` audit event.

You can review these events in your account's [audit log](https://support.1password.com/audit-log/) or retrieve them with the [1Password Events API](/events-api).

## User states

A user's `state` field reflects their current status in the 1Password account:

| State | Meaning |
| - | - |
| `ACTIVE` | The user has access to the account. Active users can be [suspended](/users-api/suspend-user). |
| `SUSPENDED` | The user's access to the account has been suspended. Suspended users can be [reactivated](/users-api/reactivate-user). |
| `STATE_UNSPECIFIED` | The user is in another state, for example pending confirmation or account recovery. For these users, the `state` field is omitted from the response, they aren't included in [list users](/users-api/list-users) results, and they can't be suspended or reactivated (`400 Bad Request`, `failed_precondition`). |

Users who have been invited but haven't joined the account yet don't have a user ID and aren't available through the API.

Additional states may be added in the future. Make sure your integration handles unknown values, and a missing `state` field, gracefully.


## Related topics

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