Send invoice
This API allows sending an invoice to its recipient via one of the routing codes defined by the standard.
The Iopole system enables issuing an invoice in France or in any other country using Peppol network or point to point interoperability connector.
Link to swaggerasynchronous
user
is needed in order to use this endpointTo enable the routing of the invoice to the recipient, the routing information contained in the invoice must be correct. Additionally, a structural and semantic validation of the content is performed for each invoice before its transfer to the destination platform.
Validation step
When issuing an invoice, if a validation error is detected, the invoice is rejected, and a status notification (containing the error description) is sent to the status notification endpoint.
Format | Description |
---|---|
Factur-X | Antivirus analyse |
Factur-X | Verification of PDF/A-3 compliance of the PDF |
Factur-X | Verification of the validity of the XMP data in the PDF |
Factur-X, UBL, CII | Verification of the validity of the signature (if present) |
Factur-X, UBL, CII | Verification of the XML metadata structure (XSD validation) |
Factur-X, UBL, CII | Verification of metadata compliance (Schematron validation) |
Extraction of routing data
If the invoice validation steps do not result in any errors, the routing data is extracted from the invoice. This information allows the system to search for the recipient in the directory and locate their destination platform. If a routing error is detected (e.g., routing information is missing or invalid, recipient not found in the directory, etc.), the invoice is rejected, and a status notification (containing the error description) is sent to the status notification endpoint if defined.
file
property.
When calling the invoice issuance endpoint, a unique identifier is created. This identifier allows tracking the status of the invoice throughout its lifecycle. The issuance of an invoice is asynchronous, meaning that the call to the invoice issuance endpoint never fails (except for authentication issues). Status updates are provided via calls to the status notification endpoints (see webhook documentation) You also can poll our API /GET status.
POST /v1/invoice
- bash
- javascript
- .NET
curl -X 'POST'
https://api.ppd.iopole.fr//v1/invoice'
-H 'accept: application/json'
-H 'Authorization: Bearer ${token}'
-H 'Content-Type: multipart/form-data'
-F 'file=@F20240610-2111-002.cii.xml.pdf;type=application/pdf'
const got = require('got');
const FormData = require('form-data');
const fs = require('fs');
const token = 'your_token_here';
(async () => {
try {
const form = new FormData();
form.append('file', fs.createReadStream('F20240610-2111-002.cii.xml.pdf'), {
contentType: 'application/pdf',
});
const response = await got.post('https://api.ppd.iopole.fr//v1/invoice', {
headers: {
'accept': 'application/json',
'Authorization': `Bearer ${token}`,
...form.getHeaders(), // Add the form headers
},
body: form,
responseType: 'json',
});
console.log(response.body);
} catch (error) {
console.error(error.response.body);
}
})();
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var token = "your_token_here";
var filePath = "F20240610-2111-002.cii.xml.pdf";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("accept", "application/json");
client.DefaultRequestHeaders.Add("Authorization", "Bearer ${token}");
using var form = new MultipartFormDataContent();
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf");
form.Add(fileContent, "file", Path.GetFileName(filePath));
try
{
var response = await client.PostAsync("https://api.ppd.iopole.fr//v1/invoice", form);
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
}
catch (HttpRequestException ex)
{
Console.WriteLine("Request error: {ex.Message}");
}
}
}
201 Created
{
"type": "INVOICE",
"id": "6d9bf1a6-25a7-4d48-b641-623c05b0a967"
}
Workflow
- Get authentication token (/oauth/token)
- Send document (/invoice) :
- file [1-1] : File of type (pdf / xml)
- attachment [0-n] : Attachment file.
Response OK
Returns the Iopole invoice identifier (GUID)
{
"invoiceId": "a664504c-a585-46fb-820e-76387d0da7e4"
}
More example
This example describes the steps involved in issuing an invoice to the ‘Phenix SOLAR’ buyer.
Step 1 :Description
Search for the customer ‘Phenix SOLAR’ in the directory
Request
- Search into all networks
- Search by name
[GET]: https://api.ppd.iopole.fr//v1/directory?value=Phenix SOLAR
- Search by siret
[GET]: https://api.ppd.iopole.fr//v1/directory?value=94920165100013
- Search by name
- Only search into French network
- Search by name
[GET]: https://api.ppd.iopole.fr//v1/directory/search?q=(invoice.buyer.name:"Phenix SOLAR")
- Search by siret
[GET]: https://api.ppd.iopole.fr//v1/directory/search?q=(invoice.buyer.siret:"94920165100013"")
- Search by name
Reponse
[
{
"source": "French Directory",
"directoryId": "15777e31-2a24-4747-beab-86d2fcd0f8a3",
"country": "FR",
"name": "PHENIX SOLAR",
"electronicAddress": null,
"entity": {
"siren": "949201651",
"siret": "94920165100013",
"routingCode": null,
"routingCodeType": null,
"entityType": "Assujetti",
"status": "ACTIVE"
}
}
]
Step 2 :
Description
Use of directory information to create the invoice (siren, siret, routing code or electronic address) and send the invoice
Request
File = Previously generated invoice path
[POST]: https://api.ppd.iopole.fr//v1/invoice
/status
and can be consulted by calling the Iopole status search endpoint.