Skip to content

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 ​

bash
curl https://api.test.bilteo.com/api/v1/ping \
  -H "Authorization: Bearer bk_live_xxx"
# → { "pong": true }

Discover catalogues ​

bash
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 ​

bash
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 ​

bash
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 ​

json
"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.

json
{ "description": "Professional service", "quantity": "1", "unit_price": "1000.00",
  "main_tax_id": "…vat21…", "retention_tax_id": "…withholding15…" }
json
{ "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:

OperationTax type
Exemptexento with exempt_reason
Not subjectno_sujeto / no_sujeto_loc
Reverse chargesujeto_isp
json
{ "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:

OperationCustomerTax
Intra-EU supply of goodsEU with VAT-IESexento, art. 25
Intra-EU B2B servicesEUno_sujeto_loc
ExportOutside the EUexento, art. 21
bash
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:

bash
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_response

Create a corrective invoice ​

bash
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 ​

bash
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:

bash
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:

bash
curl -X POST https://api.test.bilteo.com/api/v1/invoices/INV…/actions/cancel \
  -H "Authorization: Bearer bk_live_xxx"

Synchronise customers and products ​

bash
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 ​

bash
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

Bilteo · Documentation