Authentication

The OneFinOps API uses OAuth 2.0 client credentials. You exchange a client id and secret for a short-lived bearer token, and pass that token on every API call.

Issue an OAuth client

OAuth clients are managed from the Developer hub in your OneFinOps dashboard. When creating a client you choose a label (for your own bookkeeping). The single API scope gstn-india is assigned automatically — you don't pick per-action scopes.

We return the client_id (visible forever) and client_secret (shown once). Store the secret in a secrets manager — we cannot recover it; you would have to rotate.

Client ids are environment-prefixed:

EnvironmentPrefix
Sandboxofin_test_
Productionofin_live_

Request a token

curl -X POST 'https://login.onefinops.com/realms/onefinops/protocol/openid-connect/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials' \
  -d 'client_id=ofin_live_<id>' \
  -d 'client_secret=<secret>' \
  -d 'scope=gstn-india'

The response includes access_token (JWT) and expires_in (seconds, typically 900). Cache the token until it nears expiry. Pass it as Authorization: Bearer <access_token>.

Permissions are not scope-based

The gstn-india scope is a marker — it tells the API surface "this token is for me." It is not a permission grant. What your token can do is governed by your plan / entitlement and per-call rate limits, not by per-action OAuth scopes.

Practical effect:

  • You request a single scope gstn-india regardless of which endpoints you call.
  • The endpoints you can call depend on your plan / add-ons. A token whose plan doesn't include e-way-bill access will still authenticate, but the call will be rejected at the entitlement layer with a billing-shaped error code.
  • Rate limits (see Rate limits) apply per OAuth client per minute, irrespective of which endpoint you hit.

This is intentionally simpler than per-action scope juggling: you don't have to maintain a scope catalogue in your client config, and we can enable / disable products on your account without forcing you to rotate keys.

Tenant binding

Every token carries an organization_id claim that pins the call to your tenant. You cannot override the organization in the request body or path — the API reads it from the token. This is what keeps multi-org customers' data separated.

Rotating secrets

You can rotate a client's secret from the Developer hub. Rotation issues a new secret and starts a 24-hour overlap window during which both the old and new secrets work — long enough to roll your deployment without downtime. After 24 hours, the old secret is revoked.

Common mistakes

  • Calling the API with the OIDC token endpoint URL as the base URL. The token endpoint is at login.onefinops.com; the API lives at api.in.onefinops.com (or sandbox).
  • Putting the client_secret in browser code. Client credentials is server-to-server only. Never embed a secret in a SPA or mobile app.
  • Reissuing a token on every request. Cache and reuse — the token endpoint is rate-limited and aggressive churn will fail open with 429s.
  • Mixing sandbox tokens with production hosts. The audience claim is environment-scoped; cross-env tokens are rejected with 401.
  • Requesting per-action scopes (einvoice:generate etc.). They don't exist. Just request scope=gstn-india.