Authentication

OAuth 2.0 authorization code flow. PKCE is supported but not required.

The flow

Standard authorization code. Your application sends the person to our authorization endpoint, they approve and choose a TallyPrime connection, and you exchange the returned code for tokens.

1. Send them to authorize

GET
http://localhost:4173/api/v1/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://your-platform.example/callback
  &response_type=code
  &scope=tally.read%20tally.write%20connection.read
  &state=RANDOM_STRING
redirect_uri must match one you registered on the application, exactly — no wildcards and no prefixes. That exactness is what stops a crafted link from sending an authorization code somewhere else.

2. Exchange the code

curl -X POST http://localhost:4173/api/v1/oauth/token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -d "grant_type=authorization_code" \
  -d "code=THE_CODE" \
  -d "redirect_uri=https://your-platform.example/callback"
response
{
  "access_token": "…",
  "refresh_token": "…",
  "token_type": "Bearer",
  "expires_in": 2592000,
  "scope": "tally.read tally.write connection.read",
  "connection_name": "ABC Traders",
  "company_name": "ABC TRADERS PVT LTD"
}

connection_name and company_name ride along so you can label the saved connection without a second call.

3. Call the API

header
Authorization: Bearer YOUR_ACCESS_TOKEN

Refreshing

POST /api/v1/oauth/token
curl -X POST http://localhost:4173/api/v1/oauth/token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=YOUR_REFRESH_TOKEN"
The refresh token is not rotated
Automation platforms keep a copy of the credential on every workflow and refresh them independently; rotating would break the others mid-flight. Revoke to end access.

PKCE

Optional, enforced when used: code_challenge + code_challenge_method=S256 on authorize, code_verifier on the token request.

Revoking

POST /api/v1/oauth/revoke
curl -X POST http://localhost:4173/api/v1/oauth/revoke \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -d "token=THE_ACCESS_OR_REFRESH_TOKEN"

Always answers 200, whether or not the token existed — so it cannot be used to discover which tokens are live.

Testing a connection

GET /api/v1/oauth/userinfo confirms a token works and names the connection and company behind it. It is what a connector's “Test connection” button should call.

Something missing on this page? Tell us and we will fix it.