Authentication and scopes
Partner API uses the OAuth2 Client Credentials grant (RFC 6749 §4.4). No user login, cookies, or sessions — every call is authenticated with your clientId / client secret pair.
Getting a token
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type = client_credentials
client_id = <your clientId>
client_secret = <your client secret>
org_id = <client org UUID> (optional)
There are two token flavors, both valid for 1 hour, with no refresh token (just call /oauth/token again):
| Token type | org_id sent? | Use it for |
|---|---|---|
| App-only | No | Discovering authorized organizations only |
| Org-scoped | Yes | All invoice/signing endpoints, on behalf of that organization |
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "invoice:write invoice:read ttn:submit"
}
Send it as a bearer token on every subsequent call:
Authorization: Bearer <access_token>
401 invalid_client— wrongclient_id/client_secret.403 access_denied—org_idgiven but not authorized for your app (revoked, never granted, or inactive).429 TOO_MANY_REQUESTS— rate limit exceeded (see the Reference page).
Scopes
| Scope | Grants |
|---|---|
invoice:write | Create, update, submit, duplicate, delete draft invoices; trigger sign-and-send |
invoice:read | List and retrieve invoices, statuses, PDFs, generated XML, jobs, activity |
ttn:submit | Manually (re)submit to TTN — org-owned keys only, not partner tokens |
seal:sign | Trigger SEAL signing as part of sign-and-send |
digigo:sign | Trigger DigiGO signing as part of sign-and-send |
A client only grants the scopes they're comfortable with — check allowedScopes before calling an endpoint that needs a scope you weren't granted, or you'll get a 403 INSUFFICIENT_SCOPES.
Discovering client organizations
Use your app-only token for these two endpoints:
GET /api/partner/authorized-orgs
Lists every organization currently authorizing your app (orgId, orgName, taxIdentifier, allowedScopes, authorizedAt).
GET /api/partner/resolve-org?taxId=<matricule>
Resolves a Tunisian tax ID (8- or 13-character format) to the corresponding orgId, restricted to organizations that authorize your app. Returns 404 ORG_NOT_FOUND if no match.
Once you have an orgId, request an org-scoped token (org_id=<orgId>) and move on to Invoices.