Swagger UI openapi.json openapi.yaml
Guide

Authentication & Tokens

The API gateway issues HS256 JWTs. Every call (except login) requires a bearer token in the Authorization header.

How it works

The api gateway validates credentials and mints a signed JWT (HS256). Each incoming request is verified against the JWT signature and a server-side session store — so logout is instant and revocation is real.

Tokens are accepted in two ways:

  • Authorization: Bearer <token> — standard header (preferred)
  • ?token=<token> — query parameter (for webhooks / download links)

POST /sessions — Login flows

All flows use POST /sessions. The type field selects the authentication mechanism:

typeRequired fieldsUse case
emailemail, passwordStandard login
phonephone, otpPhone OTP (after POST /sessions/request)
linktokenMagic link (after POST /sessions/request)
tokentokenPre-issued one-time token
externalexternalEntity, externalAppExternal partner SSO

Example — email login

curl -X POST https://api.staging.contabeleza.com.br/sessions \
  -H "Content-Type: application/json" \
  -d '{"type":"email","email":"you@example.com","password":"secret"}'

Successful login response

On success the gateway returns a JSON object (not JSON:API) with the token and enriched session data:

{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiJ9…",
    "token-type": "user",
    "account": {
      "id": "3",
      "type": "personal",
      "email": "you@example.com"
    },
    "businesses": [
      {
        "id": "900001",
        "brand": "contabeleza",
        "permissions": ["invoices:read", "invoices:write"]
      }
    ]
  }
}

Store data.token and pass data.businesses[0].id as the ilm-business header on subsequent calls.

JWT claims reference

ClaimTypeDescription
accountIdstringThe authenticated account id
typestringuser | admin | token | external-app
restrictedTostringBusiness id scope
jtistringUnique token id — stored in the server-side session store; revoked on logout
iattimestampIssued-at (Unix seconds)
exptimestampExpiry (Unix seconds)

Token refresh

Call POST /sessions/token-refresh before exp to get a fresh token without re-authenticating:

curl -X POST https://api.staging.contabeleza.com.br/sessions/token-refresh \
  -H "Authorization: Bearer $TOKEN"

Returns a new data.token. The old token is revoked immediately.

Forgot password flow

Three-step sequence — no auth required:

  1. Request resetPOST /sessions/password/forgot with {"email":"…"}
  2. Validate tokenPOST /sessions/password/validate-token with {"reset-token":"…"}
  3. Set new passwordPOST /sessions/password/reset with {"reset-token":"…","password":"…"}

API key exchange

For machine-to-machine integrations use an API key. The gateway exchanges it for a short-lived external-app JWT:

curl -X POST https://api.staging.contabeleza.com.br/sessions/api \
  -H "Authorization: ApiKey your-api-key-here"

Manage API keys at GET/POST /external-app-tokens.

Logout

DELETE /sessions removes the token's JTI from the server-side session store immediately. Any in-flight requests using the same token after this call will receive 401 Unauthorized.

curl -X DELETE https://api.staging.contabeleza.com.br/sessions \
  -H "Authorization: Bearer $TOKEN"

Using the token

Swagger UI — open /docs, click Authorize, paste the token (without the Bearer prefix).

curl:

TOKEN=eyJhbGciOi...
curl https://api.staging.contabeleza.com.br/accounts/me \
  -H "Authorization: Bearer $TOKEN" \
  -H "ilm-business: 900001"