Flux 10: dipositar un fitxer que genera el teu sistema
Com dipositar al PPF un fitxer de Flux 10 que genera el teu sistema.
Aquesta guia explica com dipositar al PPF un fitxer de Flux 10 (e-reporting) que ja genera el teu sistema, sense que les factures subjacents passin per la facturació de B2Brouter. B2Brouter valida el fitxer contra l’XSD oficial v3.2, el normalitza per al dipòsit i el transmet a la DGFiP com a Plateforme Agréée, i et retorna els estats del cicle CDV per webhook i per API. És un camí alternatiu al pipeline natiu — on envies dades de factura en JSON i B2Brouter construeix el F10 — i tots dos comparteixen la mateixa canonada de sortida cap al PPF.
Per a qui és aquesta guia
Section titled “Per a qui és aquesta guia”Per a integradors i editors de programari que ja produeixen el seu propi <Report> F10
i només necessiten un canal acreditat per dipositar-lo. Si el que vols és que B2Brouter
generi el F10 a partir de les teves factures, no facis servir aquesta guia: consulta la
secció d’e-Reporting (Flux 10) de la guia DGFiP.
Prerequisits
Section titled “Prerequisits”- Un compte francès a B2Brouter amb el Tax Report Setting
dgfiphabilitat. Consulta els passos 1 i 2 de la guia DGFiP. X-B2B-API-Version: 2026-03-02o posterior.- Els permisos d’API per als endpoints de ledgers activats al teu pla. Si reps un
403, obre un tiquet de suport per fer-los habilitar. - El fitxer F10 vàlid contra el paquet XSD oficial v3.2.
Els exemples fan servir
https://api-staging.b2brouter.net. Per a producció, substitueix-ho perhttps://api.b2brouter.net.
Dipositar el fitxer
Section titled “Dipositar el fitxer”POST /accounts/{ACCOUNT_ID}/ledgers/importEl cos de la petició és el XML cru, amb Content-Type: application/octet-stream
(qualsevol altre content type es rebutja: així evitem que Rails intenti interpretar el
cos com a paràmetres).
curl --request POST \ --url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/ledgers/import \ --header 'X-B2B-API-Key: {YOUR_API_KEY}' \ --header 'X-B2B-API-Version: 2026-03-02' \ --header 'Content-Type: application/octet-stream' \ --header 'Idempotency-Key: f10-2026-01-transactions-001' \ --data-binary @flux10-transactions.xmlResposta — 201 Created:
{ "ledger": { "id": 68916, "type": "dgfip", "state": "new" }}L’id del ledger és l’identificador amb què seguiràs tot el cicle de vida. Guarda’l.
Estructura mínima del fitxer
Section titled “Estructura mínima del fitxer”El fitxer és un <Report> sense namespace. B2Brouter en llegeix tres coses per decidir
si el pot dipositar: el <Issuer>, el sub-flux declarat i la validesa XSD.
<?xml version="1.0" encoding="UTF-8"?><Report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ReportDocument> <Id>el-teu-identificador</Id> <Name>Déclaration Transactions Janvier 2026</Name> <IssueDateTime> <DateTimeString>202602110400</DateTimeString> </IssueDateTime> <TypeCode>IN</TypeCode> <Sender> <!-- El substituïm per la identitat de PA de B2Brouter en dipositar --> <Id schemeId="0238">0426</Id> <Name>PDP426</Name> <RoleCode>WK</RoleCode> <URIUniversalCommunication> <URIID>contact@exemple.fr</URIID> </URIUniversalCommunication> </Sender> <Issuer> <!-- Ha de coincidir amb el SIREN de l'empresa del compte destí --> <Id schemeId="0002">832987911</Id> <Name>METACORTEX</Name> <RoleCode>SE</RoleCode> <URIUniversalCommunication> <URIID>contact@metacortex.fr</URIID> </URIUniversalCommunication> </Issuer> </ReportDocument> <TransactionsReport> <!-- … o <PaymentsReport>, però no tots dos alhora --> </TransactionsReport></Report>Un sol sub-flux per dipòsit. El PPF transmet transaccions i encaixos per separat
(spec v3.2 §3.7.7): un <Report> ha de portar <TransactionsReport> o
<PaymentsReport>. El sub-flux declarat determina el mode del ledger. Un report amb tots
dos, o sense cap dels dos, es rebutja.
Validacions, en ordre
Section titled “Validacions, en ordre”| # | Comprovació | Si falla |
|---|---|---|
| 1 | Content-Type: application/octet-stream | 406 — Content-Type must be application/octet-stream |
| 2 | Mida del cos ≤ 100 Mo (límit IRR_TAILLE del PPF, v3.2 §3.4.2) | 422 — The payload exceeds the PPF file limit of 100 Mo |
| 3 | Validació XSD contra el paquet oficial v3.2 | 422 amb el detall dels errors de l’esquema |
| 4 | Versió d’API ≥ 2026-03-02 | 422 — DGFiP F10 import requires API version 2026-03-02 or later |
| 5 | El compte té el setting dgfip habilitat | 422 — The account has no enabled DGFiP e-reporting configuration |
| 6 | El SIREN de <Issuer><Id> coincideix amb l’empresa del compte | 422 — The <Issuer> SIREN (…) does not match the account's company |
| 7 | Un únic sub-flux (transactions o payments) | 422 — The report carries both transactions and payments; split it into two deposits o The report carries neither transactions nor payments |
L’element arrel decideix l’autoritat: un <Report> sense namespace s’interpreta com a F10
de la DGFiP; qualsevol altra arrel segueix tractant-se com un ledger Verifactu, de manera
que l’import de Verifactu continua funcionant a totes les versions d’API.
Idempotència
Section titled “Idempotència”Envia una capçalera Idempotency-Key amb cada dipòsit. Si no n’envies, fem servir el
SHA256 del payload, de manera que reenviar un fitxer idèntic també és idempotent.
| Escenari | Resposta |
|---|---|
| Clau nova | 201 amb el ledger creat |
| Mateixa clau, mateix payload | 200 amb el ledger que ja existia — no es crea cap duplicat |
| Mateixa clau, payload diferent | 409 — Idempotency-Key already used with a different payload |
La clau és única per compte. Les claus de més de 64 caràcters o amb caràcters no ASCII s’emmagatzemen com a resum SHA256; el comportament és el mateix.
Normalització del dipòsit
Section titled “Normalització del dipòsit”Abans de transmetre, B2Brouter reescriu dos nodes del teu fitxer:
<ReportDocument><Id>passa a ser l’id del ledger. És la clau amb què el PPF correlaciona els CDV de retorn; si mantinguéssim un valor triat pel client, un dipòsit podria reclamar les respostes d’un ledger d’un altre compte.<ReportDocument><Sender>passa a ser la identitat de Plateforme Agréée de B2Brouter (matricule ambschemeId="0238",RoleCodeWK), perquè el dipositant al PPF som nosaltres. L’AIFE ha confirmat per escrit que aquesta normalització de dipòsit és acceptable.
La resta del fitxer no es toca, i la tramesa original es conserva tal com l’hem rebuda com a adjunt d’auditoria del ledger.
Enviament al PPF
Section titled “Enviament al PPF”El ledger importat queda en estat new i el cron d’enviament el recull en la primera
execució passada la mitjanit del dia del dipòsit: en la pràctica, es diposita al PPF
l’endemà. El transport és un dipòsit SFTP al PPF (tar.gz amb l’envelope F10).
El règim de TVA no intervé en els fitxers importats: la periodització per règim és una funció del pipeline natiu. Aquí la cadència és la del dipòsit, i el període declarat és el que tu escrius al fitxer.
Seguir el cicle de vida
Section titled “Seguir el cicle de vida”Estats del ledger
Section titled “Estats del ledger”| Estat | CDV del PPF | Significat |
|---|---|---|
new | — | Importat i validat, pendent de dipòsit |
sent | — | Dipositat al PPF |
acknowledged | 500 — Reçue | El PPF ha rebut el fitxer |
deposited | — | Dipòsit acceptat pel PPF |
registered | 300 | ✅ Terminal — declaració registrada per la DGFiP |
refused | 301 | ❌ Terminal — rebutjada; error_code i error_description porten el motiu |
error | — | Error de transmissió; error_description porta el detall |
Webhooks (recomanat)
Section titled “Webhooks (recomanat)”Subscriu-te a l’esdeveniment ledger.state_change per rebre cada transició sense
pollejar. Es dispara en entrar a sent, error, acknowledged, deposited, registered
i refused.
{ "web_hook": { "url": "https://example.com/hooks", "events": ["ledger.state_change"] }}El cos que reps porta l’id del compte i el ledger sencer:
{ "account_id": 42, "object": { "object": "ledger", "id": 68916, "state": "registered", "mode": null, "error_code": null, "error_description": null, "document_type_code": "xml.ledger.dgfip.transactions", "sent_at": "2026-07-25T02:04:11.000Z", "created_at": "2026-07-24T10:12:03.000Z" }}Si dos CDV arriben molt seguits, l’estat ja superat no es lliura: sempre reps l’estat vigent, no necessàriament un lliurament per transició. Consulta el ledger si necessites confirmar l’estat actual. Per a la verificació de la signatura del webhook, consulta la guia de webhooks.
Consultar l’estat
Section titled “Consultar l’estat”curl --request GET \ --url https://api-staging.b2brouter.net/ledgers/{LEDGER_ID} \ --header 'X-B2B-API-Key: {YOUR_API_KEY}' \ --header 'X-B2B-API-Version: 2026-03-02'{ "ledger": { "id": 68916, "type": "dgfip", "state": "refused", "error_code": "303", "error_description": null, "created_at": "2026-07-24T10:12:03.000Z", "sent_at": "2026-07-25T02:04:11.000Z" }}Descarregar el fitxer dipositat
Section titled “Descarregar el fitxer dipositat”GET /ledgers/{LEDGER_ID}/downloadRetorna el XML normalitzat que hem dipositat (amb l’<Id> i el <Sender> reescrits),
disponible des del moment de l’import. És el document que cal conservar com a prova del que
s’ha declarat.
Descarregar la resposta del PPF
Section titled “Descarregar la resposta del PPF”GET /ledgers/{LEDGER_ID}/download_responseRetorna el CDV rebut del PPF. Mentre no n’hi ha cap, retorna 404.
En mode Sandbox,
downloadidownload_responseretornen 503: no hi ha dipòsit real ni respostes del PPF.