Astrada uses OAuth 2.0 with **two separate sets of client credentials**, each scoped for a specific purpose:

| Credential Set | Purpose | Used By |
| --- | --- | --- |
| **API Credentials** | Backend API operations (subaccounts, webhooks, transactions, cards) | Your server |
| **SDK Credentials** | Card enrollment via the Web SDK | Your server + the SDK in the browser |

Both credential sets are provided during onboarding. Each set consists of a unique `client_id` and `client_secret` pair.

## API Credentials

API credentials authorize your backend server to call Astrada's REST API. Use these for all server-to-server operations: managing subaccounts, registering webhooks, retrieving transactions, and more.

### Obtaining an Access Token

Exchange your API `client_id` and `client_secret` for a Bearer token using the OAuth 2.0 client credentials flow:

```curl
curl -X POST https://api.astrada.co/oauth/token \
  -H "Content-Type: application/json" \
  -d '{\n    "client_id": "YOUR_API_CLIENT_ID",\n    "client_secret": "YOUR_API_CLIENT_SECRET",\n    "grant_type": "client_credentials"\n  }'
```

**Response:**

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "expires_in": 300,
  "token_type": "Bearer"
}
```

### Using the Token

Include the access token as a Bearer token in the `Authorization` header of all API requests:

```curl
curl -X GET https://api.astrada.co/transactions \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### Token Lifecycle

- Tokens expire after **5 minutes** (`expires_in: 300`).
- Request a new token when the current one expires. There is no refresh token flow.
- Tokens are stateless JWTs validated on each request.

## SDK Credentials

SDK credentials authorize the Card Enrollment SDK to perform enrollment operations in the browser. These are a **separate `client_id` / `client_secret` pair** with restricted permissions limited to card enrollment.

### How SDK Authentication Works

The SDK credentials should never be exposed in browser code. Instead:

1. **Your backend** exchanges the SDK `client_id` and `client_secret` for an access token (using the same OAuth endpoint above).
2. **Your backend** returns the access token to the frontend.
3. **The SDK** uses the token via the `getAccessToken` callback to authenticate enrollment requests.

### Providing the Token to the SDK

Pass an async function as the `getAccessToken` parameter when launching the SDK. This function should call your backend to obtain a fresh token:

```javascript
CardEnrollmentSdk.openForm({
  companyName: "Your Company",
  subaccountId: "67bc3887-4e25-49cf-bea7-326d808acb5f",
  getAccessToken: async () => {
    const response = await fetch('/your-backend/astrada-sdk-token');
    const { access_token } = await response.json();
    return access_token;
  },
  onSuccess: (data) => console.log(data),
  onError: (error) => console.error(error),
  onCancel: () => console.log("Enrollment cancelled"),
});
```

The SDK will call `getAccessToken`:

- When the SDK is first launched.
- When the current token expires during an enrollment session.

> The `getAccessToken` function must resolve within **5 seconds** or the SDK will timeout with an error.

## Security Best Practices

> Never expose any `client_id` or `client_secret` in frontend/browser code. Both credential sets must be exchanged for tokens on your backend.

- **Principle of least privilege**: Use SDK credentials for enrollment operations and API credentials for backend operations. Do not use API credentials where SDK credentials suffice.
- **Server-side token exchange**: Both credential sets should be used exclusively on your backend. Only the resulting JWT access token should be passed to the browser (for SDK use) or used in API calls.
- **Credential storage**: Store credentials securely in your backend environment (e.g., environment variables, secrets manager). Never commit credentials to source control.
- **Token expiry**: Tokens expire after 5 minutes. Implement token caching on your backend to avoid unnecessary token requests, and handle expiry gracefully.

## Credential Summary

|  | API Credentials | SDK Credentials |
| --- | --- | --- |
| **Consists of** | `client_id` \+ `client_secret` | `client_id` \+ `client_secret` |
| **Token endpoint** | `POST /oauth/token` | `POST /oauth/token` |
| **Grant type** | `client_credentials` | `client_credentials` |
| **Token lifetime** | 5 minutes | 5 minutes |
| **Scope** | Full API access | Card enrollment only |
| **Used where** | Your backend server | Your backend (token exchange) + SDK in browser |
| **Delivered via** | 1Password during onboarding | 1Password during onboarding |

## Next Steps

- [Getting Started](https://docs.astrada.co/docs/getting-started-1) \- Step-by-step integration walkthrough
- [Web SDK Installation](https://docs.astrada.co/docs/web-sdk) \- Card enrollment SDK setup and configuration
- [Integration Guide](https://docs.astrada.co/docs/integration-guide) \- End-to-end implementation patterns
- [Authentication API Reference](https://docs.astrada.co/reference/authentication) \- Token endpoint specification

Updated 5 months ago
