Authorization
Overview
This guide walks you through authenticating to the DriveWealth API: exchanging your clientID / clientSecret pair for a session token, using that token on subsequent requests, and handling your credentials safely. If you're integrating DriveWealth into a product other developers or end customers will depend on, treat everything in the "Protecting Your Credentials" and "If a Secret Is Compromised" sections below as required reading, not optional hardening.
What you'll need
| Item | Description |
|---|---|
clientID | Issued by DriveWealth per implementer. One pair is standard; additional pairs require a request to DriveWealth (see FAQ below). |
clientSecret | Issued alongside your clientID. Treat with the same sensitivity as a database root password. |
dw-client-app-key | A separate key sent as a header, required on the token request and on every subsequent API call made with the resulting access token. Not interchangeable with clientID/clientSecret — you need all three. |
| Environment host | Sandbox (UAT) for development and pre-launch testing; production for live traffic. |
DriveWealth issues one clientID/clientSecret pair per implementer under normal circumstances. If your architecture genuinely requires multiple pairs (e.g., isolating per-service credentials), contact DriveWealth to request additional provisioning rather than sharing one pair across services.
Step 1: Request a session token
Exchange your clientID and clientSecret for a short-lived session token. This call must be made server-to-server — never from a mobile app, browser, or any client-side code, since doing so exposes your clientSecret in transit and in client binaries/inspectable JS.
Endpoint: POST /back-office/auth/tokens Sandbox host: https://bo-api.drivewealth.io
curl --location 'https://bo-api.drivewealth.io/back-office/auth/tokens' \
--header 'dw-client-app-key: YOUR_APP_KEY' \
--header 'Content-Type: application/json' \
--data '{
"clientID": "YOUR_CLIENT_ID",
"clientSecret": "YOUR_CLIENT_SECRET"
}'| Field | Location | Type | Required | Description |
|---|---|---|---|---|
clientID | body | string | Yes | The identifier of the client accessing the DriveWealth system. |
clientSecret | body | string | Yes | The secret of the client accessing the DriveWealth system. |
dw-client-app-key | header | string | Yes | Application key identifying the calling app. Required here and on every downstream API call — see Step 2. |
Response — 200:
{
"token_type": "Bearer",
"expires_in": "3600",
"access_token": "eyJraWQiOiJ...<truncated — a signed JWT>",
"scope": "all_trading",
"userID": "7c0e3e79-59ae-475d-bf76-85ea82b363af",
"partnerID": "80f9b672-120d-4b73-9cc9-42fb3262c4b9"
}A few things worth calling out explicitly for implementers, since they're easy to get wrong:
expires_inis returned as a string ("3600"), not a number. If your language/HTTP client assumes a numeric type and doesn't coerce, this will throw or silently misbehave — parse it defensively.access_tokenis a signed JWT. It can be decoded locally to inspect claims (scp/scope,sub, expiry) for debugging, but treat the API's own401responses — not local JWT expiry math — as the source of truth for whether a token is still valid.scopereflects what was granted to your credentials (e.g.,all_trading); don't assume every implementer sees the same value.- Never log the full
access_tokenor paste a real one into documentation, tickets, or Slack — including this guide. Redact it the way the example above is redacted.
Step 2: Use the token on subsequent requests
Every API call — not just the token request — needs both the Authorization header and the dw-client-app-key header:
Authorization: Bearer {access_token}
dw-client-app-key: YOUR_APP_KEY
Example:
curl --location 'https://bo-api.drivewealth.io/back-office/users/USERID' \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
--header 'dw-client-app-key: YOUR_APP_KEY'A request missing the dw-client-app-key header will fail even with a valid, unexpired access_token — if you're debugging an unexpected 401/403, confirm this header is present before assuming the token itself is bad.
Token lifecycle
- Expiry: every issued
access_tokenis valid for 60 minutes from the moment it was requested. - Multiple active tokens: requesting a new token does not invalidate a previously issued one. Each token expires independently, 60 minutes from its own issuance.
- Rate limit / expected usage: tokens should be cached and reused for their full lifetime, not re-requested per API call. DriveWealth expects roughly 5–10 token requests per hour per implementer — design your integration to cache the token and only refresh it on expiry or a
401.
Implementation pattern: cache the token along with its issued-at time in memory (or a short-lived, encrypted cache — not a database column, not logs). Before each API call, check the cached token's remaining lifetime. Refresh proactively a few minutes before the 60-minute mark — e.g., at 55 minutes — rather than waiting for expiry or a 401. Refreshing only on expiry/401 leaves a race window where a request goes out just as the token expires and gets rejected; a buffer avoids that.
- You'll exceed DriveWealth's stated usage expectation. DriveWealth expects roughly 5–10 token requests per hour per implementer. Requesting one per API call will blow past that at any real volume.
- It multiplies your
clientSecretexposure for no benefit. Every token request retransmits yourclientSecretand adds a full round-trip of latency to the request in front of it — while the token you already hold is still valid.
Cache the token, track when it was issued, and only request a new one when it's actually near/at expiry.
Protecting your credentials
Your clientID, clientSecret, and dw-client-app-key together grant programmatic access to move client assets and data. Treat all three with the same discipline — the app key is just as capable of enabling unauthorized access as the secret is, even though it's passed as a plain header rather than a body field.
- Never commit credentials to source control. Not in config files, not in
.envfiles checked into git, not in a "temporary" branch. If you use a public SCM (GitHub, etc.), this is non-negotiable. Use environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager, etc.) for runtime injection instead. - Never hardcode credentials in application code. Keep them in environment variables or an external, access-controlled config store outside your application's repository.
- Never expose credentials client-side. No mobile apps, no browser JS, no anything a customer's device can inspect. The token exchange must happen server-to-server.
- Limit access by environment. Sandbox credentials can reasonably be shared across your dev team. Production
clientSecretaccess should be restricted to the minimum set of engineers/services that need it — not the whole engineering org. - Keep secrets out of logs and error messages. Scrub
clientSecretandaccess_tokenvalues from application logs, crash reports, and any third-party observability tooling (Datadog, Sentry, etc.) before they're captured. - Use a secrets manager with audit logging in production, so you have a record of who/what accessed the secret and when — this matters both for your own incident response and for demonstrating controls during regulatory or client security reviews.
If a secret is compromised
If you know or suspect your clientID, or clientSecret has been exposed — committed to a public repo, logged somewhere insecure, shared over an unencrypted channel, or accessed by anyone outside your authorized team — reach out to DriveWealth immediately. Do not wait to confirm the extent of the exposure first; report it, then investigate. Please contact Client Services by submitting a service ticket and reach out in your dedicated communication channel with DriveWealth.
When you reach out, be ready to provide: which clientID is affected, your best estimate of when the exposure occurred, and what you've already done (e.g., rotated the secret, revoked tokens) if anything.
Updated 3 days ago