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

# How to authenticate Safeclose API requests

> Obtain a session JWT from your active Safeclose login and pass it as a Bearer token on every API call. Includes token expiry and error handling.

The Safeclose API uses Bearer token authentication. Every request to a `/v1/` endpoint must include an `Authorization` header containing a valid Clerk JWT session token. This page explains how to get that token and how to use it.

## How it works

When you sign into Safeclose, Clerk issues a short-lived JWT session token that encodes your identity. The Safeclose API verifies this token on every request using your Clerk secret key. If the token is valid, the API resolves your user identity from the database to determine what you can access based on your role.

You never send a username or password directly to the API — only the JWT.

## Getting your token

### From browser DevTools

1. Sign into Safeclose in your browser.
2. Open DevTools (`F12` or `Cmd+Option+I`) and go to the **Network** tab.
3. Make any action in the app that triggers a network request, or navigate to a page that loads data.
4. Click any request to `/v1/` in the request list.
5. Under **Request Headers**, copy the value of the `Authorization` header (everything after `Bearer `).

### From Clerk's client-side SDK

If you are building a client-side integration, use Clerk's [`getToken()`](https://clerk.com/docs/references/javascript/session#get-token) method:

```javascript theme={null}
const token = await clerk.session.getToken();
```

Pass the returned string as your Bearer token.

## Making authenticated requests

Include the token in the `Authorization` header on every request:

```http theme={null}
Authorization: Bearer <your-session-token>
```

<CodeGroup>
  ```bash curl theme={null}
  curl https://your-api.example.com/v1/signing/session \
    -H "Authorization: Bearer <your-session-token>"
  ```

  ```javascript fetch theme={null}
  const response = await fetch('https://your-api.example.com/v1/signing/session', {
    headers: {
      'Authorization': `Bearer ${token}`,
    },
  });
  const data = await response.json();
  ```

  ```python requests theme={null}
  import requests

  response = requests.get(
      'https://your-api.example.com/v1/signing/session',
      headers={'Authorization': f'Bearer {token}'},
  )
  data = response.json()
  ```
</CodeGroup>

For requests that include a body, also set `Content-Type: application/json`:

```bash theme={null}
curl https://your-api.example.com/v1/signing/manager/signings \
  -X POST \
  -H "Authorization: Bearer <your-session-token>" \
  -H "Content-Type: application/json" \
  -d '{"locationId": 42}'
```

## Token expiry

Clerk session tokens are short-lived. For interactive use, your token refreshes automatically while your browser session is active. For scripts or automated workflows, you need to obtain a fresh token before it expires — do not store tokens long-term.

<Warning>
  If you are writing a long-running script, fetch a new token at the start of each run rather than reusing a saved token. Expired tokens return a `401` response.
</Warning>

## Token errors

| Status | Error message                         | What to do                                                                                                 |
| ------ | ------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `401`  | `Missing Authorization Bearer token.` | Add the `Authorization: Bearer <token>` header to your request                                             |
| `401`  | `Empty bearer token.`                 | Make sure the token value is not empty after `Bearer `                                                     |
| `401`  | `Invalid or expired token.`           | Re-authenticate in Safeclose and get a fresh token                                                         |
| `403`  | *(resource-specific message)*         | Your token is valid, but your role does not have access to this resource — contact your organization admin |

## Roles and access

The API resolves your identity from the token's `sub` claim (your Clerk user ID) and looks up your corresponding records in the database. What you can read and write depends on your assigned role:

| Role        | Access                                                                                                          |
| ----------- | --------------------------------------------------------------------------------------------------------------- |
| **Signer**  | Your own assigned signing packages, their documents, and co-signer information                                  |
| **Manager** | Organizations, companies, locations, signing packages, templates, and flows scoped to your employee memberships |
| **Admin**   | Global read access across all organizations and companies, subject to per-resource caps                         |

<Note>
  Your organization admin sets up your role. If you receive a `403` on a resource you expect to access, ask your admin to verify that your account has the appropriate role and scope assigned.
</Note>
