Authentication Guide
Learn how to authenticate with Custodia using OAuth2 client credentials
Overview
Custodia uses OAuth2 with the client credentials grant type for authentication. This means you'll use your clientId and clientSecret to obtain an access token that you'll use for all subsequent API requests.
Note: Keep your
clientSecret secure and never expose it in client-side code or public repositories.
Authentication Endpoint
POST
/md/api/Application/authenticate
Request Parameters
All parameters should be sent in the request body as JSON or form data:
| Parameter | Type | Required | Description |
|---|---|---|---|
client_id |
string | Yes | Your application's client ID provided by Custodia |
client_secret |
string | Yes | Your application's client secret provided by Custodia |
scope |
array | Yes | Array of scopes for your application. Use ["DEFAULT"] for standard access. |
grant_type |
string | Yes | Must be "client_credentials" |
Example Request
Using cURL:
curl -X POST https://sandbox.custodia-tech.com/md/api/Application/authenticate \
-H "Content-Type: application/json" \
-d '{
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"scope": ["DEFAULT"],
"grant_type": "client_credentials"
}'
Using JavaScript (fetch):
const response = await fetch('https://sandbox.custodia-tech.com/md/api/Application/authenticate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
client_id: 'your-client-id',
client_secret: 'your-client-secret',
scope: ['DEFAULT'],
grant_type: 'client_credentials'
})
});
const tokenData = await response.json();
Using Python (requests):
import requests
url = 'https://sandbox.custodia-tech.com/md/api/Application/authenticate'
payload = {
'client_id': 'your-client-id',
'client_secret': 'your-client-secret',
'scope': ['DEFAULT'],
'grant_type': 'client_credentials'
}
response = requests.post(url, json=payload)
token_data = response.json()
Response
On successful authentication, you'll receive a JSON response with the following structure:
Success Response (200 OK)
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 300,
"scopes": ["DEFAULT"],
"scope": "DEFAULT"
}
| Field | Type | Description |
|---|---|---|
access_token |
string | The JWT access token to use for authenticated API requests |
token_type |
string | Always "Bearer" for this API |
expires_in |
number | Token expiration time in seconds (typically 300 seconds / 5 minutes in production, 900 seconds / 15 minutes in development) |
scopes |
array | Array of scopes granted to your token (typically ["DEFAULT"]) |
scope |
string | The scope granted to your token (typically "DEFAULT") |
Important: Access tokens expire after a short period (typically 5 minutes). You should implement token refresh logic to obtain a new token before the current one expires.
Using the Access Token
Once you have an access token, include it in the Authorization header and include your clientId in the x-appid header of all subsequent requests:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
x-appid: your-client-id
Example Request:
const response = await fetch('https://sandbox.custodia-tech.com/md/api/Transactions', {
method: 'GET',
headers: {
'Authorization': `Bearer ${tokenData.access_token}`,
'x-appid': clientId,
'Content-Type': 'application/json'
}
});
const transactions = await response.json();
Error Responses
If authentication fails, you'll receive an error response:
Error Response (401 Unauthorized)
{
"error": {
"statusCode": 401,
"name": "Error",
"message": "authorization failed with appId (clientId) your-client-id",
"code": "INVALID-OAUTH2"
}
}
Common Error Codes
| Error Code | Description | Solution |
|---|---|---|
INVALID-OAUTH2 |
Invalid client ID or client secret | Verify your credentials are correct |
400 Bad Request |
Missing required parameters or invalid grant_type | Ensure all required parameters are included and grant_type is "client_credentials" |
429 Too Many Requests |
Rate limit exceeded | Wait before retrying the request |
Best Practices
- Store credentials securely: Never hardcode your
clientSecretin your application. Use environment variables or secure credential storage. - Implement token caching: Cache your access token and reuse it until it expires to reduce authentication requests.
- Handle token expiration: Implement automatic token refresh before expiration to avoid API call failures.
- Use DEFAULT scope: For now, use
["DEFAULT"]as the scope array for authentication. - Use HTTPS: Always make authentication requests over HTTPS to protect your credentials.
Next Steps: Once you've successfully authenticated, you can start making requests to access transactions, expenses, and other resources. Check the other documentation pages for endpoint details.