Salta al contingut
Log in

Submissió d'un fitxer de Flux 10 e-reporting generat per tu

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 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.

  • Un compte francès a B2Brouter amb el Tax Report Setting dgfip habilitat. Consulta els passos 1 i 2 de la guia DGFiP.
  • X-B2B-API-Version: 2026-03-02 o 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 per https://api.b2brouter.net.

POST /accounts/{ACCOUNT_ID}/ledgers/import

El 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).

Finestra del terminal
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.xml

Resposta — 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.

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.

#ComprovacióSi falla
1Content-Type: application/octet-stream406Content-Type must be application/octet-stream
2Mida del cos ≤ 100 Mo (límit IRR_TAILLE del PPF, v3.2 §3.4.2)422The payload exceeds the PPF file limit of 100 Mo
3Validació XSD contra el paquet oficial v3.2422 amb el detall dels errors de l’esquema
4Versió d’API ≥ 2026-03-02422DGFiP F10 import requires API version 2026-03-02 or later
5El compte té el setting dgfip habilitat422The account has no enabled DGFiP e-reporting configuration
6El SIREN de <Issuer><Id> coincideix amb l’empresa del compte422The <Issuer> SIREN (…) does not match the account's company
7Un únic sub-flux (transactions o payments)422The 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.

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.

EscenariResposta
Clau nova201 amb el ledger creat
Mateixa clau, mateix payload200 amb el ledger que ja existia — no es crea cap duplicat
Mateixa clau, payload diferent409Idempotency-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.

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 amb schemeId="0238", RoleCode WK), 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.

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.

EstatCDV del PPFSignificat
newImportat i validat, pendent de dipòsit
sentDipositat al PPF
acknowledged500 — ReçueEl PPF ha rebut el fitxer
depositedDipòsit acceptat pel PPF
registered300Terminal — declaració registrada per la DGFiP
refused301Terminal — rebutjada; error_code i error_description porten el motiu
errorError de transmissió; error_description porta el detall

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.

Finestra del terminal
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"
}
}
GET /ledgers/{LEDGER_ID}/download

Retorna 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.

GET /ledgers/{LEDGER_ID}/download_response

Retorna el CDV rebut del PPF. Mentre no n’hi ha cap, retorna 404.

En mode Sandbox, download i download_response retornen 503: no hi ha dipòsit real ni respostes del PPF.