> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stora.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Set up authentication with the Stora Public API using access tokens or OAuth 2.0.

## Prerequisites

You'll need:

* A Stora account with an active operator
* A staff member with permission to manage API settings
* Access to BackOffice → Settings → Public API

<Note>
  Stora doesn't currently offer self-service sandbox access. Contact us directly if you need a test environment.
</Note>

## Choose your connection method

Stora supports two ways to authenticate. Both use the same scopes and the same `Authorization: Bearer <token>` header — they differ in how you get the token.

### Access tokens

A static secret key you generate directly in BackOffice. Use it immediately in requests — no token exchange needed.

**Good for:** scripts, internal tools, quick automations, exploring the API.

|          |                                             |
| -------- | ------------------------------------------- |
| Setup    | Instant — generate in BackOffice            |
| Security | The token is long-lived. Store it securely. |
| Expiry   | Configurable when you create it             |
| Scopes   | Configurable, can be modified later         |

### OAuth 2.0 applications

Short-lived access tokens issued via the OAuth 2.0 standard. Supports two grant types:

* **Client Credentials** — server-to-server, no user interaction required
* **Authorization Code** — for partner integrations where an operator authorises your app

**Good for:** production integrations, third-party apps, anything you share with others.

|          |                                                 |
| -------- | ----------------------------------------------- |
| Setup    | Create an application in BackOffice             |
| Security | Tokens are short-lived (2 hours)                |
| Expiry   | Automatic — request or refresh tokens as needed |
| Scopes   | Configurable, can be modified later             |

<Tip>
  Start with an access token to explore the API. Move to an OAuth application when you're building for production or distributing to third parties.
</Tip>

## Option A: Access token

<Steps>
  <Step title="Generate a token">
    Go to BackOffice → Settings → Public API and click **Generate Access Token**.
  </Step>

  <Step title="Choose your scopes">
    Start with read-only scopes (e.g. `public.site:read`).
  </Step>

  <Step title="Set an expiry date">
    Choose when the token should expire.
  </Step>

  <Step title="Copy the token">
    Copy it immediately — you won't be able to see it again.
  </Step>
</Steps>

Use it directly in requests:

```bash theme={null}
curl -X GET "https://public-api.stora.co/2025-09/sites" \
  -H "accept: application/json" \
  -H "authorization: Bearer YOUR_ACCESS_TOKEN"
```

## Option B: OAuth 2.0 — Client Credentials

Use this when your server needs to talk to Stora without user interaction.

<Steps>
  <Step title="Create an application">
    Go to BackOffice → Settings → Public API and click **Create Application**.
  </Step>

  <Step title="Choose your scopes">
    Select the scopes your application needs.
  </Step>

  <Step title="Note your credentials">
    Copy your `client_id` and `client_secret`.
  </Step>
</Steps>

Exchange your credentials for a short-lived access token:

```bash theme={null}
curl -X POST "https://public-api.stora.co/oauth2/token" \
  -H "content-type: application/json" \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "scope": "public.site:read"
  }'
```

Response:

```json theme={null}
{
  "access_token": "ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "public.site:read",
  "created_at": 1710000000
}
```

Use the `access_token` in subsequent requests. It expires after 2 hours (`expires_in: 7200`) — request a new one before it does.

## Option C: OAuth 2.0 — Authorization Code

Use this when building a partner integration where an operator's staff member authorises your app to access their data.

### Step 1: Redirect the user to authorise

Direct the user's browser to:

```
https://app.stora.co/oauth2/authorize?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=https://yourapp.com/callback&
  response_type=code&
  scope=public.contact:read public.order:read
```

The user logs in to the Stora BackOffice and approves the requested scopes. Stora redirects back to your `redirect_uri` with an authorisation code:

```
https://yourapp.com/callback?code=AUTHORIZATION_CODE
```

### Step 2: Exchange the code for tokens

```bash theme={null}
curl -X POST "https://public-api.stora.co/oauth2/token" \
  -H "content-type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://yourapp.com/callback"
```

Response:

```json theme={null}
{
  "access_token": "ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "public.contact:read public.order:read",
  "created_at": 1710000000,
  "refresh_token": "REFRESH_TOKEN"
}
```

### Refreshing tokens

Access tokens expire after 2 hours. Use the refresh token to get a new one without requiring the user to re-authorise:

```bash theme={null}
curl -X POST "https://public-api.stora.co/oauth2/token" \
  -H "content-type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "refresh_token=REFRESH_TOKEN"
```

The response includes a new `access_token` and a new `refresh_token`. The previous refresh token is revoked.

### PKCE (optional)

[PKCE](https://oauth.net/2/pkce/) (Proof Key for Code Exchange) protects the Authorization Code flow against code interception. Use it when your OAuth client is a single-user application running on a user-owned device — a mobile app, a desktop app, or a CLI tool.

<Warning>
  If you're distributing your integration as code that runs outside infrastructure you control (WordPress plugin, browser extension, client-side app extension, packaged on-premise tool, etc.), PKCE alone is not sufficient. Follow [Distributing a public plugin](/2025-09/guides/distributing-public-plugins) instead — the broker pattern it describes is the safe way to keep OAuth credentials and tokens out of distributed code.
</Warning>

Generate a `code_verifier` and `code_challenge` before redirecting:

```bash theme={null}
CODE_VERIFIER=$(openssl rand -base64 64 | tr -d '=/+\n' | head -c 128)
CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl dgst -sha256 -binary | base64 | tr -d '=' | tr '/+' '_-')
```

Add the challenge to the authorisation URL:

```
https://app.stora.co/oauth2/authorize?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=https://yourapp.com/callback&
  response_type=code&
  scope=public.contact:read public.order:read&
  code_challenge=CODE_CHALLENGE&
  code_challenge_method=S256
```

Include the `code_verifier` when exchanging the code:

```bash theme={null}
curl -X POST "https://public-api.stora.co/oauth2/token" \
  -H "content-type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://yourapp.com/callback" \
  -d "code_verifier=CODE_VERIFIER"
```
