France API integration
This page is for integrators who connect an ERP or middleware to xTool over the public API (/api/v2/..., x-api-key header).
France configuration (Annuaire / QAS registration, company identifiers, tax-report mode) is managed in the web UI only. There is no public /api/v2/france/... endpoint. After the configuration is Active, all invoice exchange, payments, and tax-report reads go through the standard document / transaction / payment APIs.
Related pages:
- Practical request examples: Send and receive invoices
- QAS setup: Test Environment
- Concepts: Transactions, Payments, Tax reports
- OpenAPI: API Reference
Integration model
France API work is built on standard xTool entities. Use the exact names below — they match the API resources.
| Entity | API resource | You create? | Role |
|---|---|---|---|
| Document | /api/v2/documents |
Yes (upload) or xTool (inbound) | Invoice / credit note content |
| Transaction | /api/v2/transactions |
Indirectly via send, or xTool on receive |
One channel attempt: send.france or receive.france |
| Transaction Event | /api/v2/transaction-events |
No | Immutable history entry on a transaction (prepare, send, receive, approved, …) |
| Transaction Event File | /api/v2/transaction-event-files/.../download |
No | Binary attachment belonging to a transaction event (XML payload, acknowledgement, …) |
| Transaction Action | /api/v2/transactions/{id}/actions |
Yes (buyer) | Command you submit on a receive.france transaction (acknowledge / approve / partially approve / dispute / refuse) |
| Payment | /api/v2/payments |
Yes | Money movement + allocations to documents |
| Tax report | /api/v2/tax-reports |
No | Read-only regulatory report built by xTool |
Object model:
flowchart TD
Document --> Transaction
Transaction --> Events["Transaction Event[]"]
Events --> Files["Transaction Event File[]"]
Transaction --> Actions["Transaction Action[]"]
- Transaction type:
send.franceorreceive.france - Actions: buyer lifecycle +
payment_sentonreceive.france;payment_receivedonsend.france
Transaction Action ≠ Transaction Event.
You POST a Transaction Action. For buyer lifecycle actions, xTool records a matching Transaction Event (for example action france.invoice.approve → event france.invoice.approved). Action france.invoice.payment_sent (receive.france) marks payment as transmitted. Action france.invoice.payment_received (send.france) creates a Payment allocated to the document (same as POST /api/v2/payments). On B2B domestic, these map to CDV lifecycle codes (see below); B2C and B2B cross-border may not use CDV.
See also Transactions.
Transaction, events, actions, and files
This section is the core object model for France lifecycle tracking.
Transaction
A Transaction is one send or receive attempt for one document on one channel.
| Field (API) | Notes |
|---|---|
id |
Transaction UUID — store it for polling |
document_id |
Parent document |
type |
send.france or receive.france |
status |
Lifecycle of the attempt (initial → processing → completed / failed) |
metadata |
Client-safe France fields such as invoice_state (no internal provider ids) |
status_log |
Optional via include=status_log |
events |
Optional via include=events (nested events include files) |
actions |
Optional via include=actions |
One document can have multiple transactions (resend, receive, other channels). Always follow the specific France transaction you care about.
Transaction Event
A Transaction Event is a historical record of something that already happened on that transaction. Clients never create events.
| Field (API) | Notes |
|---|---|
id |
Event UUID |
transaction_id |
Parent transaction (on get-by-id / list) |
type |
Event type string (see table below) |
metadata |
Optional event-specific data |
files |
Nested Transaction Event File items when loaded |
created_at / updated_at |
Timestamps |
include=events on the transaction get also loads nested event files.
France transaction event types
type |
Typical meaning |
|---|---|
france.invoice.prepare |
Invoice prepared / validated for the provider |
france.invoice.send |
Submitted to the France channel (outbound) |
france.invoice.receive |
Inbound invoice received from the channel |
france.invoice.acknowledged |
Buyer acknowledged the invoice (CDV 204) |
france.invoice.approved |
Buyer fully approved the invoice (CDV 205) |
france.invoice.partially_approved |
Buyer partially approved the invoice (CDV 206) |
france.invoice.disputed |
Buyer disputed the invoice (CDV 207) |
france.invoice.suspended |
Buyer suspended processing (CDV 208; channel/CDAR) |
france.invoice.completed |
Seller completed after suspension (CDV 209; channel/CDAR) |
france.invoice.refused |
Buyer refused the invoice (CDV 210) |
france.invoice.payment_sent |
Buyer marked payment as sent (CDV 211; receive.france) |
france.invoice.payment_received |
Seller recorded payment received (CDV 212; send.france) |
france.tax_report.send |
Tax report submitted |
france.tax_report.acknowledged |
Tax report acknowledged |
france.tax_report.registered |
Tax report registered |
CDV codes (204–212) come from the domestic B2B lifecycle (CDAR / AFNOR XP Z12-012). They apply to B2B domestic flows. B2C and B2B cross-border use different reporting paths and may not produce these CDV lifecycle codes; xTool still records the same transaction event types when the channel reports the corresponding status.
Timing depends on domestic vs cross-border scenarios and provider processing. Poll and process new event ids only.
When the channel delivers a lifecycle notification (CDAR / ApplicationResponse) for B2B domestic, xTool prefers the CDV code in the XML (ProcessConditionCode / ResponseCode) over the provider invoice state. That is what distinguishes e.g. full approval (205) from partial approval (206).
Transaction Event File
A Transaction Event File is a stored file attached to a Transaction Event (for example the invoice XML that was sent or received, or a related acknowledgement payload).
| Field (API) | Notes |
|---|---|
id |
File UUID — required for download |
filename |
Original / stored name |
content_type |
MIME type |
created_at |
Timestamp |
Files appear nested under events when you list/get events. Download content separately:
Typical usage:
- Poll transaction with
include=events - Find the event of interest (for example
france.invoice.receiveorfrance.invoice.send) - Read
files[].id/filename/content_type - Download each needed file by id
There is no create/update/delete of event files via the public client API.
Transaction Action
A Transaction Action is a command you ask xTool to perform on an existing transaction. Today France buyer actions exist only on receive.france.
| Field (API) | Notes |
|---|---|
id |
Action UUID |
transaction_id |
Parent transaction |
type |
Buyer lifecycle action, france.invoice.payment_sent, or france.invoice.payment_received |
parameters |
Action payload (for refuse: reason / optional reason_code) |
status |
initial → processing → completed / failed |
created_at |
Timestamp |
There is no get-by-id endpoint for a single action. Use the list, or include=actions on the transaction get.
CDV codes → actions (B2B domestic)
CDV codes apply to B2B domestic only (CDAR / AFNOR XP Z12-012). B2C and B2B cross-border may not use them. Codes without an action are reported by the channel only.
| CDV | Label | Action type |
Event type |
Transaction |
|---|---|---|---|---|
| 204 | Prise en charge | france.invoice.acknowledge |
france.invoice.acknowledged |
receive.france |
| 205 | Approuvée | france.invoice.approve |
france.invoice.approved |
receive.france |
| 206 | Approuvée partiellement | france.invoice.partially_approve |
france.invoice.partially_approved |
receive.france |
| 207 | En litige | france.invoice.dispute |
france.invoice.disputed |
receive.france |
| 208 | Suspendue | — (channel only) | france.invoice.suspended |
either |
| 209 | Complétée | — (channel only) | france.invoice.completed |
either |
| 210 | Refusée | france.invoice.refuse |
france.invoice.refused |
receive.france |
| 211 | Paiement transmis | france.invoice.payment_sent |
france.invoice.payment_sent |
receive.france |
| 212 | Encaissée | france.invoice.payment_received |
france.invoice.payment_received |
send.france |
Earlier channel statuses such as 200 (Déposée), 202 (Reçue), and 203 (Mise à disposition) are also B2B domestic CDV codes; xTool does not expose client actions for them.
France action types → resulting events
Action type |
Body | Result |
|---|---|---|
france.invoice.acknowledge |
{ "type": "france.invoice.acknowledge" } |
Event france.invoice.acknowledged |
france.invoice.approve |
{ "type": "france.invoice.approve" } |
Event france.invoice.approved |
france.invoice.partially_approve |
{ "type": "france.invoice.partially_approve", "amount": "...", "reason": "..." } (amount_code optional, default MAPTTC) |
Event france.invoice.partially_approved |
france.invoice.dispute |
{ "type": "france.invoice.dispute", "reason": "..." } |
Event france.invoice.disputed |
france.invoice.refuse |
{ "type": "france.invoice.refuse", "reason": "..." } (reason required; reason_code optional) |
Event france.invoice.refused |
france.invoice.payment_sent |
{ "type": "france.invoice.payment_sent" } (receive.france only) |
Event france.invoice.payment_sent |
france.invoice.payment_received |
{ "type": "france.invoice.payment_received" } (optional amount / currency / paid_at; send.france only) |
Creates a Payment allocated to the document; event france.invoice.payment_received (after channel notification) |
Rules:
- Submitting the same lifecycle action twice for one transaction returns conflict (
409) - Wait for action
statusto becomecompleted/failed, and for the matching event to appear - Payment sent (
receive.france) only updates channel status; it does not create a Payment - Payment received (
send.france) creates the Payment immediately and syncs to the provider
Authentication and organisation scope
The API key is scoped to an organisation. Every document, transaction, payment, and tax report you see belongs to that organisation.
Checklist:
- Create an API key in the web UI with permission to send via France (and to read documents / transactions / payments as needed).
- Call
/api/v2/...with that key. - Ensure the organisation has at least one Active France configuration (web UI → Channels → France).
France configuration and which account sends
France configuration is not selected in the send request body. On send.france, xTool:
- Takes the document’s organisation
- Loads Active France configurations for that organisation (with a provider account id)
- Matches the document sender (
metadata.sender_id, typically the supplier endpoint / SIREN) to configurationsiren/siret/cin_value - If no match, falls back to the first Active configuration with an account
Practical rules:
- Put the seller identifiers in the invoice so they match the configuration you intend to send from
- One organisation may have several France configurations (for example two QAS companies for send/receive tests)
- Reception-only mode (
annuaire_only) cannot send invoices
Configuration lifecycle (NEW → … → DIRECTORY_PENDING / SCHEDULED → ACTIVE) is web + background jobs. API exchange requires Active.
Formats
Preferred for France channel tests and production-like flows:
| Format code | Syntax | Notes |
|---|---|---|
france_cius.invoice.1_0.xml_ubl.en16931 |
UBL | France CIUS invoice |
france_cius.invoice.1_0.xml_cii.en16931 |
CII | France CIUS invoice |
france_cius.credit_note.1_0.xml_ubl |
UBL | France CIUS credit note |
peppol_bis_billing_france.invoice.3_0.xml_ubl |
UBL | Peppol BIS Billing France invoice (explicit) |
peppol_bis_billing_france.credit_note.3_0.xml_ubl |
UBL | Peppol BIS Billing France credit note (explicit) |
xtool.invoice.1_0 |
JSON | Internal model; can be converted / mapped |
xtool.credit_note.1_0 |
JSON | Internal credit note |
France CIUS models require France-specific fields such as document.profile_id (billing mode, for example S1).
Domestic B2B send typically expects EUR, a short enough invoice number, and a French buyer routing id (PIN / endpoint) where required. Validation failures return before or during prepare.
Upload options:
Keep the returned document id.
Example France CIUS UBL (test)
Use this body for POST /api/v2/documents/upload/xml?direction=outbound&require_valid=true in the xTool test environment, then POST .../send with { "transaction_type": "send.france" }.
Before upload:
- Replace seller SIREN
256685928with the Active France configuration SIREN you send from (QAS number from your Chorus Pro dataset — see Test Environment). - Replace buyer SIREN
346628948with another QAS company that is also registered / Active as receiver (second France configuration, or a counterparty in QAS). - Align
EndpointID,PartyLegalEntity/CompanyID, and VATCompanyID(FR…+ SIREN) with those numbers. - Use a unique
cbc:IDfor each send.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
Detected / expected format: france_cius.invoice.1_0.xml_ubl.en16931.
Step A — Upload
Upload CIUS XML or a JSON model (see formats above).
Step B — Send
Store transaction.id.
Step C — Poll the transaction
Recommended poll:
Also useful:
| Call | Purpose |
|---|---|
GET /api/v2/transactions/{id}/events |
Transaction Event list (+ nested Transaction Event Files) |
GET /api/v2/transaction-events/{event_id} |
Single Transaction Event (+ files) |
GET /api/v2/transaction-event-files/{file_id}/download |
Download a Transaction Event File |
GET /api/v2/transactions?document_id={document_id} |
All transactions for one document |
Suggested polling:
- Interval: 5–30 seconds while transaction
statusisprocessing - Stop when the transaction reaches
completedorfailed - Persist last seen Transaction Event ids so you only process new events
- When you need payloads, download Transaction Event Files by
files[].id
Typical outbound Transaction Events
Transaction Event type |
Meaning |
|---|---|
france.invoice.prepare |
Built / validated for the provider |
france.invoice.send |
Submitted to the France channel |
france.invoice.approved |
Buyer approved |
france.invoice.refused |
Buyer refused |
france.invoice.payment_received |
Payment received confirmed (CDV 212, B2B domestic) |
france.tax_report.send / acknowledged / registered |
Related tax-report processing |
Exact timing depends on scenario (domestic vs cross-border) and provider processing. Some tax-report events may appear later.
Step D — Optional payment
Allocate to the document id (not the transaction id). For outbound invoices, POST /api/v2/transactions/{transaction_id}/actions with { "type": "france.invoice.payment_received" } creates the same kind of payment for that transaction's document; the matching france.invoice.payment_received event usually appears after channel notification (on B2B domestic, CDV 212). For inbound invoices, use france.invoice.payment_sent to mark payment as transmitted without creating a Payment (on B2B domestic, CDV 211).
Inbound integration pattern
Inbound documents are created by xTool when the channel delivers them. Your job is to discover, store, and respond.
Discovery
Pattern:
- Poll inbound documents and/or
receive.francetransactions on a schedule - Deduplicate by document id
- Fetch content once, then drive ERP posting
Read content
Optional:
Inspect receive transaction
Transaction Event france.invoice.receive typically carries the inbound invoice as Transaction Event Files. Download them via /api/v2/transaction-event-files/{id}/download.
Buyer response (Transaction Actions)
Only on receive.france:
Other buyer lifecycle actions: france.invoice.acknowledge, france.invoice.partially_approve, france.invoice.dispute.
Then poll Transaction Events until the matching lifecycle event appears (for example france.invoice.approved or france.invoice.refused) on both receiver and sender sides as the network propagates. Also check the Transaction Action status (processing → completed / failed).
Payments API (France-relevant rules)
| Method | Path |
|---|---|
POST |
/api/v2/payments |
GET |
/api/v2/payments |
GET |
/api/v2/payments/{payment_id} |
PATCH |
/api/v2/payments/{payment_id} |
DELETE |
/api/v2/payments/{payment_id}/delete |
Rules of thumb:
currencyis required on create (useEURfor typical France domestic flows)- Allocations target
document_id+amount PATCHamount does not rewrite allocations unless you also sendallocations- Partial payments are normal: multiple payments over time for one invoice
Tax reports API
Read-only:
Reports list sources (document, payment, …). You do not create tax reports via API; they appear from France processing (sometimes delayed for aggregated / cross-border scenarios).
Endpoint map
Documents
| Method | Path | Notes |
|---|---|---|
POST |
/api/v2/documents/upload/xml |
Outbound/inbound via query direction |
POST |
/api/v2/documents/upload/model |
JSON model upload |
GET |
/api/v2/documents |
Filter direction=inbound / outbound |
GET |
/api/v2/documents/{id} |
Optional include=model, status_log |
GET |
/api/v2/documents/{id}/xml |
XML representation |
GET |
/api/v2/documents/{id}/model |
Model representation |
POST |
/api/v2/documents/{id}/send |
Body: transaction_type |
POST |
/api/v2/documents/{id}/ack |
Optional inbound ack |
Transactions / Transaction Events / Transaction Actions / Transaction Event Files
| Method | Path | Notes |
|---|---|---|
GET |
/api/v2/transactions |
Filters: document_id, transaction_type, transaction_status |
GET |
/api/v2/transactions/{id} |
include=events, actions, status_log |
GET |
/api/v2/transactions/{id}/events |
Transaction Events (includes nested Transaction Event Files) |
GET |
/api/v2/transaction-events/{id} |
Single Transaction Event + files |
GET |
/api/v2/transaction-event-files/{id}/download |
Download Transaction Event File content |
GET |
/api/v2/transactions/{id}/actions |
List Transaction Actions |
POST |
/api/v2/transactions/{id}/actions |
Create Transaction Action (buyer lifecycle / paid) |
There is no get-by-id for a single Transaction Action.
Payments / tax reports
See tables above.
Error handling
| Situation | What to do |
|---|---|
400 on upload / send |
Fix validation / format / France rules (currency, profile, buyer id, …) |
400 “No active France configuration” |
Complete Channels → France onboarding in the web UI |
400 annuaire_only cannot issue |
Switch tax-report mode to full for sending |
Transaction failed |
Read Transaction Events + status_log; fix data and send again (new Transaction) |
| Missing inbound | Confirm receiver configuration is Active; poll direction=inbound and receive.france |
Payment created but no paid event yet |
Wait for channel confirmation; keep polling Transaction Events |
Always log transaction_id, document_id, Transaction Event types, and Transaction Action ids for support.
Recommended implementation checklist
- Web setup — Active France configuration(s); note SIREN/SIRET used as seller/buyer
- Auth — API key with France send (+ read) rights
- Outbound worker — upload →
send.france→ poll Transaction / Transaction Events / Event Files → optional Payment - Inbound worker — poll inbound /
receive.france→ fetch document XML/model and/or Transaction Event Files → ERP → Transaction Actions (approve / refuse / …) → optional Payment - Reporting — periodically
GET /api/v2/tax-reportsand reconcile sources to documents/payments - Idempotency — store external invoice number ↔ xTool document id; ignore duplicate inbound ids
- Observability — persist Transaction Event timeline (and action outcomes) per document for audits
For copy-paste HTTP examples of each step, use Send and receive invoices.