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 clientSecret in 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.