EMS integrations authenticate with an account_client OAuth client — machine-to-machine credentials tied to your partner account.
This docs site covers account_client only. Other client types (organization_client, account_user, etc.) exist internally but are not part of the EMS integration path.
Get a token
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
curl -X POST https://sandbox-api.opencard.io/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=organizations-read organizations-write webhooks-write"
Response:
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}
Use on every API call:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
Create an account_client
Dashboard: Account → OAuth Clients → Create New
Or via API (requires an existing client with oauth-clients-write):
POST /accounts/{accountId}/oauthclients
Response includes secret in plain text — shown once. Store it immediately.
Update scopes later:
PUT /accounts/{accountId}/oauthclients/{oauthclientId}
{ "scopes": ["organizations-read", "organizations-write", "webhooks-write"] }
Clients created on an account without an organization_id are account_client — this is what you want.
Recommended scopes for EMS
Start with this set:
account-tpas-read account-tpas-write account-tpa-signatories-write account-tpa-identities-read
organizations-read organizations-write
card-holders-read card-holders-write
webhooks-read webhooks-write webhook-events-read
public-records-read
account-card-issuers-read account-card-issuers-write
oauth-clients-read
billings-write
receipts-write
Request only what you need. Scopes are space-separated in the token request.
All account_client scopes
| Scope | What it unlocks |
|---|
accounts-read / accounts-write | Your account settings |
oauth-clients-read / oauth-clients-write | Manage OAuth clients |
public-records-read | Company registry lookup |
account-tpas-read / account-tpas-write / account-tpas-delete | TPAs |
account-tpa-signatories-read / -write / -delete | TPA signatories |
account-tpa-identities-read | Identities on a TPA |
account-card-issuers-read / -write / -delete | Enable card programs |
organizations-read / -write / -delete | Organizations |
card-holders-read / -write / -delete | Card holders |
webhooks-read / webhooks-write | Webhooks |
webhook-events-read | Webhook delivery log |
webhook-headers-read / -write / -delete | Custom webhook headers |
webhook-groups-read / -write / -delete | Buyer-party webhook filters |
billings-read / billings-write | Billing profiles |
receipts-write | Receipt OCR scan |
files-read | Download files (e.g. receipt URLs) |
card-issuers-read | List available card programs |
environmental-impacts-read | CO₂ data on transactions |
account-users-read / -write / -delete | Account user management |
account-statistics-read | Account statistics |
Access control
Your account_client token is tied to your account. The API checks:
- Token has the required scope for the route
- Token owner has access to
accountId / organizationId in the URL
You can only access your own account’s resources.
Errors
| Status | Meaning |
|---|
401 | Invalid or expired token |
403 | Valid token but missing scope or no access to resource |
404 | Resource doesn’t exist (or you can’t see it) |