Authentication
Every request to /api/v1/* must carry a bearer token:
Authorization: Bearer <token>
Accept: application/json
There are two ways to get one, for two different use cases.
Organization API tokens (server-to-server)
The simplest path for integrations: create a token in the admin panel under Organization → API Tokens.
- The token is shown once at creation — store it securely.
- It is bound to one organization; you don't need to select an organization per request, but if you send
X-Organization-Idit must match the token's organization. - Each token has its own scopes (see below;
*grants all). - Tokens can be given an expiry date, and are revoked from the same admin page (not via the logout endpoint).
OAuth 2.0 Authorization Code + PKCE (apps acting for users)
For applications where a user signs in with their own EncryptInvoice account, use the standard OAuth 2.0 Authorization Code flow with PKCE. It is a public client flow — there is no client secret.
- Generate a
code_verifier(random 43–128 chars) and itscode_challenge(Base64url(SHA-256(verifier))), plus a randomstate. - Open the system browser at:
GET /oauth/authorize
?client_id=<client_id>
&redirect_uri=<registered redirect URI>
&response_type=code
&scope=<space-separated scopes>
&state=<state>
&code_challenge=<code_challenge>
&code_challenge_method=S256
- After sign-in, the browser is redirected to your
redirect_uriwith?code=...&state=.... Verifystate, then exchange the code:
POST /oauth/token
grant_type=authorization_code
client_id=<client_id>
redirect_uri=<same redirect URI>
code=<code>
code_verifier=<original verifier>
Response:
{
"token_type": "Bearer",
"expires_in": 1296000,
"access_token": "eyJ0eXAiOiJKV1Q...",
"refresh_token": "def50200..."
}
Refreshing
POST /oauth/token
grant_type=refresh_token
refresh_token=<refresh_token>
client_id=<client_id>
Refresh rotation is on: each refresh returns a new access and refresh token and revokes the old refresh token. Replace the stored pair atomically; a 400 invalid_grant means the session has ended — restart the sign-in flow.
Signing out
| Endpoint | Effect |
|---|---|
POST /api/v1/logout |
Revokes the token used on this request (and its refresh token). |
POST /api/v1/logout-all |
Revokes all of the user's API tokens on every device. |
Revocation is immediate. Organization API tokens are managed in the admin panel and return 400 invalid_token_type on these endpoints.
Scopes
| Scope | Grants |
|---|---|
organizations:read |
List/read organizations |
invoices:read / invoices:write / invoices:send / invoices:delete |
Invoices |
quotes:read / quotes:write / quotes:convert |
Quotes |
customers:read / customers:write |
Customers |
contacts:read / contacts:write |
Contacts |
expenses:read / expenses:write |
Expenses |
einvoicing:send / einvoicing:participants |
E-invoicing submission and participant lookup |
Scopes declare your app's intent; actual authorization is additionally enforced per user and role on every request. A token can never do more than the user or organization behind it is allowed to.
Token lifetimes
| Credential | Lifetime |
|---|---|
| OAuth access token | 15 days |
| OAuth refresh token | 30 days (rotated on each refresh) |
| Organization API token | Optional expiry (never, if not set) |