# Authentication

The Understory API requires you to authenticate yourself in most endpoints.
To authenticate your requests you need to provide an access token which is based on your integration credentials.

## About the protocol

We use the standard [OAuth2.0 protocol](https://oauth.net/2/) with [Open ID Connect (OIDC)](https://openid.net/developers/how-connect-works/).
These are industry standards and most programming languages and frameworks support these out of the box.

## Which authentication method do I need?

Understory supports two authentication methods depending on your use case:

| **Method** | **Use Case** | **Grant Type** |
|  --- | --- | --- |
| [Internal Integration Keys](/docs/usage/authentication/integration-keys) | You are an Understory customer building tools to automate or extend your own Understory account. Your integration accesses only your own data. | `client_credentials` |
| [Third-Party Integration](/docs/usage/authentication/third-party-integrations) | You are building an application that will access other Understory customers' data with their permission. Examples include marketplaces, marketing tools, and accounting integrations. | `authorization_code` |


## Endpoint configuration

Below are the protocol endpoints which can be used to configure your client of choice.

| Description | Endpoint |
|  --- | --- |
| Issuer | `https://api.auth.understory.io` |
| OpenID Connect Discovery Endpoint | `https://api.auth.understory.io/.well-known/openid-configuration` |
| Token | `https://api.auth.understory.io/oauth2/token` |
| Authorize | `https://api.auth.understory.io/oauth2/auth` |


## Access tokens

Both methods end with an access token, which you send in the `Authorization: Bearer <token>` header on every API call.
The token response tells you how long the token is valid in `expires_in`, in seconds; access tokens last about one hour.

Reuse your access token
Request an access token once and send it on every API call until it is about to expire.
Keep it in memory, or in a shared cache when several processes call the API.
Request a new one a few minutes before `expires_in` runs out, or when a call returns `401 Unauthorized`.

Do not request a new token for each API call.
The token endpoint and the API are rate limited, and a token per call doubles your request count, slows every call down, and gets your integration throttled.

How you get a new token depends on the method:

- **Internal integration keys** request a new token with the same `client_credentials` call. See [Reuse the token in your code](/docs/usage/authentication/integration-keys#reuse-the-token-in-your-code).
- **Third-party integrations** exchange their refresh token for a new access token without user interaction. See [Refreshing access tokens](/docs/usage/authentication/third-party-integrations#refreshing-access-tokens).


A `401 Unauthorized` response means the token is missing, expired or revoked.
A `403 Forbidden` response means the token is valid but lacks the scope the endpoint requires; a new token with the same scopes will not help.

Treat access tokens as opaque strings.
Their format can change at any time and is not covered by the [breaking changes](/docs/about/breaking-changes) policy.

## Scopes

Scopes define what resources and actions your integration can access.
Request only the scopes your application needs following the [principle of least privilege](https://csrc.nist.gov/glossary/term/least_privilege).

| **Scope** | **Description** |
|  --- | --- |
| `booking.read` | Read access to bookings |
| `booking.write` | Create and modify bookings |
| `event.read` | Read access to events and availability |
| `experience.read` | Read access to experiences |
| `gift-card.read` | Read access to gift cards |
| `gift-card.write` | Modify gift cards |
| `marketing.read` | Read access to marketing consents |
| `order.read` | Read access to orders |
| `webhook.read` | Read access to webhook subscriptions |
| `accounting.read` | Read access to accounting data |
| `accounting.write` | Create and modify accounting data |
| `webhook.write` | Create, modify, and delete webhook subscriptions |
| `location.read` | Read access to locations |
| `offline` | Enables refresh tokens for long-lived access (required for third-party integrations) |


Refer to the [API Reference](/apis) for detailed information about which endpoints require which scopes.