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
Join the developer waitlist
Visit surchi.io/developers and submit your application. Early access is granted on a rolling basis during Phase 2 launch. Access the developer dashboard
Once approved, you will receive an email invitation. Log in to the SURCHI developer dashboard at dashboard.surchi.io with your credentials. 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.
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.
Obtaining a Bearer Token
Exchange your API key for a short-lived access token by calling the /v1/auth/token endpoint:
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:
{
"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:
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:
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:
{
"error": "invalid_token",
"error_description": "The access token has expired. Request a new token using your API key.",
"status": 401
}
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.