Cookbook
Copy-and-paste examples for common flows. Replace bk_live_xxx with your key and … with tenant UUIDs. All amounts are strings. For OAuth2, replace bk_live_xxx with your bo_at_… access token in the same examples. See Authentication and scopes.
Check the key
curl https://api.test.bilteo.com/api/v1/ping \
-H "Authorization: Bearer bk_live_xxx"
# → { "pong": true }Discover catalogues
curl "https://api.test.bilteo.com/api/v1/taxes?tax_use=sale&is_active=true" \
-H "Authorization: Bearer bk_live_xxx"
curl https://api.test.bilteo.com/api/v1/series -H "Authorization: Bearer bk_live_xxx"
curl https://api.test.bilteo.com/api/v1/economic-activities -H "Authorization: Bearer bk_live_xxx"Bilteo applies defaults when series, activity, or currency are omitted.
Create and issue an F1
curl -X POST https://api.test.bilteo.com/api/v1/invoices \
-H "Authorization: Bearer bk_live_xxx" -H "Content-Type: application/json" \
-d '{
"type": "F1", "partner_id": "…", "operation_date": "2026-01-15",
"lines": [
{ "description": "January consulting", "quantity": "10",
"unit_price": "75.00", "main_tax_id": "…vat21…" }
]
}'
curl -X POST https://api.test.bilteo.com/api/v1/invoices/INV…/actions/issue \
-H "Authorization: Bearer bk_live_xxx"The first request creates a draft; the second numbers, freezes, and starts AEAT submission.
Simplified F2
curl -X POST https://api.test.bilteo.com/api/v1/invoices \
-H "Authorization: Bearer bk_live_xxx" -H "Content-Type: application/json" \
-d '{ "type": "F2",
"lines": [{ "description": "Counter sale", "quantity": "1",
"unit_price": "30.00", "main_tax_id": "…vat21…" }] }'Discount and multiple VAT rates
"lines": [
{ "description": "Service (21%)", "quantity": "1", "unit_price": "1000.00",
"discount": "10", "main_tax_id": "…vat21…" },
{ "description": "Book (4%)", "quantity": "2", "unit_price": "20.00",
"main_tax_id": "…vat4…" }
]Withholding and surcharge
retention_tax_id subtracts withholding from the amount due; surcharge_tax_id adds an equivalence surcharge to the line.
{ "description": "Professional service", "quantity": "1", "unit_price": "1000.00",
"main_tax_id": "…vat21…", "retention_tax_id": "…withholding15…" }{ "description": "Goods", "quantity": "1", "unit_price": "100.00",
"main_tax_id": "…vat21…", "surcharge_tax_id": "…surcharge52…" }Exempt, not subject, and reverse charge
In the Public API, the main_tax_id tax carries the classification:
| Operation | Tax type |
|---|---|
| Exempt | exento with exempt_reason |
| Not subject | no_sujeto / no_sujeto_loc |
| Reverse charge | sujeto_isp |
{ "description": "Exempt training", "quantity": "1", "unit_price": "500.00",
"main_tax_id": "…exempt-art20…" }See Taxes for the complete model.
International operations
Combine the customer's country with the correct tax:
| Operation | Customer | Tax |
|---|---|---|
| Intra-EU supply of goods | EU with VAT-IES | exento, art. 25 |
| Intra-EU B2B services | EU | no_sujeto_loc |
| Export | Outside the EU | exento, art. 21 |
curl -X PUT "https://api.test.bilteo.com/api/v1/partners/by-external-id/EU-FR-01" \
-H "Authorization: Bearer bk_live_xxx" -H "Content-Type: application/json" \
-d '{ "type": "com", "name": "Atelier Vionnet SARL",
"id_num": "FR47812904563", "country": "FR" }'Close the Veri*Factu loop
Subscribe to verifactu.accepted and verifactu.rejectedwebhooks. If you need to query instead:
curl "https://api.test.bilteo.com/api/v1/verifactu-records?invoice_id=INV…" \
-H "Authorization: Bearer bk_live_xxx"
# pending → in-process → accepted | accepted_error | rejected | unknown_responseCreate a corrective invoice
curl -X POST https://api.test.bilteo.com/api/v1/invoices/INV…/actions/rectify \
-H "Authorization: Bearer bk_live_xxx" -H "Content-Type: application/json" \
-d '{ "rectificative_type": "S", "rectification_cause": "law_error" }'This creates a draft R1. See the cause mapping.
Replace an F2 with an F3
curl -X POST https://api.test.bilteo.com/api/v1/invoices/INV_F2…/actions/replace \
-H "Authorization: Bearer bk_live_xxx" -H "Content-Type: application/json" \
-d '{ "partner_id": "…" }'Add ?issue=true to issue it in the same request.
Correct a rejected record
Only to fix submission data. The outcome depends on the history:
curl -X POST https://api.test.bilteo.com/api/v1/invoices/INV…/actions/request-fix \
-H "Authorization: Bearer bk_live_xxx"
# Never accepted (latest record rejected): needs_fix → correct → issue
# Accepted at some point: stays issued and a correction is queued with the
# current partner data (update it FIRST with PATCH /partners/{id})See the complete flow.
Cancel
Only for an invoice issued by mistake that should never have existed:
curl -X POST https://api.test.bilteo.com/api/v1/invoices/INV…/actions/cancel \
-H "Authorization: Bearer bk_live_xxx"Synchronise customers and products
curl -X PUT "https://api.test.bilteo.com/api/v1/partners/by-external-id/CUS-42" \
-H "Authorization: Bearer bk_live_xxx" -H "Content-Type: application/json" \
-d '{ "type": "com", "name": "Northwind Ltd", "id_num": "B85447761", "country": "ES" }'
curl -X PUT "https://api.test.bilteo.com/api/v1/products/by-external-id/SKU-9" \
-H "Authorization: Bearer bk_live_xxx" -H "Content-Type: application/json" \
-d '{ "name": "Annual subscription", "unit_price": "240.00", "main_tax_id": "…vat21…" }'PUT returns 201 on creation and 200 on update. See Synchronisation by external_id.
Download documents
curl "https://api.test.bilteo.com/api/v1/invoices/INV…/actions/print" \
-H "Authorization: Bearer bk_live_xxx" -H "Accept: application/pdf" -o invoice.pdf
curl "https://api.test.bilteo.com/api/v1/invoices/INV…/actions/facturae" \
-H "Authorization: Bearer bk_live_xxx" -o invoice.xml