Authentication

Available to: Developers (license type) Minimum plan: Free

TitanRDM's API uses OAuth 2.0 (via Doorkeeper) for authentication. This page explains how to obtain access tokens and use them to authenticate API requests.


Prerequisites

  • An OAuth Application created in TitanRDM (see OAuth Applications)
  • Your application's Client ID and Client Secret

Grant Types

TitanRDM supports two OAuth 2.0 grant types:

Client Credentials (Machine-to-Machine)

Use this for automated pipelines, ETL jobs, and services that don't act on behalf of a specific user.

When to use: - CI/CD pipelines importing or exporting data - Scheduled sync jobs - Monitoring and reporting scripts

Limitations: - No user context — actions are not attributed to a specific user - Some endpoints require user context (deployments, promotions) and will return 401 with a message to use Authorization Code flow instead

Authorization Code (User Context)

Use this for integrations that act on behalf of a specific user, where actions need to be attributed and permissions need to be evaluated per-user.

When to use: - Custom admin tools or dashboards - Integrations where audit trail must show which user performed the action - Deployment and promotion automation (these require a user)


Obtaining an Access Token

Client Credentials Flow

curl -X POST https://{subdomain}.app.titanrdm.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "scope=api"

You can also use HTTP Basic authentication for the client credentials:

curl -X POST https://{subdomain}.app.titanrdm.com/oauth/token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "scope=api"

Successful response:

{
  "access_token": "eyJhbGciOiJIUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "scope": "api",
  "created_at": 1700000000
}

Authorization Code Flow

  1. Redirect the user to the authorization endpoint:
https://{subdomain}.app.titanrdm.com/oauth/authorize?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=YOUR_REDIRECT_URI&
  response_type=code&
  scope=api
  1. User grants access — they are redirected to your redirect_uri with a code parameter.

  2. Exchange the code for an access token:

curl -X POST https://{subdomain}.app.titanrdm.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=YOUR_REDIRECT_URI"

Successful response:

{
  "access_token": "eyJhbGciOiJIUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 7200,
  "refresh_token": "abc123...",
  "scope": "api",
  "created_at": 1700000000
}

Using an Access Token

Include the token in the Authorization header of every API request:

curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  https://{subdomain}.app.titanrdm.com/api/v1/domains

Token Expiration and Refresh

  • Access tokens expire after 2 hours (7200 seconds) by default
  • When using the Authorization Code flow, a refresh token is provided
  • Use the refresh token to obtain a new access token without re-authenticating the user:
curl -X POST https://{subdomain}.app.titanrdm.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "refresh_token=YOUR_REFRESH_TOKEN"

For the Client Credentials flow, simply request a new token when the current one expires.


Scopes

Request specific scopes to limit what the token can do:

ScopeAccess Level
apiFull access (parent scope)
api:readRead-only (GET requests)
api:writeCreate and update (POST, PATCH, PUT)
api:deleteDelete resources (DELETE)
api:adminAdministrative operations

Request multiple scopes by separating with spaces:

scope=api:read api:write

Scopes are enforced per-request based on the HTTP method: - GET / HEAD → requires api:read - POST / PATCH / PUT → requires api:write - DELETE → requires api:delete

The parent scope api satisfies all sub-scopes.


Tenant Context

TitanRDM is multi-tenant. The API automatically determines your account (tenant) from the OAuth application:

  • Client Credentials: Tenant is set from the OAuth application's account
  • Authorization Code: Tenant is set from the authenticated user's account

The API verifies that the token's application account matches the user's account. Cross-account access is not permitted.


Error Responses

StatusErrorCause
401Invalid tokenToken is expired, revoked, or malformed
401Invalid resource ownerUser associated with the token no longer exists
401Token/user account mismatchToken application and user belong to different accounts
401Tenant context not setAuthentication failed completely
403Insufficient scope. Required: api:writeToken does not have the required scope for this action

Security Best Practices

  • Never expose client secrets in client-side code, public repositories, or logs
  • Use the minimum scope needed — request api:read if you only need to read data
  • Store tokens securely — use environment variables or a secrets manager
  • Rotate secrets periodically — use the "Regenerate Secret" feature in OAuth Applications
  • Use Client Credentials for service accounts, Authorization Code for user-facing integrations
  • Monitor API usage — check your account's usage dashboard for unexpected spikes