Documentation
Browse documentation
Language
EN ES

Python SDK

Install the fiscalrail package and use its typed, pooled API client.
View as Markdown

The official fiscalrail package is the recommended way to call FiscalRail from Python. It provides typed request parameters, immutable response dataclasses, pooled connections, safe retries and country-specific tax helpers without adding a runtime validation framework.

Install and authenticate

python -m pip install fiscalrail
export FISCALRAIL_API_KEY=ak_test_...

Create one client and reuse it for the lifetime of your application process:

import os

from fiscalrail import FiscalRail

client = FiscalRail(os.environ["FISCALRAIL_API_KEY"])

The API key is a required constructor argument. Your application decides whether it comes from an environment variable, secret manager or another configuration source; the SDK does not inspect process environment variables. Test and Live use the same base URL, and the key selects the account environment.

FiscalRail owns a pooled requests.Session. Use it as a context manager in short-lived scripts, or call client.close() during application shutdown. You can inject your own requests.Session when you need custom proxies, TLS settings, adapters or observability; injected sessions remain owned by your application.

Issue an invoice

Use Decimal for monetary input and the Spain helpers for catalog-backed taxes:

import os
from decimal import Decimal

from fiscalrail import FiscalRail
from fiscalrail.tax_regimes.es import irpf, vat

client = FiscalRail(os.environ["FISCALRAIL_API_KEY"])
invoice = client.invoices.issue(
    customer="cus_...",
    lines=[
        {
            "description": "Consulting services",
            "unit_price": Decimal("2500.00"),
            "taxes": [vat.general, irpf.professionals],
        }
    ],
)

print(invoice.code)
print(invoice.totals.payable)

Invoice issuance and amendment generate an idempotency key automatically. Durable jobs should supply and persist their own idempotency_key so a retry after a process restart identifies the same intended operation.

Typed requests and responses

Methods accept typed keyword arguments directly. Exported TypedDict definitions are useful when building a payload before making the call:

from decimal import Decimal

from fiscalrail.params import InvoiceIssueParams
from fiscalrail.tax_regimes.es import vat

params = InvoiceIssueParams(
    customer="cus_...",
    lines=[
        {
            "description": "Consulting services",
            "unit_price": Decimal("2500.00"),
            "taxes": [vat.general],
        }
    ],
)

invoice = client.invoices.issue(**params)

Responses are frozen dataclasses generated from FiscalRail's OpenAPI contract. Dates become date, timestamps become datetime, and decimal strings become Decimal. Unknown response fields remain available through response.extra_fields so adding a response field does not break older SDK versions.

Retries and errors

The client retries connection failures, timeouts, 408, 429 and transient 5xx responses only when the operation is safe to retry. It honors Retry-After and otherwise uses capped exponential backoff. The default is two retries; configure max_retries=0 to disable them.

FiscalRail errors are raised as subclasses of FiscalRailError. API errors expose status_code, code, request_id and validation details where available. Connection and timeout errors preserve the idempotency key so a durable worker can decide how to resume.

Available resources

  • client.accounts
  • client.api_keys
  • client.customers
  • client.event_destinations
  • client.events
  • client.invoice_series
  • client.invoices
  • client.invoice_pdfs
  • client.tax_ids
  • client.tax_regimes

Invoices use the domain verbs issue and amend; issued documents are never updated. Every operation in the API reference has a corresponding SDK resource method.

Verify webhooks

Pass the unmodified request body, the FiscalRail-Signature header and the destination's signing secret to construct_event:

from fiscalrail.webhooks import construct_event

event = construct_event(raw_body, signature_header, signing_secret)

The helper verifies the HMAC in constant time, rejects timestamps older than five minutes and only then parses the JSON event. A failed check raises WebhookSignatureError.