Skip to content

API Authentication

Applies to: All subscriptions

Purpose

Show exactly what to send on each API surface, and how to tell one authentication failure from another. Most integration delays at this stage come from confusing "not authenticated" with "not permitted".

Audience

Integration developers.

Prerequisites

Steps

1. Identify which credential your surface needs

Surface Credential
Ingest Machine credential
Integration (write-back) Machine credential
Mapping templates User token
Administration User token

Machine credentials cannot call administrative endpoints, and user tokens are not intended for ingest. This separation is deliberate.

2. Present a machine credential

Either form is accepted on ingest and integration endpoints:

Identity-provider token (preferred):

Authorization: Bearer eyJ0eXAiOiJKV1Qi...
Content-Type: application/json

Static key (supported, primarily for migration):

X-API-Key: cfly_<company>_<gstin>_<suffix>
Content-Type: application/json

The static key may also be sent as a bearer token; the platform distinguishes them by prefix.

3. Obtain an identity-provider token

The ERP requests a token using the client-credentials flow against the customer's identity tenant. The token must:

Requirement Failure if missing
Be issued by the configured tenant Rejected as unauthenticated
Carry an accepted audience Rejected as unauthenticated
Be unexpired Rejected, with an expiry indication
Carry the required application role Rejected as forbidden — the token is valid, it simply lacks the granted role

The last row is the most common OAuth stumble. A token that authenticates but is refused means the application role was never granted through admin consent — not that the credential is wrong.

Cache the token until shortly before expiry. Requesting a new token per call is unnecessary and will attract rate limiting.

4. Present a user token

User-token surfaces need both the token and the registration being worked on:

Authorization: Bearer <session token>
X-GSTIN: 29AAACW3775F000
Content-Type: application/json

The registration header exists for tenant isolation. Omitting it is refused for ordinary users.

5. Distinguish the failures

This table resolves most integration authentication problems:

Response Meaning Fix
401 TOKEN_MISSING No credential presented Send the header
401 TOKEN_INVALID Malformed, wrong audience, wrong issuer, or bad signature Decode the token and compare against the configuration
401 TOKEN_EXPIRED Expired, or the clocks disagree Refresh. If it recurs, check time synchronisation on both hosts
403 missing role Valid token, role not granted Grant the application role through admin consent
403 OAUTH_REQUIRED This client has been switched to identity-provider tokens only Complete the migration; the static key is now refused
403 GSTIN_NOT_PERMITTED Authenticated, but the document's supplier registration is outside the credential's scope Widen the scope deliberately, or send from the correct credential

401 means "I do not know who you are". 403 means "I know who you are, and no". Treat them differently in your error handling: a 401 warrants a credential refresh and one retry; a 403 never does.

6. Handle credential rotation

Credential Rotation
Identity-provider token Refreshed automatically by your client before expiry
Static key Issue the new key, migrate the caller, verify, then revoke the old one

A static key is shown once when issued. Store it in a secret manager at that moment; it cannot be retrieved afterwards.

Validation

Check Method Pass condition
Credential authenticates Call a low-risk endpoint Accepted
Token is cached Inspect your client's behaviour One token serves many calls
Refresh works Let a token expire Refreshed automatically, without a failed business call
Scope enforced Submit for an out-of-scope registration 403, distinguishable from 401
Failures distinguished Force each of 401 and 403 Your code takes different paths
Revocation works Revoke and call again Refused
No credential in source control Review the repository Absent
Clocks synchronised Compare host times Within a second

Troubleshooting

Symptom Cause Action
401 with a token that looks valid Wrong audience or issuer Decode the token; compare its claims with the configuration
401 intermittently Clock drift on either host Token validation is time-sensitive. Fix time synchronisation
403 with a valid token Application role not granted Grant it through admin consent
403 on some documents only Those documents' supplier registrations are outside scope Check which registration each document belongs to
Static key suddenly refused The client has been marked as requiring identity-provider tokens Complete the migration
Key lost Keys are not retrievable after issue Issue a new one, migrate, revoke the old
Token validation fails after months of success Provider signing keys rotated and cannot be fetched Confirm outbound access to the provider's key endpoint
Rate limited while authenticating A token requested per call instead of cached Cache until near expiry
All integrations fail after one change A single credential shared across ERPs Issue one per ERP
User-token call refused with a missing-header message Registration header omitted Send it