Token Management

Refresh, introspect, and manage OAuth tokens


After a user authorizes your app, you receive an access token and (optionally) a refresh token. Here's how to manage them.

Token Types#

TokenPrefixLifetimePurpose
Access tokenost_15 minutesAuthenticate API requests
Refresh tokenosr_30 daysGet new access tokens
Authorization codeosc_5 minutesOne-time use, exchanged for tokens

Using Access Tokens#

Include the access token in the Authorization header of every API request:

curl https://api.orshot.com/v1/templates \
  -H "Authorization: Bearer ost_your_access_token"

Refreshing Tokens#

Access tokens expire after 15 minutes. Use the refresh token to get a new one without re-prompting the user:

curl -X POST https://api.orshot.com/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "refresh_token",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "refresh_token": "osr_your_refresh_token"
  }'

Response:

{
  "access_token": "ost_new_access_token",
  "refresh_token": "osr_new_refresh_token",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "workspace:read render:generate",
  "user_id": "user-uuid",
  "workspace_ids": ["workspace-uuid-1"]
}

Token Introspection#

Check whether a token is still valid and see its metadata:

curl -X POST https://api.orshot.com/v1/oauth/introspect \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "token": "ost_token_to_check"
  }'

Active token response:

{
  "active": true,
  "scope": "workspace:read render:generate",
  "client_id": "your-client-id",
  "user_id": "user-uuid",
  "workspace_ids": ["workspace-uuid-1"],
  "exp": 1714500000
}

Expired or revoked token:

{
  "active": false
}

Best Practices#

Handle token expiry gracefully#

Don't wait for a 401 response to refresh. Check the expires_in value and refresh proactively:

function isTokenExpiringSoon(expiresAt, bufferSeconds = 60) {
  return Date.now() / 1000 > expiresAt - bufferSeconds;
}

Store tokens securely#

  • Server-side apps: Store tokens in an encrypted database or secrets manager
  • Desktop apps: Use the OS keychain (macOS Keychain, Windows Credential Manager)
  • CLI tools: Store in a local config file with restricted file permissions (chmod 600)
  • Never store tokens in localStorage, cookies without httpOnly, or source code

Handle refresh failures#

If a refresh request fails, the user needs to re-authorize:

async function getValidToken(storedTokens) {
  if (!isTokenExpiringSoon(storedTokens.expiresAt)) {
    return storedTokens.accessToken;
  }

  try {
    const response = await refreshToken(storedTokens.refreshToken);
    // Map OAuth response (snake_case) to your stored format
    const newTokens = {
      accessToken: response.access_token,
      refreshToken: response.refresh_token,
      expiresAt: Date.now() / 1000 + response.expires_in,
    };
    await saveTokens(newTokens);
    return newTokens.accessToken;
  } catch (err) {
    // Refresh failed — re-authorize
    throw new Error("Re-authorization required");
  }
}

Token Revocation#

Tokens are automatically revoked when:

  • The user removes your app's access from their Orshot settings
  • The user removes a workspace from your app's grant (only tokens for that workspace)
  • Your app's OAuth client is disabled
  • A refresh token is replaced during rotation (the old one is invalidated)

To proactively revoke access from your side, stop using the tokens and discard them. There is no explicit revocation endpoint at this time.

All Set? Let's Start Automating

Get Your API Key →
  • Image, PDF and Video Generation via API
  • Canva like editor with AI and smart features
  • No-Code Integrations (Zapier, Make, n8n etc.)
  • Embed Orshot Studio in your app
  • Start Free. No credit card required. Cancel anytime.