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

# Authenticate with the SURCHI API Using Bearer Tokens

> How to obtain and use a SURCHI API access token — request credentials, pass them in headers, handle expiry, and manage token rotation.

Every request to the SURCHI Developer API must be authenticated using a short-lived Bearer token derived from your API key. This two-step model — API key → access token — keeps your long-lived credentials out of request headers and makes token rotation straightforward. This page walks through obtaining your API key, exchanging it for a Bearer token, and handling expiry gracefully.

## Getting an API Key

<Steps>
  <Step title="Join the developer waitlist">
    Visit [surchi.io/developers](https://surchi.io/developers) and submit your application. Early access is granted on a rolling basis during Phase 2 launch.
  </Step>

  <Step title="Access the developer dashboard">
    Once approved, you will receive an email invitation. Log in to the SURCHI developer dashboard at [dashboard.surchi.io](https://dashboard.surchi.io) with your credentials.
  </Step>

  <Step title="Create a new API key">
    Navigate to **API Keys** in the sidebar and click **Create New Key**. Give your key a descriptive name (e.g. `prod-trading-bot`) and select the appropriate permission scopes for your use case.
  </Step>

  <Step title="Copy your API key">
    Your API key is displayed **only once** immediately after creation. Copy it to a secure secrets manager (such as AWS Secrets Manager, HashiCorp Vault, or a `.env` file that is not committed to version control). If you lose your key, you will need to revoke it and generate a new one.
  </Step>
</Steps>

## Obtaining a Bearer Token

Exchange your API key for a short-lived access token by calling the `/v1/auth/token` endpoint:

```bash theme={null}
curl -X POST https://api.surchi.io/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{"api_key": "your_api_key_here"}'
```

A successful response returns a signed JWT access token along with its expiry:

```json theme={null}
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer",
  "expires_in": 3600
}
```

| Field          | Type    | Description                                          |
| -------------- | ------- | ---------------------------------------------------- |
| `access_token` | string  | Signed JWT to include in all subsequent API requests |
| `token_type`   | string  | Always `bearer`                                      |
| `expires_in`   | integer | Seconds until the token expires (3600 = 1 hour)      |

## Using Your Token

Pass the Bearer token in the `Authorization` header on every API request:

```bash theme={null}
curl https://api.surchi.io/v1/intelligence/signals \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
```

The token must be included on all endpoints — there is no unauthenticated access to any SURCHI API resource.

## Token Expiry and Rotation

Access tokens expire after **1 hour** (`expires_in: 3600`). Your application should implement automatic token refresh before expiry to avoid disruptions. A recommended pattern is to store the token alongside its expiry timestamp and proactively re-request a new token when fewer than 5 minutes remain:

```typescript token-manager.ts theme={null}
interface Token {
  accessToken: string;
  expiresAt: number; // Unix ms timestamp
}

let cachedToken: Token | null = null;

async function getAccessToken(): Promise<string> {
  const now = Date.now();
  const fiveMinutes = 5 * 60 * 1000;

  if (cachedToken && cachedToken.expiresAt - now > fiveMinutes) {
    return cachedToken.accessToken;
  }

  const response = await fetch('https://api.surchi.io/v1/auth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ api_key: process.env.SURCHI_API_KEY }),
  });

  const data = await response.json();
  cachedToken = {
    accessToken: data.access_token,
    expiresAt: now + data.expires_in * 1000,
  };

  return cachedToken.accessToken;
}
```

## Error Responses

Authentication failures return standard HTTP error codes with a JSON body describing the issue:

| Status Code             | Error                 | Description                                                                      |
| ----------------------- | --------------------- | -------------------------------------------------------------------------------- |
| `401 Unauthorized`      | `invalid_token`       | The Authorization header is missing, malformed, or the token has expired         |
| `403 Forbidden`         | `insufficient_scope`  | The token is valid but does not have permission to access the requested resource |
| `429 Too Many Requests` | `rate_limit_exceeded` | Your API key has exceeded its rate limit for the current window                  |

Error response body format:

```json theme={null}
{
  "error": "invalid_token",
  "error_description": "The access token has expired. Request a new token using your API key.",
  "status": 401
}
```

<Warning>
  Never expose your API key or access token in client-side code, public repositories, or browser environments. Always use environment variables and make API calls from server-side code or secure backend services only. If your key is compromised, revoke it immediately from the developer dashboard.
</Warning>
