Skip to main content
The SIMCEL API supports OAuth2 and token-based authentication. You can authenticate in two ways:
  • OAuth2 Client Credentials flow
  • API key to token exchange
Both methods return a short-lived JWT bearer token used on API requests.

Option A: OAuth2 Client Credentials

POST https://app.simcel.io/api/oauth/v1/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=insights:read plans:read
Response:
{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 3600,
  "tokenType": "Bearer"
}

Option B: API key to token exchange

Generate an API key

  1. Log in to app.simcel.io
  2. Go to Settings -> API Keys
  3. Click Create new key
  4. Give it a name (for example my-ai-agent-prod) and set the scopes
  5. Copy the key. It is shown once.
Treat API keys like passwords. Do not commit them to source control. Use environment variables or a secrets manager.

Exchange API key for a token

POST https://app.simcel.io/api/auth/v1/token
Content-Type: application/json

{
  "apiKey": "sk_live_..."
}
Response:
{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 3600,
  "tokenType": "Bearer"
}
Tokens expire after 3600 seconds (1 hour).

Use the token

Pass the token as a Bearer header on every API request:
GET https://app.simcel.io/api/insights/v1/pnl-summary?planId=...
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Token refresh strategy

For long-running processes or agents, implement a refresh strategy:
import requests
import time

class SimcelClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self._token = None
        self._token_expiry = 0

    def _get_token(self) -> str:
        if time.time() < self._token_expiry - 60:  # refresh 60s before expiry
            return self._token

        resp = requests.post(
            "https://app.simcel.io/api/auth/v1/token",
            json={"apiKey": self.api_key}
        )
        resp.raise_for_status()
        data = resp.json()
        self._token = data["accessToken"]
        self._token_expiry = time.time() + data["expiresIn"]
        return self._token

    def get(self, path: str, **kwargs):
        headers = kwargs.pop("headers", {})
        headers["Authorization"] = f"Bearer {self._get_token()}"
        return requests.get(
            f"https://app.simcel.io/api/insights/v1{path}",
            headers=headers,
            **kwargs
        )

API Key scopes

ScopeDescription
insights:readRead access to all Insights API endpoints
plans:readList plans and scenarios
adminFull access (not recommended for integrations)
Most AI agent use cases only need insights:read + plans:read.

Errors

StatusMeaning
401 UnauthorizedToken missing, malformed, or expired
403 ForbiddenToken is valid but lacks required scope
{
  "statusCode": 401,
  "error": "Unauthorized",
  "message": "Bearer token is missing or has expired"
}