Skip to content

Send and receive invoices

Once your France configuration is Active in the xTool web app, you can exchange invoices through the API.

All examples below use the public API (x-api-key header). France configuration itself is managed in the web UI only — there is no /api/v2/france/... endpoint.

What you work with

Concept Role
Document The invoice (or credit note) content
Transaction The communication flow for that document (send.france or receive.france)
Event Something that already happened (sent, received, approved, …)
Action Something you ask xTool to do (approve / refuse an incoming invoice)
Payment Money movement; allocate it to an invoice document to report payment
Tax report Regulatory reporting entity (created by xTool; readable via API)

Actions ≠ events. You create actions. xTool records events as history.

Prerequisites

  1. France configuration status is Active (web UI → Channels → France).
  2. For sending invoices, the configuration must not be reception-only (annuaire_only).
  3. API key with permission to send via France.

Supported formats for the France channel:

Format code Use
france_cius.invoice.1_0.xml_ubl.en16931 France CIUS invoice (UBL)
france_cius.invoice.1_0.xml_cii.en16931 France CIUS invoice (CII)
france_cius.credit_note.1_0.xml_ubl France CIUS credit note
peppol_bis_billing_france.invoice.3_0.xml_ubl Peppol BIS Billing France invoice (explicit)
peppol_bis_billing_france.credit_note.3_0.xml_ubl Peppol BIS Billing France credit note (explicit)
xtool.invoice.1_0 xTool invoice (JSON)
xtool.credit_note.1_0 xTool credit note (JSON)

Send an invoice (outbound)

1. Upload the document

Option A — XML

1
2
3
POST /api/v2/documents/upload/xml?direction=outbound&require_valid=true
Content-Type: application/xml
x-api-key: <your-api-key>

Body: raw France CIUS (or other supported) XML. Full test sample: API integration — Example France CIUS UBL.

Option B — JSON model

1
2
3
POST /api/v2/documents/upload/model?direction=outbound&require_valid=true
Content-Type: application/json
x-api-key: <your-api-key>
1
2
3
4
5
6
7
8
9
{
  "format": "xtool.invoice.1_0",
  "document": { "id": "FA-2026-0019", "issue_date": "2026-08-10" },
  "supplier": { "...": "..." },
  "customer": { "...": "..." },
  "items": [],
  "taxes": [],
  "totals": { "...": "..." }
}

For France CIUS models, set "format": "france_cius.invoice.1_0.xml_ubl.en16931" and include the required France fields (for example document.profile_id).

Response includes the document id. Keep it for the next step.

2. Send via France

1
2
3
POST /api/v2/documents/{document_id}/send
Content-Type: application/json
x-api-key: <your-api-key>
1
2
3
{
  "transaction_type": "send.france"
}

Response includes the created transaction (id, type, status).

Typical send-side checks if something fails:

  • France configuration is Active and has a provider account
  • Document is valid
  • Format supports the France channel
  • Invoice rules (for example EUR currency, invoice number length, buyer PIN where required)

3. Follow the transaction

GET /api/v2/transactions/{transaction_id}?include=events&include=status_log
x-api-key: <your-api-key>

Or list events only:

GET /api/v2/transactions/{transaction_id}/events

Download a file attached to an event:

GET /api/v2/transaction-event-files/{transaction_event_file_id}/download

Get a single event:

GET /api/v2/transaction-events/{transaction_event_id}

Common send-side event types:

Event type Meaning
france.invoice.prepare Prepared for the provider
france.invoice.send Submitted to the France channel
france.invoice.acknowledged / approved / partially_approved / disputed / refused / paid Lifecycle updates from the network
france.tax_report.send / acknowledged / registered Related tax-report processing

You cannot create these events yourself — they appear as the flow progresses.


Receive an invoice (inbound)

Inbound invoices are created by xTool when the France channel delivers them. Your integration discovers and processes them.

1. Find inbound documents

GET /api/v2/documents?direction=inbound
x-api-key: <your-api-key>

Or find France receive transactions (optionally filter by document):

GET /api/v2/transactions?transaction_type=receive.france
GET /api/v2/transactions?document_id={document_id}

2. Read the invoice

1
2
3
GET /api/v2/documents/{document_id}?include=model&include=status_log
GET /api/v2/documents/{document_id}/xml
GET /api/v2/documents/{document_id}/model

Optional acknowledgement:

POST /api/v2/documents/{document_id}/ack
{ "ack": true }

3. Inspect the receive transaction

GET /api/v2/transactions/{transaction_id}?include=events&include=actions&include=status_log

The receive transaction type is receive.france. Event france.invoice.receive typically carries the inbound invoice files.


Approve, refuse, dispute, or record payment

Buyer lifecycle actions (acknowledge / approve / partially_approve / dispute / refuse / payment_sent) are only available on receive.france.

Where CDV codes are shown below, they apply to B2B domestic lifecycle (CDAR). B2C and B2B cross-border use the same xTool actions/events but may not produce these CDV codes.

Payment sent (france.invoice.payment_sent, receive.france) marks payment as transmitted on the channel. It does not create a Payment entity.

Payment received (france.invoice.payment_received, send.france) creates a Payment allocated to the transaction document (same as POST /api/v2/payments with one allocation). Amount and currency default to the document payable total; optional amount, currency, and paid_at may be passed.

1
2
3
POST /api/v2/transactions/{transaction_id}/actions
Content-Type: application/json
x-api-key: <your-api-key>

Acknowledge (CDV 204, B2B domestic)

1
2
3
{
  "type": "france.invoice.acknowledge"
}

Approve (CDV 205, B2B domestic)

1
2
3
{
  "type": "france.invoice.approve"
}

Partially approve (CDV 206, B2B domestic — amount and reason required; amount_code optional, default MAPTTC)

1
2
3
4
5
6
{
  "type": "france.invoice.partially_approve",
  "amount": "500.00",
  "reason": "Partial delivery accepted",
  "amount_code": "MAPTTC"
}

Dispute (CDV 207, B2B domestic)

1
2
3
4
{
  "type": "france.invoice.dispute",
  "reason": "Incorrect line items"
}

Refuse (reason is required; reason_code is optional)

1
2
3
4
5
{
  "type": "france.invoice.refuse",
  "reason": "Incorrect amount",
  "reason_code": null
}

Payment sent (receive.france only — CDV 211, B2B domestic)

1
2
3
{
  "type": "france.invoice.payment_sent"
}

Payment received (send.france only — CDV 212, B2B domestic)

1
2
3
{
  "type": "france.invoice.payment_received"
}

Optional overrides for payment received:

1
2
3
4
5
6
{
  "type": "france.invoice.payment_received",
  "amount": "1000.00",
  "currency": "EUR",
  "paid_at": "2026-08-14T12:00:00Z"
}

List existing actions:

GET /api/v2/transactions/{transaction_id}/actions

On success for buyer lifecycle actions, xTool records a matching event (for example france.invoice.approved or france.invoice.refused). Do not try to create those events via API.


Record a payment

Payments are separate entities. Allocate them to the invoice document so xTool can sync payment status to the France provider when a send.france transaction exists for that document.

You can also use the france.invoice.payment_received transaction action above as a shortcut that creates a payment for an outbound invoice document.

1
2
3
POST /api/v2/payments
Content-Type: application/json
x-api-key: <your-api-key>

Partial payment example:

{
  "direction": "incoming",
  "amount": "300.00",
  "currency": "EUR",
  "paid_at": "2026-08-09T00:00:00Z",
  "allocations": [
    {
      "document_id": "invoice-document-uuid",
      "amount": "300.00"
    }
  ]
}

Later payment for the remainder:

{
  "direction": "incoming",
  "amount": "700.00",
  "currency": "EUR",
  "paid_at": "2026-08-15T00:00:00Z",
  "allocations": [
    {
      "document_id": "invoice-document-uuid",
      "amount": "700.00"
    }
  ]
}

Other payment endpoints:

Method Path
GET /api/v2/payments
GET /api/v2/payments/{payment_id}
PATCH /api/v2/payments/{payment_id}
DELETE /api/v2/payments/{payment_id}/delete

After recording payment received on an outbound invoice, expect event france.invoice.payment_received on the related transaction. More detail: Payments.


Tax reports

Tax reports are created by xTool from France processing. The API is read-only for clients:

GET /api/v2/tax-reports
GET /api/v2/tax-reports/{tax_report_id}

Each report can list sources (document, payment, …).

How reporting relates to scenarios:

Scenario Invoice exchange Tax reporting
Domestic B2B send.france / receive.france Usually tied to invoice processing
Cross-border B2B send.france / receive.france Often aggregated later from eligible invoices and payments
B2C send.france Aggregated periodically (no inbound B2C e-invoice flow here)

More detail: Tax reports.


Quick reference

Outbound checklist

  1. France config Active (web UI)
  2. POST /api/v2/documents/upload/xml or /upload/model
  3. POST /api/v2/documents/{id}/send with { "transaction_type": "send.france" }
  4. Poll GET /api/v2/transactions/{tx_id}?include=events
  5. Optional: POST /api/v2/payments with allocations

Inbound checklist

  1. GET /api/v2/documents?direction=inbound and/or GET /api/v2/transactions?transaction_type=receive.france
  2. Fetch XML / model; optional ack
  3. POST /api/v2/transactions/{tx_id}/actions — approve, refuse, or other buyer lifecycle actions
  4. Optional: payments and tax-report GETs

Useful includes

GET /api/v2/transactions/{transaction_id}?include=events&include=actions&include=status_log

include=events also loads event files on nested events.

For a fuller integrator guide (auth, account matching, polling patterns, endpoint map), see API integration.