Quickstart
From an API key to your first delivered invoice — create master data, POST /invoices with a full JSON example, then submit it over Peppol.
This guide takes you end to end: get an API key, make sure your customer and
items exist, create an invoice with POST /invoices, then submit it for Peppol
delivery.
Get an API key
Create a key under Settings → Integrations → API Keys and copy the
fat_… secret. See Authentication. Send it
in the X-Api-Key header on every request.
Create a customer and items (if needed)
You can reference the buyer and items inline on the invoice, or create them
first as master data so they're reusable. Each create is a POST and must
carry an Idempotency-Key header:
curl https://integration.fatorly.com/v1/customers \
-H "X-Api-Key: fat_your_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: customer-acme-001" \
-d '{
"code": "CUST-001",
"name": "ACME Trading LLC",
"vatTrn": "100123456700003",
"participantId": "iso6523-actorid-upis::0235:100123456700003"
}'
Create the invoice
POST /invoices with a V1CreateInvoiceRequest body. The example below shows
a tax invoice with one line, plus where the optional fields go —
references, delivery, allowancesCharges (document and line level),
line classifications, item identifiers, and payment details.
curl https://integration.fatorly.com/v1/invoices \
-H "X-Api-Key: fat_your_key_here" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: invoice-2026-00042" \
-d @invoice.json
{
"documentType": "Invoice",
"invoiceNumber": "INV-2026-00042",
"issueDate": "2026-06-16",
"currency": "AED",
"seller": {
"name": "Your Company LLC",
"trn": "100987654300003"
},
"buyer": {
"name": "ACME Trading LLC",
"trn": "100123456700003",
"participantId": "iso6523-actorid-upis::0235:100123456700003",
"address": {
"line1": "12 Sheikh Zayed Road",
"city": "Dubai",
"countrySubentity": "Dubai",
"countryCode": "AE"
}
},
"references": {
"purchaseOrderId": "PO-9981",
"buyerReference": "ACME-REF-77"
},
"delivery": {
"actualDeliveryDate": "2026-06-15",
"incoterms": "DAP",
"streetName": "Warehouse 4, Al Quoz",
"city": "Dubai",
"countryCode": "AE"
},
"allowancesCharges": [
{
"isCharge": false,
"amount": 50.00,
"reasonCode": "95",
"reason": "Loyalty discount",
"vatCategory": "S",
"vatRate": 5
}
],
"paymentMode": "30",
"paymentBankAccount": "AE070331234567890123456",
"lines": [
{
"description": "Steel bolts M8",
"quantity": 100,
"unitCode": "EA",
"unitPrice": 2.50,
"vatCategory": "S",
"vatRate": 5,
"sellersItemId": "BOLT-M8",
"itemTypeCode": "G",
"classifications": [
{ "code": "31161600", "listId": "UNSPSC" }
],
"allowancesCharges": [
{ "isCharge": false, "amount": 10.00, "reason": "Bulk discount" }
]
}
]
}
Note
documentType accepts Invoice, CreditNote, SelfBillingInvoice, or
SelfBillingCreditNote. A credit note also requires precedingInvoiceNumber
(the invoice it corrects). vatCategory accepts S (standard 5%), Z
(zero-rated), E (exempt), O (out of scope), or AE (reverse charge) — on
any line whose vatCategory is E, an exemptionReasonCode is required.
Read the response
A successful create returns 201 with the document in status Draft — it
is stored and validated, but not yet sent anywhere:
{
"id": "9f1c2b7e-…",
"invoiceNumber": "INV-2026-00042",
"status": "Draft",
"participantDelivery": "NotApplicable",
"createdAt": "2026-06-16T09:30:00Z",
"links": { "self": "/v1/invoices/9f1c2b7e-…" }
}
If the request fails, you'll get a JSON error body and a status code — see Errors.
Submit it for Peppol delivery
Optionally preflight with POST /invoices/{id}/validate (runs the PINT-AE
schematron without sending), then submit:
curl -X POST https://integration.fatorly.com/v1/invoices/9f1c2b7e-…/submit \
-H "X-Api-Key: fat_your_key_here" \
-H "Idempotency-Key: submit-2026-00042"
Submission is asynchronous: the call returns 202 with status: "Pending".
Poll GET /invoices/{id} until the status settles:
status | Meaning |
|---|---|
Draft | Created, not yet submitted |
Pending | Queued or being delivered over Peppol |
Sent | Delivered |
DeliveryFailed | Submission failed — see submissionError, fix with PUT, then resubmit |
Received | An inbound (purchase) document |
Warning
Every POST must include an Idempotency-Key header. Without it the request
is rejected with 400. Reuse the same key when you retry so a duplicate is
never created — see Idempotency.