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

# Authentication

> OAuth 2.0 client credentials — how to get a token and use it.

## Overview

SignProof uses **OAuth 2.0 client credentials** for all API access. You exchange a
`client_id` + `client_secret` for a short-lived bearer token, then pass that token on every request.

Signers never use this auth flow — they access their specific envelope via a tokenized one-time link
(no account required).

***

## Get your credentials

1. Log in to the [SignProof Console](https://console.thesignproof.com)
2. Go to **Settings → Applications**
3. Create an application — you'll receive a `client_id` and `client_secret`
4. The `client_secret` is shown **once** at creation time. Store it in your secrets manager immediately.

***

## Mint a token

```bash theme={null}
curl -X POST https://api.thesignproof.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
```

```json theme={null}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}
```

**Token TTL: 1 hour.** Cache the token and refresh it before it expires — do not mint a new token on
every request.

***

## Use the token

Pass the token as an `Authorization` header on every API request:

```bash theme={null}
curl https://api.thesignproof.com/v1/envelopes/env_01HX... \
  -H "Authorization: Bearer eyJhbGci..."
```

***

## Scopes

All tokens issued via client credentials have access to all endpoints within your application's
scope. There is no per-request scope narrowing in v1.

***

## Token expiry and refresh

<Warning>
  Tokens expire after 1 hour. If you receive a `401 Unauthorized` response, mint a new token.
  Do not retry the failed request with the same token.
</Warning>

Recommended pattern:

```python theme={null}
import time

class TokenCache:
    def __init__(self):
        self._token = None
        self._expires_at = 0

    def get(self):
        if time.time() < self._expires_at - 60:  # 60s buffer
            return self._token
        response = mint_token()
        self._token = response["access_token"]
        self._expires_at = time.time() + response["expires_in"]
        return self._token
```

***

## Error responses

| Status             | Meaning                                                   |
| ------------------ | --------------------------------------------------------- |
| `401 Unauthorized` | Missing or expired token                                  |
| `403 Forbidden`    | Token is valid but you don't have access to this resource |

***

## Security

* **Never expose your `client_secret` in client-side code** (browsers, mobile apps). All SignProof
  API calls must come from your backend.
* Store credentials in your secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.) — not in
  environment variables checked into source control.
* Rotate credentials in the Console if you suspect a secret has been compromised.
