v2026-06-26
Changelog
Selecciona aquesta versió enviant X-B2B-API-Version: 2026-06-26 a les capçaleres de la teva petició.
Aquesta versió implementa canvis incompatibles. Cada canvi incompatible està marcat amb l'etiqueta Breaking.
Resum dels canvis
Section titled “Resum dels canvis”| Canvi | Àrea |
|---|---|
| Events de webhook per a factures rebudes | Webhooks |
Crear oficines via POST /accounts amb parent_id | Comptes |
| CIN independent per a oficines de contacte 🚨 Breaking | Contactes |
parent_id a les respostes de contacte | Contactes |
| Validació més estricta de contactes en crear factures 🚨 Breaking | Factures |
refuse_reason_code de DGFiP a mark_as i a les respostes de factura | Factures |
issue_after_import en crear i importar factures | Factures |
Consulta a l'Annuaire francès a /directory/fr 🚨 Breaking | Directori |
routing_codes del contacte en línia en crear factures 🚨 Breaking | Factures |
routing_codes a nivell de factura en crear factures 🚨 Breaking | Factures |
| Base imposable i quota d'impost al llistat de factures | Factures |
Filtres del llistat de factures: number ara fa coincidència per prefix i series_code | Factures |
| Generar informe fiscal retorna 201 Created 🚨 Breaking | Factures |
Preferència unit_code_format del compte | Comptes |
apply_taxes_per_line per factura | Factures |
Afegit
Section titled “Afegit”Events de webhook per a factures rebudes
Section titled “Events de webhook per a factures rebudes”Dos nous events de webhook per a factures rebudes:
received_invoice.created— s'activa quan es crea una nova factura rebuda a la plataforma (p. ex. importada o pujada).received_invoice.state_change— s'activa quan una factura rebuda transiciona a un nou estat.
Subscriu-te a aquests events en configurar un webhook:
{ "web_hook": { "url": "https://example.com/hooks", "events": ["received_invoice.created", "received_invoice.state_change"] }}Payload per a received_invoice.created:
{ "invoice_id": 12345, "account_id": 42, "state": "received"}Payload per a received_invoice.state_change:
{ "invoice_id": 12345, "event_id": 67890, "state": "accepted", "notes": null}Crear oficines via POST /accounts amb parent_id
Section titled “Crear oficines via POST /accounts amb parent_id”POST /accounts ara accepta un camp opcional parent_id. Quan es proporciona, el compte es crea com a oficina (filial) sota el compte pare indicat.
Quan parent_id està establert:
- El pare ha de ser un compte de nivell superior dins del mateix grup (no pot ser ell mateix una oficina).
- Els camps obligatoris habituals (
name,postalcode,email,address,city,province,phone,tin_value) esdevenen opcionals. - El compte creat hereta la integració del grup i es retorna amb
parent_ida la resposta.
Retorna 422 Unprocessable Entity amb codi parameter_invalid (paràmetre parent_id) si:
- El compte pare no es troba o pertany a un grup diferent.
- El pare és ell mateix una oficina.
Exemple de petició:
POST /accounts{ "account": { "parent_id": 12345, "name": "Paris Establishment", "address": "1 Rue de la Paix", "city": "Paris", "postalcode": "75001", "province": "Ile-de-France", "email": "paris@example.com" }}Exemple de resposta:
{ "account": { "id": 67890, "parent_id": 12345, "name": "Paris Establishment", ... }}Notes:
tin_value/tin_schemeno es poden establir en una oficina — sempre s'hereten del compte pare. Enviar-los retorna422 parameter_cannot_change(paràmetretin_value).cin_value/cin_schemes'emmagatzemen de forma independent a l'oficina. Si no s'estableixen, l'oficina hereta el CIN del pare a les respostes de lectura.
parent_id a les respostes de contacte
Section titled “parent_id a les respostes de contacte”Totes les respostes d'un únic contacte ara inclouen parent_id: GET /contacts/{id}, POST /accounts/{account}/contacts, PUT /contacts/{id} i DELETE /contacts/{id}.
- Per als contactes de nivell superior,
parent_idésnull. - Per a les oficines,
parent_idconté l'ID del contacte pare.
refuse_reason_code de DGFiP a mark_as i a les respostes de factura
Section titled “refuse_reason_code de DGFiP a mark_as i a les respostes de factura”POST /invoices/{id}/mark_as ara accepta un paràmetre opcional reason_code en transicionar a l'estat refused. Aquest camp porta un codi de motiu estructurat definit per DGFiP per als rebutjos del procés 210.
Valors acceptats:
ADR_ERR, REF_CT_ABSENT, CMD_ERR, TX_TVA_ERR, MONTANTTOTAL_ERR, CALCUL_ERR, DOUBLON, NON_CONFORME, DEST_ERR, TRANSAC_INC, EMMET_INC, CONTRAT_TERM, DOUBLE_FACT, AUTRE
Exemple de petició:
POST /invoices/{id}/mark_as{ "state": "refused", "reason": "Incorrect total amount", "reason_code": "MONTANTTOTAL_ERR"}Exemple de resposta (extracte):
{ "invoice": { "id": 12345, "state": "refused", "refuse_reason": "Incorrect total amount", "refuse_reason_code": "MONTANTTOTAL_ERR", "..." }}issue_after_import en crear i importar factures
Section titled “issue_after_import en crear i importar factures”POST /accounts/{account}/invoices i POST /accounts/{account}/invoices/import ara accepten un indicador opcional issue_after_import. Quan és true i la factura passa les validacions:
- La factura transiciona a
state=issued(cantonada c1) de forma síncrona, dins de la mateixa petició. - Si el compte té activada una configuració d'informe fiscal
before_send(Verifactu, Ksef, Zatca) ambauto_generateactivat i la factura hi qualifica, l'informe fiscal es genera en línia i s'exposa viatax_report_idsa la resposta. Quanauto_generateestà desactivat, la factura s'emet igualment però no es crea cap informe — coherent amb el flux d'enviament, aquests informes es gestionen a través de l'API de Tax Reports. - Les autoritats que informen després de l'enviament (p. ex. SII, SDI) no s'activen en emetre; els seus informes es creen quan la factura s'envia o es marca com enviada.
- No s'encua cap job d'enviament en segon pla per a la factura; l'estat a nivell de transport (c2) roman intacte. Els informes fiscals que s'envien automàticament (p. ex. Ksef) segueixen encuant el seu propi job d'enviament.
Mentre la factura roman en state=issued és de només lectura: no es pot actualitzar, eliminar ni revertir a new fins que s'envia o es descarrega.
Si tant send_after_import com issue_after_import són true, send_after_import guanya — enviar ja emet la factura. S'ignora per a documents que no siguin factures.
L'endpoint d'importació massiva POST /accounts/{account}/invoices/imports accepta el mateix indicador issue_after_import (com a camp de formulari multipart). S'aplica per fitxer: cada factura importada que hi qualifica s'emet; un fitxer que no es pot emetre, o l'emissió del qual falla, es reporta en aquest element sense avortar el lot.
Exemple de petició:
POST /accounts/{account}/invoices{ "issue_after_import": true, "invoice": { "number": "F-2026-0001", "..." }}Base imposable i quota d'impost al llistat de factures
Section titled “Base imposable i quota d'impost al llistat de factures”GET /accounts/{account}/invoices ara retorna dos camps addicionals per factura:
taxable_base— el subtotal de la factura abans d'impostos (float, mateixa moneda quecurrency).tax_amount— l'import total d'impostos, calculat com la suma de tots els desglossaments d'impost (float).
Exemple de resposta (parcial):
{ "invoices": [ { "id": 12345, "number": "INV-2025-001", "total": 121.0, "taxable_base": 100.0, "tax_amount": 21.0, "currency": "EUR" } ]}Preferència unit_code_format del compte
Section titled “Preferència unit_code_format del compte”Els comptes ara exposen un camp unit_code_format que controla la llista de codis utilitzada per als codis d'unitat de les línies de factura en llegir i escriure factures a través de l'API.
internal(per defecte) — la pròpia llista de codis d'unitat enters de B2Brouter.unece_rec20— codis de la Recomanació 20 d'UN/ECE (p. ex.HUR,KGM,H87).
Llegeix'l a GET /accounts/{account} i estableix-lo a PUT /accounts/{account}:
{ "account": { "unit_code_format": "unece_rec20" }}Quan s'estableix a unece_rec20, el camp unit de la línia de factura canvia de tipus: en lloc de l'id enter per defecte, s'intercanvia com un codi UNECERec20 en cadena (p. ex. "HUR"). Es retorna així en les lectures de factura — GET /invoices/{id} i les respostes de create/update — i s'accepta com a codi en les escriptures (creació i importació de factures); els codis desconeguts recauen a other. Les integracions que interpreten unit com a enter han de gestionar la forma en cadena per a aquests comptes.
El valor per defecte internal manté l'id enter, de manera que les integracions existents no es veuen afectades tret que ho activin.
apply_taxes_per_line per factura
Section titled “apply_taxes_per_line per factura”Nou camp apply_taxes_per_line (booleà, nul·lable) a les factures, tant escrivible com retornat a la resposta. Sobreescriu, per factura, la configuració a nivell de compte del mateix nom que controla l'arrodoniment d'IVA:
true— els impostos es calculen per línia (cada línia s'arrodoneix i després se sumen).false— els impostos es calculen per factura (la base imposable se suma per tipus, i s'arrodoneix una sola vegada).- omès /
null— hereta la configuracióapply_taxes_per_linedel compte (el comportament anterior).
La sobreescriptura només s'honora per a comptes premium. Això permet alinear el mode d'arrodoniment amb administracions públiques que recalculen els totals i rebutgen discrepàncies, sense canviar el valor per defecte a nivell de compte. Consulta la guia de càlcul de factures per a exemples treballats.
Endpoints afectats:
GET /invoices/{id}— retorna l'apply_taxes_per_lineefectiu.POST /accounts/{account}/invoices— accepta i retornaapply_taxes_per_line.PATCH /invoices/{id}— accepta i retornaapply_taxes_per_line.
Modificat
Section titled “Modificat”CIN independent per a oficines de contacte
Section titled “CIN independent per a oficines de contacte”🚨 Breaking
POST /accounts/{account}/contacts i PUT /contacts/{id} ara emmagatzemen cin_value i cin_scheme de forma independent a les oficines. Anteriorment, el CIN sempre s'heretava del contacte pare.
Comportament:
- Si es proporcionen
cin_value/cin_scheme, s'emmagatzemen a l'oficina i es retornen a les respostes. - Si s'ometen (o s'esborren amb
cin_value: ""), l'oficina hereta elcin_valuedel contacte pare. tin_value/tin_schemecontinuen heretant-se del pare i no es poden establir de forma independent.- S'aplica la unicitat del CIN dins del compte: enviar un
cin_valueja assignat a un altre contacte del mateix compte retorna422 Unprocessable Entity.
Endpoints afectats:
POST /accounts/{account}/contacts—cin_value/cin_schemeara s'emmagatzemen quanparent_idestà establert.PUT /contacts/{id}—cin_value/cin_schemeara s'emmagatzemen a les oficines.
Exemple: Crear una oficina amb el seu propi CIN
POST /accounts/{account_id}/contacts{ "contact": { "parent_id": 12345, "name": "Branch Office", "cin_value": "1234567890", "cin_scheme": 88 }}Resposta:
{ "contact": { "id": 67890, "parent_id": 12345, "name": "Branch Office", "cin_value": "1234567890", "cin_scheme": "88", "..." }}Validació més estricta de contactes en crear factures
Section titled “Validació més estricta de contactes en crear factures”🚨 Breaking
Quan es proporciona un objecte contact en crear una factura, l'API el compara amb els contactes existents per tin_value o cin_value:
- Si totes les dades coincideixen amb un contacte existent, la factura es crea i s'enllaça amb ell.
- Si els identificadors d'encaminament difereixen (
cin_value,cin_scheme,routing_codes,pin_value,recipient_code), es crea una oficina automàticament. - Si només difereixen camps descriptius (
address,city,postalcode, etc.), la petició retorna422 Unprocessable Entityamb codidata_mismatch. Passaupdate_contact: true(camp de la petició a nivell superior, per defectefalse) per fusionar les dades descriptives amb el contacte coincident en lloc d'això — els identificadors d'encaminament i fiscals mai es sobreescriuen d'aquesta manera. - Si no es troba cap contacte coincident, es crea un contacte nou. Quan coincideix amb una empresa publicada al directori de B2Brouter, s'enllaça amb ella: si les dades descriptives de la factura coincideixen amb una de les oficines registrades d'aquesta empresa, el contacte s'enllaça amb aquesta oficina; si en difereix, el contacte manté les dades de la factura (enllaçat al directori però no verificat contra ell).
update_contacts'ignora per als documents rebuts: una factura entrant mai reescriu les dades d'un contacte existent.
Nota: l'endpoint de contactes és la manera recomanada de crear i mantenir contactes i les seves oficines. Per enllaçar una factura amb un contacte existent sense cap lògica de coincidència, utilitza
contact_iddirectament.
Consulta a l'Annuaire francès a /directory/fr
Section titled “Consulta a l'Annuaire francès a /directory/fr”🚨 Breaking
GET /directory/fr/{scheme}/{id} ara consulta l'Annuaire francès de la PPF (API REST de la DGFiP) quan l'identificador és un SIREN (9 dígits, esquema 0002), un SIRET (14 dígits, esquema 0009), o una adreça electrònica FRCTC (esquema 0225, format SIREN, SIREN_SIRET, SIREN_SIRET_CodeRoutage o SIREN_Suffix).
L'identificador ha de ser vàlid per al seu esquema — la longitud i el checksum es validen per a cada esquema, no només els francesos. Un identificador que el validador de l'esquema rebutja retorna 422 Unprocessable Entity amb codi invalid_identifier (això inclou un SIREN/SIRET de longitud incorrecta, un checksum fallit, o una adreça FRCTC amb un SIREN/SIRET no vàlid). Els esquemes sense validador s'accepten i es consulten com abans.
Per a l'esquema 0225 el valor s'utilitza tal qual com a identificador d'adreçament de l'Annuaire, i l'empresa resolta es clau per el seu identificador legal subjacent: un SIREN sol resol a cin_scheme 0002, un SIREN_SIRET a 0009 (SIRET), amb l'adreça FRCTC completa mantinguda com a pin_scheme 0225; un code routage s'exposa com a codi d'encaminament cin1 (esquema 0224). Això significa que una consulta 0225 i una posterior consulta 0009/0002 de la mateixa empresa retornen la mateixa entrada de directori.
La consulta és asíncrona per mantenir els temps de resposta en mil·lisegons:
- Si l'empresa ja és coneguda al directori de B2Brouter, la resposta és
200 OKamb les dades de l'empresa. - Si encara no és coneguda, la resposta és
202 Acceptedamb unpolling_url. Un job en segon pla consulta l'Annuaire i persisteix el resultat. Reintenta la petició al cap d'uns segons — un cop les dades estiguin disponibles, la petició retorna200 OK. - Quan una entrada de directori coneguda no s'ha comprovat en les últimes 24 hores (o mai s'ha enriquit des de l'Annuaire), la resposta continua sent
200 OKimmediatament i s'activa una actualització en segon pla (stale-while-revalidate). - Després d'un
404 Not Founden un SIREN/SIRET, les peticions posteriors per al mateix identificador retornen404durant 15 minuts sense tornar a consultar l'Annuaire. Reintenta després d'aquest període si creus que l'identificador s'ha registrat des de llavors. - Si la consulta falla perquè un servei upstream (Annuaire, Peppol) no està disponible, la resposta és
424 Failed Dependencyamb codi d'errorupstream_unavailablei una capçaleraRetry-After— reintenta després del retard indicat. Una fallada upstream transitòria mai es converteix en un404.
La resposta inclou un nou camp information_flags (array de cadenes) que porta l'estat de registre a l'Annuaire, alineat amb l'especificació CTC de Peppol:
| Indicador | Significat |
|---|---|
FR_ASSUJETTI_ACTIVE | L'identificador és present i actiu a l'Annuaire |
FR_ASSUJETTI_INACTIVE | L'identificador és present a l'Annuaire però inactiu |
FR_ASSUJETTI_UNKNOWN | L'empresa és coneguda per B2Brouter però absent de l'Annuaire |
S'estableix exactament un d'aquests indicadors per empresa. Quan una empresa ja coneguda per B2Brouter (p. ex. via Peppol) està absent de l'Annuaire, es retorna amb FR_ASSUJETTI_UNKNOWN perquè l'absència sigui visible. Un identificador desconegut per B2Brouter i absent de l'Annuaire resol a 404 Not Found (vegeu la nota de caché de negació anterior).
Les unitats subordinades (oficines SIRET sota un SIREN) encara no s'exposen a la resposta.
Exemple: empresa encara no coneguda — primera petició
curl --request GET \ --url 'https://app-staging.b2brouter.net/api/v1/directory/fr/0002/123456789' \ --header 'X-B2B-API-Key: {YOUR_API_KEY}' \ --header 'X-B2B-API-Version: 2026-06-26'{ "status": "processing", "message": "Querying French PPF Annuaire. Please retry this request.", "polling_url": "https://app-staging.b2brouter.net/api/v1/directory/fr/0002/123456789"}Estat HTTP: 202 Accepted.
Exemple: la mateixa petició uns segons després
{ "name": "SIREN 123456789", "country": "fr", "information_flags": ["FR_ASSUJETTI_ACTIVE"], ...}Estat HTTP: 200 OK.
Endpoints afectats:
GET /directory/fr/{scheme}/{id}— comportament ampliat descrit anteriorment. Els països no francesos no es veuen afectats.
routing_codes del contacte en línia en crear factures
Section titled “routing_codes del contacte en línia en crear factures”🚨 Breaking
El contact en línia a POST /accounts/{account}/invoices ara accepta un objecte routing_codes — la mateixa forma utilitzada per POST /accounts/{account}/contacts i retornada a les respostes de contacte. Porta fins a cinc Números d'Identificació d'Empresa addicionals (cin1_value/cin1_scheme … cin5_value/cin5_scheme) a més del cin principal. Si es proporciona cinN_value, cinN_scheme és obligatori (i viceversa). Aquests codis d'encaminament també es retornen dins de routing_codes a l'objecte invoice.contact incrustat a la resposta.
POST /accounts/{account_id}/invoices{ "invoice": { "contact": { "tin_value": "ESA13585625", "name": "Buyer Full Name AS", "routing_codes": { "cin1_value": "ESR_MISSION_FACTURES_DEPLACEMENTS", "cin1_scheme": "8017" } } }}Canvi incompatible: les claus planes cinN_value / cinN_scheme dins de contact ja no s'accepten. Aquestes peticions retornen 422 Unprocessable Entity. Envia els codis d'encaminament del contacte a través de contact.routing_codes en el seu lloc.
routing_codes a nivell de factura en crear factures
Section titled “routing_codes a nivell de factura en crear factures”🚨 Breaking
POST /accounts/{account}/invoices i PUT /invoices/{id} ara accepten un objecte routing_codes a nivell superior de la factura — la mateixa forma cin1_value/cin1_scheme … cin5_value/cin5_scheme utilitzada per contact.routing_codes. Porta els codis d'encaminament propis de la factura (p. ex. els codis de servei DIR3 / Chorus Pro del comprador), independents dels del contacte.
Els codis aplicats es retornen en un objecte routing_codes al nivell superior de la factura de la resposta, de manera que un integrador pot verificar què s'ha emmagatzemat.
POST /accounts/{account_id}/invoices{ "invoice": { "number": "F-2026-0001", "routing_codes": { "cin1_value": "ESR_MISSION_FACTURES_DEPLACEMENTS", "cin1_scheme": "8017" } }}Els camps d'encaminament dedicats que versions anteriors acceptaven al nivell superior de la factura ja no s'accepten. Estableix la ranura routing_codes equivalent en el seu lloc, segons l'esquema:
| Ranura | DIR3 (esquema 8014) | DIRe (8015) | EDI/GLN (88) |
|---|---|---|---|
| cin1 | accounting_unit | — | nadby |
| cin2 | managing_unit | — | naddp |
| cin3 | processing_unit | — | nadiv |
| cin4 | proponent_unit | — | nadpr |
| cin5 | — | dire | nadud |
Canvi incompatible: al nivell superior de la factura, tant les claus planes cinN_value / cinN_scheme com els camps d'encaminament dedicats (dire, accounting_unit, managing_unit, processing_unit, proponent_unit, nadby, naddp, nadiv, nadpr, nadud) ja no s'accepten, tant a POST /accounts/{account}/invoices com a PUT /invoices/{id}. Aquestes peticions retornen 422 Unprocessable Entity. Envia els codis d'encaminament de la factura a través de l'objecte routing_codes de la factura en el seu lloc. Versions anteriors de l'API encara accepten aquests camps.
Filtres del llistat de factures
Section titled “Filtres del llistat de factures”Canvis de filtratge a GET /accounts/{account}/invoices:
number ara fa coincidència per prefix
El paràmetre de consulta number ara fa una coincidència de prefix en lloc d'una coincidència exacta. Es retornen les factures el número de les quals comença per el valor proporcionat.
GET /accounts/{account}/invoices?number=INV-2retorna INV-20, INV-21, … a més d'una factura numerada exactament INV-2.
En versions anteriors, el filtre
numberrequeria el número de factura complet i retornava només una coincidència exacta.
series_code
El paràmetre de consulta series_code filtra factures per codi de sèrie mitjançant coincidència exacta.
Generar informe fiscal retorna 201 Created
Section titled “Generar informe fiscal retorna 201 Created”🚨 Breaking
POST /invoices/{id}/generate_tax_report ara retorna 201 Created en cas d'èxit en lloc de 200 OK. El cos de la resposta no canvia.
Abans (≤ 2026-04-20): 200 OK
Després (≥ 2026-06-26): 201 Created
Aquest és un canvi incompatible menor per als clients que comproven un estat exacte de
200. Els clients que comproven qualsevol èxit2xxno es veuen afectats.