Authentication
All fiskaly APIs use JWT-based authentication. This guide covers the different authentication patterns across products.
Authentication Flow
Section titled “Authentication Flow”API Key + Secret → POST /auth (or /tokens) → access_token + refresh_token │ ├─ Use in Authorization header │ └─ On 401 → refresh or re-authenticateSIGN DE, SIGN AT, DSFINVK DE, RECEIPT
Section titled “SIGN DE, SIGN AT, DSFINVK DE, RECEIPT”These products use a straightforward auth endpoint:
curl -X POST https://kassensichv-middleware.fiskaly.com/api/v2/auth \
-H "Content-Type: application/json" \
-d '{
"api_key": "YOUR_API_KEY",
"api_secret": "YOUR_API_SECRET"
}'const response = await fetch(
"https://kassensichv-middleware.fiskaly.com/api/v2/auth",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
api_key: "YOUR_API_KEY",
api_secret: "YOUR_API_SECRET",
}),
}
);
const { access_token, refresh_token } = await response.json();import requests
response = requests.post(
"https://kassensichv-middleware.fiskaly.com/api/v2/auth",
json={"api_key": "YOUR_API_KEY", "api_secret": "YOUR_API_SECRET"},
)
tokens = response.json()
access_token = tokens["access_token"]
refresh_token = tokens["refresh_token"]Response
Section titled “Response”{ "access_token": "eyJhbGciOiJSUzI1NiIs...", "access_token_expires_in": 86400, "refresh_token": "eyJhbGciOiJSUzI1NiIs...", "refresh_token_expires_in": 172800}| Field | Description |
|---|---|
access_token | JWT token valid for 24 hours — include as Authorization: Bearer <token> |
refresh_token | Token valid for 48 hours — use to obtain a new access token |
SIGN ES
Section titled “SIGN ES”SIGN ES wraps the auth request in a content envelope:
curl -X POST https://test.es.sign.fiskaly.com/api/v1/auth \
-H "Content-Type: application/json" \
-d '{
"content": {
"api_key": "YOUR_API_KEY",
"api_secret": "YOUR_API_SECRET"
}
}'const response = await fetch(
"https://test.es.sign.fiskaly.com/api/v1/auth",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
content: {
api_key: "YOUR_API_KEY",
api_secret: "YOUR_API_SECRET",
},
}),
}
);
const { access_token } = await response.json();response = requests.post(
"https://test.es.sign.fiskaly.com/api/v1/auth",
json={"content": {"api_key": "YOUR_API_KEY", "api_secret": "YOUR_API_SECRET"}},
)
access_token = response.json()["access_token"]SIGN IT, SIGN FR, E-Invoice
Section titled “SIGN IT, SIGN FR, E-Invoice”These newer APIs use /tokens with the content.type discriminator and require additional headers:
curl -X POST https://test.api.fiskaly.com/tokens \
-H "Content-Type: application/json" \
-H "X-Api-Version: 2026-02-03" \
-d '{
"content": {
"type": "API_KEY",
"key": "YOUR_API_KEY",
"secret": "YOUR_API_SECRET"
}
}'const response = await fetch(
"https://test.api.fiskaly.com/tokens",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Version": "2026-02-03",
},
body: JSON.stringify({
content: {
type: "API_KEY",
key: "YOUR_API_KEY",
secret: "YOUR_API_SECRET",
},
}),
}
);
const { access_token } = await response.json();response = requests.post(
"https://test.api.fiskaly.com/tokens",
headers={"X-Api-Version": "2026-02-03"},
json={"content": {"type": "API_KEY", "key": "YOUR_API_KEY", "secret": "YOUR_API_SECRET"}},
)
access_token = response.json()["access_token"]Scoped Authentication
Section titled “Scoped Authentication”To scope requests to a specific organization UNIT, include the X-Scope-Identifier header:
Authorization: Bearer <access_token>X-Api-Version: 2026-02-03X-Scope-Identifier: <organization_unit_id>Token Refresh
Section titled “Token Refresh”When the access token expires, use the refresh token instead of re-authenticating with credentials:
curl -X POST https://kassensichv-middleware.fiskaly.com/api/v2/auth \
-H "Content-Type: application/json" \
-d '{"refresh_token": "YOUR_REFRESH_TOKEN"}'const response = await fetch(
"https://kassensichv-middleware.fiskaly.com/api/v2/auth",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ refresh_token: refreshToken }),
}
);
const { access_token } = await response.json();response = requests.post(
"https://kassensichv-middleware.fiskaly.com/api/v2/auth",
json={"refresh_token": refresh_token},
)
access_token = response.json()["access_token"]Best Practices
Section titled “Best Practices”💡Cache tokens
Access tokens are valid for 24 hours. Cache the token and only refresh on
401 responses. Re-authenticating on every request wastes ~100ms per call.
⚠️Never expose secrets
- Store API secrets in environment variables or a secrets manager - Never commit secrets to source control - Never include secrets in client-side code - Rotate API keys if a secret is compromised
Recommended Token Strategy
Section titled “Recommended Token Strategy”- Authenticate once at application startup
- Store the
access_tokenandrefresh_tokenin memory - On
401response, attempt to refresh using therefresh_token - If refresh fails (token expired), re-authenticate with API key + secret
- If re-auth fails, surface the error to the operator
Related
Section titled “Related”Was this page helpful?