Authentication#
Authentication is based on JWT tokens. You should call the Incomaker authentication service to obtain a token that you can use to authenticate your individual requests.Base URL: https://auth.incomaker.com
1. Obtain a token#
Exchange your plugin's API key for a short-lived JWT. This is a
server-to-server call:POST /token
Content-Type: application/json
{ "apiKey": "<uuid-format api key>" }
{
"access_token": "<jwt>",
"token_type": "Bearer",
"expires_in": 3600
}
Two key formats are accepted — issue either and this endpoint handles both
transparently:Legacy keys — a raw UUID.
New keys — prefixed inco_<uuid>, stored SHA-256 hashed. Support
multiple keys per plugin, each with its own scoped permissions and expiry,
issued by an administrator.
Rate limit: 20 requests per minute per IP by default. Exceeding it
returns 429.
2. Check a token#
Tokens are validated locally against a public key — no call back to the
Auth Service is needed per request.Fetch the signing key#
GET /.well-known/jwks.json
Algorithm: EdDSA (Ed25519). Cache the response — it changes only on key
rotation. Reject any token signed with a different algorithm.Validate#
Signature valid against the JWKS public key
iss equals "incomaker-token-service"
aud contains "incomaker-services"
Read the claims#
| Claim | Type | Description |
|---|
iss | string | "incomaker-token-service" |
aud | string | "incomaker-services" |
iat | number | Issued-at (Unix seconds) |
exp | number | Expiry (Unix seconds), default 60 minutes |
plugin_id | number | Plugin identifier |
domain_id | string | Plugin's public UUID |
account_id | number | Account the plugin belongs to |
rights | string[] | Granted permission codes |
Plugin tokens never carry a sub claim — that's how you tell them apart from
user tokens, if your service also accepts those.Catch revocation between expiries (recommended)#
JWTs are stateless, so revoking an API key doesn't retroactively invalidate a
token already issued from it. Close that gap by checking the invalidation
feed:GET /token/invalidations?since=<unix_ms>
Authorization: Bearer <jwt>
Requires auth:invalidations:read.[
{ "subjectType": "plugin", "subjectId": "1341", "invalidBefore": 1783586700000 }
]
Reject a token if payload.iat * 1000 < invalidBefore for the matching
plugin_idIntrospect your own token (debugging)#
GET /auth/me
Authorization: Bearer <jwt>
{
"iss": "incomaker-token-service",
"iat": 1783586727,
"exp": 1783590327,
"plugin_id": 1341,
"domain_id": "...",
"account_id": 1272,
"permissions": []
}
Reads claims already present in the token — no database hit, safe on the hot
path — but it won't tell you if something behind the token has since been
revoked. Returns 401 missing_token without a valid Bearer header.
3. Use a token#
Attach the access token as a Bearer credential on every request to a
protected endpoint:Authorization: Bearer <jwt>
Using the token, access a particular endpoint of the API. For Incomaker Reporting API v1 use:Base URL: https://reporting.incomaker.com/v1Modified at 2026-07-17 16:35:50