Skip to main content

Transactions

Submit and query fiscalization transactions. All endpoints require authentication.

info

FiscalAPI never blocks the cash register. POST /v1/transactions always returns 201 Created — fiscalization happens inline when possible, and retries asynchronously on failure.

Create a transaction

POST /v1/transactions

Submits a transaction for fiscalization. The transaction is stored immediately and fiscalized inline when possible. If inline fiscalization fails, it retries asynchronously — the response is always 201.

Request headers

HeaderRequiredDescription
AuthorizationYesBearer token (fsk_test_... or fsk_live_...)
Content-TypeYesapplication/json
Idempotency-KeyNoUUID for replay protection. Auto-generated if omitted.
X-Fiscalization-TimeoutNoTimeout hint in seconds for inline fiscalization

Request body

FieldTypeRequiredDescription
location_idstringYesUUID of the merchant location
timestampstringYesISO 8601 transaction timestamp
itemsarrayYesNon-empty array of line items
pretax_amountnumberYesPre-tax amount (>= 0)
tax_amountnumberYesTax amount (>= 0)
total_amountnumberYesTotal amount (> 0). Must equal pretax_amount + tax_amount
currencystringYesISO 4217 currency code (3 letters, e.g. EUR)
payment_methodstringYesOne of: cash, card, transfer, other
customer_contextobjectNoOptional customer data for the fiscal receipt

Examples

curl:

curl -X POST https://api.fiscalapi.com/v1/transactions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer fsk_test_abc123def456..." \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"location_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"timestamp": "2026-03-09T14:30:00Z",
"items": [
{"description": "Café con leche", "quantity": 2, "unit_price": 2.50, "tax_rate": 0.21},
{"description": "Tostada", "quantity": 1, "unit_price": 3.00, "tax_rate": 0.21}
],
"pretax_amount": 6.61,
"tax_amount": 1.39,
"total_amount": 8.00,
"currency": "EUR",
"payment_method": "card"
}'

Python:

import requests

response = requests.post(
"https://api.fiscalapi.com/v1/transactions",
headers={
"Authorization": "Bearer fsk_test_abc123def456...",
"Idempotency-Key": "550e8400-e29b-41d4-a716-446655440000",
},
json={
"location_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"timestamp": "2026-03-09T14:30:00Z",
"items": [
{"description": "Café con leche", "quantity": 2, "unit_price": 2.50, "tax_rate": 0.21},
{"description": "Tostada", "quantity": 1, "unit_price": 3.00, "tax_rate": 0.21},
],
"pretax_amount": 6.61,
"tax_amount": 1.39,
"total_amount": 8.00,
"currency": "EUR",
"payment_method": "card",
},
)
transaction = response.json()
print(transaction["id"], transaction["status"])

JavaScript (Node.js):

const response = await fetch("https://api.fiscalapi.com/v1/transactions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer fsk_test_abc123def456...",
"Idempotency-Key": "550e8400-e29b-41d4-a716-446655440000",
},
body: JSON.stringify({
location_id: "7c9e6679-7425-40de-944b-e07fc1f90ae7",
timestamp: "2026-03-09T14:30:00Z",
items: [
{ description: "Café con leche", quantity: 2, unit_price: 2.50, tax_rate: 0.21 },
{ description: "Tostada", quantity: 1, unit_price: 3.00, tax_rate: 0.21 },
],
pretax_amount: 6.61,
tax_amount: 1.39,
total_amount: 8.00,
currency: "EUR",
payment_method: "card",
}),
});
const transaction = await response.json();
console.log(transaction.id, transaction.status);

Go:

payload := map[string]interface{}{
"location_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"timestamp": "2026-03-09T14:30:00Z",
"items": []map[string]interface{}{
{"description": "Café con leche", "quantity": 2, "unit_price": 2.50, "tax_rate": 0.21},
{"description": "Tostada", "quantity": 1, "unit_price": 3.00, "tax_rate": 0.21},
},
"pretax_amount": 6.61,
"tax_amount": 1.39,
"total_amount": 8.00,
"currency": "EUR",
"payment_method": "card",
}
body, _ := json.Marshal(payload)

req, _ := http.NewRequest("POST", "https://api.fiscalapi.com/v1/transactions", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer fsk_test_abc123def456...")
req.Header.Set("Idempotency-Key", "550e8400-e29b-41d4-a716-446655440000")

resp, err := http.DefaultClient.Do(req)

Response 201 Created

{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"account_id": "9f8e7d6c-5b4a-3210-fedc-ba0987654321",
"location_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
"type": "sale",
"status": "pending",
"amount": 800,
"currency": "EUR",
"country": "ES",
"request_payload": { "...": "original request body" },
"fiscal_id": null,
"created_at": "2026-03-09T14:30:01Z"
}
info

The amount field is stored in cents (integer). A total_amount of 8.00 becomes 800.

Errors

StatusErrorCause
400Key: 'CreateRequest.LocationID'...Missing required field
400items must be a non-empty arrayEmpty or invalid items array
400pretax_amount + tax_amount must equal total_amountAmount mismatch (tolerance: 0.01)
400location not foundInvalid location_id or not owned by account
400location is not activeLocation has been deactivated

Idempotency

Include an Idempotency-Key header to safely retry requests. If a transaction with the same key already exists for your account, the existing transaction is returned without creating a duplicate.


List transactions

GET /v1/transactions

Returns a paginated list of transactions for the authenticated account, ordered by created_at descending.

Query parameters

ParameterTypeDefaultDescription
limitinteger20Items per page (max 100)
offsetinteger0Pagination offset (max 10000)
statusstring--Filter by status: pending, processing, success, failed, failed_permanent, pending_lroe, cancelled

Examples

curl:

# List all transactions
curl https://api.fiscalapi.com/v1/transactions \
-H "Authorization: Bearer fsk_test_abc123def456..."

# Filter by status and paginate
curl "https://api.fiscalapi.com/v1/transactions?status=success&limit=10&offset=0" \
-H "Authorization: Bearer fsk_test_abc123def456..."

Python:

import requests

response = requests.get(
"https://api.fiscalapi.com/v1/transactions",
headers={"Authorization": "Bearer fsk_test_abc123def456..."},
params={"status": "success", "limit": 10},
)
data = response.json()
for tx in data["data"]:
print(tx["id"], tx["status"], tx["amount"])

JavaScript (Node.js):

const params = new URLSearchParams({ status: "success", limit: "10" });
const response = await fetch(
`https://api.fiscalapi.com/v1/transactions?${params}`,
{ headers: { "Authorization": "Bearer fsk_test_abc123def456..." } },
);
const { data, total } = await response.json();
console.log(`${total} transactions found`);

Go:

req, _ := http.NewRequest("GET", "https://api.fiscalapi.com/v1/transactions?status=success&limit=10", nil)
req.Header.Set("Authorization", "Bearer fsk_test_abc123def456...")
resp, err := http.DefaultClient.Do(req)

Response 200 OK

{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"account_id": "9f8e7d6c-5b4a-3210-fedc-ba0987654321",
"location_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
"type": "sale",
"status": "success",
"amount": 800,
"currency": "EUR",
"country": "ES",
"request_payload": { "...": "original request body" },
"fiscal_id": "TBAI-12345678",
"created_at": "2026-03-09T14:30:01Z",
"submitted_at": "2026-03-09T14:30:02Z",
"completed_at": "2026-03-09T14:30:03Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}

Get a transaction

GET /v1/transactions/{id}

Returns a single transaction by ID, scoped to the authenticated account. Use this to poll for fiscalization status.

Path parameters

ParameterTypeDescription
iduuidTransaction UUID

Examples

curl:

curl https://api.fiscalapi.com/v1/transactions/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer fsk_test_abc123def456..."

Python:

import requests

tx_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
response = requests.get(
f"https://api.fiscalapi.com/v1/transactions/{tx_id}",
headers={"Authorization": "Bearer fsk_test_abc123def456..."},
)
tx = response.json()
print(tx["status"], tx.get("fiscal_id"))

JavaScript (Node.js):

const txId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";
const response = await fetch(
`https://api.fiscalapi.com/v1/transactions/${txId}`,
{ headers: { "Authorization": "Bearer fsk_test_abc123def456..." } },
);
const tx = await response.json();
console.log(tx.status, tx.fiscal_id);

Go:

txID := "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
req, _ := http.NewRequest("GET", "https://api.fiscalapi.com/v1/transactions/"+txID, nil)
req.Header.Set("Authorization", "Bearer fsk_test_abc123def456...")
resp, err := http.DefaultClient.Do(req)

Response 200 OK

Returns a Transaction object.

Errors

StatusError
404transaction not found

Cancel a transaction

POST /v1/transactions/{id}/cancel

Cancels a previously fiscalized transaction. A cancellation transaction is created and submitted to the fiscal authority.

Path parameters

ParameterTypeDescription
iduuidTransaction UUID to cancel

Request body

FieldTypeRequiredDescription
reasonstringNoCancellation reason

Example

curl -X POST https://api.fiscalapi.com/v1/transactions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/cancel \
-H "Content-Type: application/json" \
-H "Authorization: Bearer fsk_test_abc123def456..." \
-d '{"reason": "Customer returned items"}'

Response 201 Created

Returns a new transaction with type: "cancellation":

{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"type": "cancellation",
"status": "pending",
"amount": 800,
"currency": "EUR",
"environment": "test",
"created_at": "2026-03-09T15:00:00Z"
}

Cancellable statuses

Only transactions in certain statuses can be cancelled:

StatusCancellable
successYes
pending_lroeYes
pending_submissionYes
pendingNo
processingNo
failedNo
failed_permanentNo
cancelledNo

Errors

StatusErrorCause
404transaction not foundInvalid ID
409transaction cannot be cancelledTransaction is not in a cancellable status

Idempotency

Cancellation is idempotent. Cancelling an already-cancelled transaction returns the existing cancellation transaction.


Transaction object

FieldTypeDescription
iduuidTransaction identifier
account_iduuidOwning account identifier
location_iduuidMerchant location identifier
idempotency_keystringIdempotency key for replay protection
typestringTransaction type: sale or cancellation
statusstringFiscalization status (see below)
amountintegerTotal amount in cents
currencystringISO 4217 currency code
countrystringISO 3166-1 alpha-2 country code
request_payloadobjectOriginal request body (stored for audit)
response_payloadobjectFiscal authority response (when available)
fiscal_idstringFiscal identifier assigned by the tax authority
environmentstringtest or live (determined by API key prefix)
error_messagestringError details (when status is failed)
submitted_atdatetimeWhen the transaction was sent to the fiscal authority
completed_atdatetimeWhen fiscalization completed
created_atdatetimeCreation timestamp

Transaction statuses

StatusDescription
pendingCreated, awaiting fiscalization
processingBeing processed by the fiscal authority
successFiscalized successfully -- fiscal_id is set
failedFiscalization failed -- see error_message. Will be retried.
failed_permanentFiscalization permanently failed (max retries exceeded, moved to dead letter)
pending_lroeInline fiscalization succeeded, awaiting LROE batch submission (Spain TicketBAI)
cancelledTransaction was cancelled via the cancel endpoint