Authorization

All API requests require authentication using JWT tokens signed with RSA keys. You’ll generate these tokens using a private RSA key obtained from your project, then include them in the Authorization header as a Bearer token.

Overview

The authorization flow involves:

  1. Account Setup - Contact support to have a project and RSA keys provisioned for your account
  2. Creating JWT Tokens - Sign JWTs with your provided private key including required claims
  3. Making API Requests - Include JWT as Bearer token in Authorization header
  4. Token Validation - API validates tokens using your project’s stored public key

Account Provisioning

To get started with the API, contact our support team to provision:

  • Project ID - Unique identifier for your integration
  • RSA Key Pair - Private key for JWT signing and public key for verification
  • Environment Access - Sandbox and/or production environment permissions

Contact: support@basistheory.com for account provisioning.

Authentication Types

Project JWT Tokens

Used for Payment Methods and Purchase Intents operations:

  • Signed with project’s RSA private key
  • Include sub (entityId) and iss (projectId) claims
  • Required for all customer-facing API endpoints

Support Provisioning

All project and key management is handled through our support team:

  • Project Creation - Contact support to create projects for your account
  • RSA Key Generation - Support will provide RSA key pairs for JWT signing
  • Environment Setup - Support configures sandbox and production access

Authentication Header

Include your JWT token in all API requests:

Authorization: Bearer YOUR_JWT_TOKEN

JWT Structure

All JWTs must use RS256 algorithm and include specific claims for proper authentication and authorization.

JWT Generation

Required Claims Structure

const jwt = require('jsonwebtoken');
 
// JWT Payload
const payload = {
  sub: 'user-12345',           // Subject: unique user identifier
  iss: 'project-abc123',       // Issuer: your project ID
  roles: ['private'],          // Roles: permissions array
  iat: Math.floor(Date.now() / 1000)  // Issued at time
};
 
// JWT Options
const options = {
  algorithm: 'RS256',
  keyid: 'key-456',           // Key ID from your project
  expiresIn: '1h'             // Token expiration
};
 
// Generate JWT
const token = jwt.sign(payload, privateKey, options);

Project-Level Security

The API uses project-scoped authentication where:

  • JWT iss (issuer) must match the projectId in the URL path
  • JWT sub (subject) scopes access to user-specific resources
  • Only resources belonging to the authenticated subject are accessible
import { SignJWT, importPKCS8 } from 'jose';
 
// Import your RSA private key (in production, this should be done on backend only)
const privateKey = await importPKCS8(privateKeyPem, 'RS256');
 
// Create JWT with public role for payment method collection
async function createPublicJwt() {
  const token = await new SignJWT({
    sub: 'user-12345',           // Subject: unique user identifier
    iss: 'your-project-id',      // Issuer: your project ID
    roles: ['public']            // Public role for payment collection
  })
    .setProtectedHeader({ 
      alg: 'RS256',              // Must use RS256 algorithm
      kid: 'your-key-id'         // Key ID from your credentials
    })
    .setIssuedAt()
    .setExpirationTime('1h')
    .sign(privateKey);
 
  return token;
}

Required Claims

ClaimTypeRequiredDescription
substringYesSubject: unique user identifier that scopes access to resources
issstringYesIssuer: your project ID (must match URL parameter)
rolesstring[]YesArray of roles, typically ['private'] for API access
iatnumberYesIssued at time (Unix timestamp)
expnumberYesExpiration time (Unix timestamp)

Header Requirements

HeaderTypeRequiredDescription
algstringYesMust be RS256
kidstringYesKey ID corresponding to your project’s RSA key

Project-Level Security

The API uses project-scoped authentication where:

  • JWT iss (issuer) must match the projectId in the URL path
  • JWT sub (subject) scopes access to user-specific resources
  • Only resources belonging to the authenticated subject are accessible

URL Structure

All API endpoints follow this pattern:

/projects/{projectId}/resource

The projectId must match the iss claim in your JWT token.

Validation & Error Handling

Validation Process

  1. Token Structure: JWT must be properly formatted with valid RS256 signature
  2. Project Matching: JWT iss must equal URL projectId parameter
  3. Subject Validation: For POST requests, entityId in body must match JWT sub
  4. Role Authorization: User must have required role (typically private)
  5. Key Verification: Token must be signed with valid project key

Common Errors

{
  "error": {
    "status": 401,
    "type": "unauthorized",
    "title": "Unauthorized", 
    "message": "Missing or invalid JWT token was provided."
  }
}

Environment Configuration

The API supports different environments with different base URLs:

EnvironmentBase URLDescription
productionhttps://api.basistheory.aiProduction environment
sandboxhttps://api.sandbox.basistheory.aiTesting environment

Note: JWT tokens are environment-specific. Keys created in one environment cannot be used to authenticate requests in another environment.

Security Best Practices

  1. Keep private keys secure - Never expose RSA private keys in client-side code
  2. Use appropriate expiration times - Shorter tokens (15-60min) for sensitive operations
  3. Rotate keys regularly - Implement key rotation for long-lived applications
  4. Environment isolation - Use separate projects and keys for different environments
  5. Management token security - Protect management tokens as they provide administrative access
  6. Validate on every request - API validates all tokens server-side
  7. Handle errors gracefully - Implement proper error handling and token refresh
  8. Use HTTPS only - All API communication must use TLS encryption