Skip to main content

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)

StatusMeaningWhen it occurs
400 Bad RequestValidation errorMissing/invalid fields, constraint violations
401 UnauthorizedAuthentication failedMissing, invalid, or revoked API key
403 ForbiddenAccess deniedInactive account or live mode not enabled
404 Not FoundResource not foundInvalid ID or accessing another account's resource
207 Multi-StatusPartial successSome items in a batch operation succeeded while others failed
409 ConflictDuplicate resource or state conflictE.g., duplicate billing email, non-cancellable transaction

Server errors (5xx)

StatusMeaningWhen it occurs
500 Internal Server ErrorUnexpected failureDatabase 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

  1. Always check the status code before parsing the response body
  2. Log error responses for debugging -- the error field provides context
  3. Handle 401 errors by refreshing or rotating your API key
  4. Retry 500 errors with exponential backoff (e.g., 1s, 2s, 4s)
  5. Don't retry 4xx errors without fixing the request -- they indicate client-side issues