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:
- Account Setup - Contact support to have a project and RSA keys provisioned for your account
- Creating JWT Tokens - Sign JWTs with your provided private key including required claims
- Making API Requests - Include JWT as Bearer token in Authorization header
- 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) andiss(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 theprojectIdin 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
| Claim | Type | Required | Description |
|---|---|---|---|
sub | string | Yes | Subject: unique user identifier that scopes access to resources |
iss | string | Yes | Issuer: your project ID (must match URL parameter) |
roles | string[] | Yes | Array of roles, typically ['private'] for API access |
iat | number | Yes | Issued at time (Unix timestamp) |
exp | number | Yes | Expiration time (Unix timestamp) |
Header Requirements
| Header | Type | Required | Description |
|---|---|---|---|
alg | string | Yes | Must be RS256 |
kid | string | Yes | Key ID corresponding to your project’s RSA key |
Project-Level Security
The API uses project-scoped authentication where:
- JWT
iss(issuer) must match theprojectIdin 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
- Token Structure: JWT must be properly formatted with valid RS256 signature
- Project Matching: JWT
issmust equal URLprojectIdparameter - Subject Validation: For POST requests,
entityIdin body must match JWTsub - Role Authorization: User must have required role (typically
private) - 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:
| Environment | Base URL | Description |
|---|---|---|
production | https://api.basistheory.ai | Production environment |
sandbox | https://api.sandbox.basistheory.ai | Testing environment |
Note: JWT tokens are environment-specific. Keys created in one environment cannot be used to authenticate requests in another environment.
Security Best Practices
- Keep private keys secure - Never expose RSA private keys in client-side code
- Use appropriate expiration times - Shorter tokens (15-60min) for sensitive operations
- Rotate keys regularly - Implement key rotation for long-lived applications
- Environment isolation - Use separate projects and keys for different environments
- Management token security - Protect management tokens as they provide administrative access
- Validate on every request - API validates all tokens server-side
- Handle errors gracefully - Implement proper error handling and token refresh
- Use HTTPS only - All API communication must use TLS encryption