Error Handling
FiscalAPI uses standard HTTP status codes and returns structured error responses.
Error response format
All errors return a JSON object with an error field:
{
"error": "human-readable error message"
}
HTTP status codes
Client errors (4xx)
| Status | Meaning | When it occurs |
|---|---|---|
400 Bad Request | Validation error | Missing/invalid fields, constraint violations |
401 Unauthorized | Authentication failed | Missing, invalid, or revoked API key |
403 Forbidden | Access denied | Inactive account or live mode not enabled |
404 Not Found | Resource not found | Invalid ID or accessing another account's resource |
207 Multi-Status | Partial success | Some items in a batch operation succeeded while others failed |
409 Conflict | Duplicate resource or state conflict | E.g., duplicate billing email, non-cancellable transaction |
Server errors (5xx)
| Status | Meaning | When it occurs |
|---|---|---|
500 Internal Server Error | Unexpected failure | Database errors, upstream failures |
Common errors by endpoint
Account creation (POST /v1/accounts)
# Missing name
curl -X POST https://api.fiscalapi.com/v1/accounts \
-H "Content-Type: application/json" \
-d '{"billing_email": "admin@acme.com"}'
{
"error": "Key: 'CreateRequest.Name' Error:Field validation for 'Name' failed on the 'required' tag"
}
# Duplicate email
curl -X POST https://api.fiscalapi.com/v1/accounts \
-H "Content-Type: application/json" \
-d '{"name": "Acme 2", "billing_email": "admin@acme.com"}'
{
"error": "an account with this billing email already exists"
}
Location creation (POST /v1/locations)
# Spain without country_config
curl -X POST https://api.fiscalapi.com/v1/locations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer fsk_test_..." \
-d '{"name": "Test", "country": "ES"}'
{
"error": "Spain locations require country_config with system field (ticketbai or verifactu)"
}
Authentication errors
# No Authorization header
curl https://api.fiscalapi.com/v1/locations
{
"error": "missing or invalid Authorization header"
}
# Invalid key
curl https://api.fiscalapi.com/v1/locations \
-H "Authorization: Bearer invalid_key"
{
"error": "invalid API key format"
}
Pagination errors
# Invalid status filter
curl "https://api.fiscalapi.com/v1/locations?status=deleted" \
-H "Authorization: Bearer fsk_test_..."
{
"error": "status must be 'active' or 'inactive'"
}
Live mode guard (403 Forbidden)
# Using a live key when live mode is not enabled
curl -X POST https://api.fiscalapi.com/v1/transactions \
-H "Authorization: Bearer fsk_live_..." \
-H "Content-Type: application/json" \
-d '{ ... }'
{
"error": "live mode is not enabled"
}
Transaction cancellation (409 Conflict)
# Cancelling a transaction that is not in a cancellable status
curl -X POST https://api.fiscalapi.com/v1/transactions/{id}/cancel \
-H "Authorization: Bearer fsk_test_..."
{
"error": "transaction cannot be cancelled"
}
Batch processing (207 Multi-Status)
Batch processing endpoints may return 207 when some items succeed and others fail. Check the alert_triggered field in the response to detect failures.
Transaction statuses and errors
The failed_permanent status indicates a transaction that has exhausted all retry attempts and moved to dead letter. Subscribe to the fiscalization.dead_letter webhook event to be notified when this occurs.
Best practices
- Always check the status code before parsing the response body
- Log error responses for debugging -- the
errorfield provides context - Handle 401 errors by refreshing or rotating your API key
- Retry 500 errors with exponential backoff (e.g., 1s, 2s, 4s)
- Don't retry 4xx errors without fixing the request -- they indicate client-side issues