Guía de migración v2026-04-20 → v2026-06-26
Todo lo que necesitas para actualizar tu código.
Esta guía te ayuda a actualizar de X-B2B-API-Version: 2026-04-20 a X-B2B-API-Version: 2026-06-26, centrándose en qué debes cambiar, no solo en qué ha cambiado.
Resumen
Sección titulada «Resumen»| Qué ha cambiado | ¿Necesitas actuar? |
|---|---|
Las oficinas ahora almacenan su propio cin_value / cin_scheme en lugar de heredarlo | Sí — solo si tu integración crea o lee oficinas (contactos con parent_id) |
Coincidencia más estricta de contactos al crear facturas con un contact en línea | Sí — afecta integraciones que pasan datos de contact en línea al crear facturas |
La consulta al Annuaire francés en /directory/fr ahora puede retornar 202 Accepted | Sí — solo si llamas a /directory/fr para identificadores franceses |
Las claves planas cinN_value / cinN_scheme ya no se aceptan en el contact de la factura | Sí — muévelas a contact.routing_codes |
Los campos de enrutamiento dedicados (dire, accounting_unit, etc.) ya no se aceptan en el nivel superior de la factura | Sí — muévelos al objeto routing_codes a nivel de factura |
POST /invoices/{id}/generate_tax_report ahora retorna 201 Created | Sí — solo si compruebas un estado exacto de 200 |
El filtro number del listado de facturas ahora coincide por prefijo en lugar de coincidencia exacta | Solo si tu integración depende del comportamiento de coincidencia exacta |
| Nuevos eventos de webhook para facturas recibidas | No — opt-in |
Crear oficinas via POST /accounts con parent_id | No — opt-in |
issue_after_import al crear e importar facturas | No — opt-in |
Preferencia unit_code_format de la cuenta | No — opt-in |
apply_taxes_per_line por factura | No — opt-in |
Nuevos campos taxable_base / tax_amount en el listado de facturas | No — aditivo |
refuse_reason_code de DGFiP en mark_as y en las respuestas de factura | No — opt-in |
Cambios que requieren acción
Sección titulada «Cambios que requieren acción»1. Las oficinas ahora almacenan su propio CIN en lugar de heredarlo
Sección titulada «1. Las oficinas ahora almacenan su propio CIN en lugar de heredarlo»Anteriormente, una oficina (un contacto creado con parent_id) siempre heredaba cin_value / cin_scheme de su contacto padre. Ahora estos campos se almacenan de forma independiente por oficina.
- Si envías
cin_value/cin_schemeal crear o actualizar una oficina, se almacenan en la oficina y se retornan en las respuestas. - Si los omites (o los borras con
cin_value: ""), la oficina sigue heredando el CIN del padre en las respuestas de lectura — no es necesario actuar si nunca has establecido el CIN en las oficinas. tin_value/tin_schemeno se ven afectados — siguen heredándose siempre del padre y no se pueden establecer de forma independiente.- Ahora se aplica la unicidad del CIN dentro de la cuenta: reutilizar un
cin_valueya asignado a otro contacto de la misma cuenta retorna422 Unprocessable Entity.
POST /accounts/{account_id}/contacts{ "contact": { "parent_id": 12345, "name": "Branch Office", "cin_value": "1234567890", "cin_scheme": 88 }}// Respuesta — cin_value se ignora, se hereda del contacto padre{ "contact": { "id": 67890, "parent_id": 12345, "name": "Branch Office", "cin_value": "<cin_value del padre>", "cin_scheme": "<cin_scheme del padre>" }}POST /accounts/{account_id}/contacts{ "contact": { "parent_id": 12345, "name": "Branch Office", "cin_value": "1234567890", "cin_scheme": 88 }}// Respuesta — cin_value ahora se almacena en la propia oficina{ "contact": { "id": 67890, "parent_id": 12345, "name": "Branch Office", "cin_value": "1234567890", "cin_scheme": "88" }}Endpoints afectados: POST /accounts/{account}/contacts, PUT /contacts/{id}
2. Validación más estricta de contactos al crear facturas con un contact en línea
Sección titulada «2. Validación más estricta de contactos al crear facturas con un contact en línea»Cuando pasas un hash contact en línea al crear una factura, la API ahora lo compara con los contactos existentes por tin_value o cin_value antes de decidir qué hacer:
- Coincidencia completa → la factura se enlaza con el contacto existente.
- Los identificadores de enrutamiento difieren (
cin_value,cin_scheme,routing_codes,pin_value,recipient_code) → se crea una oficina automáticamente. - Solo difieren campos descriptivos (
address,city,postalcode, etc.) → la petición ahora retorna422 Unprocessable Entitycon códigodata_mismatchen lugar de actualizar el contacto silenciosamente. - Ninguna coincidencia → se crea un contacto nuevo (y se enlaza al directorio de B2Brouter si coincide con una empresa conocida).
Si tu integración depende del comportamiento anterior de sobrescribir silenciosamente los datos descriptivos del contacto al crear facturas, pasa update_contact: true (campo de la petición a nivel superior, por defecto false) para volver a activarlo. Los identificadores de enrutamiento y fiscales nunca se sobrescriben de esta manera, y update_contact no tiene ningún efecto en documentos recibidos.
// Activar la actualización de datos descriptivos del contacto desde la creación de facturaPOST /accounts/{account_id}/invoices{ "update_contact": true, "invoice": { "contact": { "tin_value": "B12345678", "name": "Acme Corp", "address": "New address 123" } }}El endpoint de contactos es la forma recomendada de crear y mantener contactos y sus oficinas. Para enlazar una factura con un contacto existente sin ninguna lógica de coincidencia, usa
contact_iddirectamente.
Endpoints afectados: POST /accounts/{account}/invoices
3. La consulta al Annuaire francés en /directory/fr ahora es asíncrona
Sección titulada «3. La consulta al Annuaire francés en /directory/fr ahora es asíncrona»GET /directory/fr/{scheme}/{id} ahora consulta el Annuaire francés de la PPF para identificadores SIREN, SIRET y FRCTC (0225). Si tu integración llama a este endpoint para identificadores franceses, gestiona las nuevas formas de respuesta:
202 Acceptedcon unpolling_url— la empresa aún no era conocida; un job en segundo plano está consultando el Annuaire. Reintenta al cabo de unos segundos.424 Failed Dependencycon código de errorupstream_unavailabley una cabeceraRetry-After— el Annuaire o Peppol no están disponibles temporalmente. Reintenta después del retraso indicado; no lo trates como un404.422 Unprocessable Entitycon códigoinvalid_identifier— el identificador ha fallado la validación de longitud/checksum para su esquema.- Se incluye un nuevo array
information_flagsen las respuestas exitosas (FR_ASSUJETTI_ACTIVE,FR_ASSUJETTI_INACTIVE,FR_ASSUJETTI_UNKNOWN).
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'// 202 Accepted — aún no conocida, reintenta en polling_url{ "status": "processing", "message": "Querying French PPF Annuaire. Please retry this request.", "polling_url": "https://app-staging.b2brouter.net/api/v1/directory/fr/0002/123456789"}Endpoints afectados: GET /directory/fr/{scheme}/{id} (los países no franceses no se ven afectados)
4. Las claves planas cinN_value / cinN_scheme ya no se aceptan en el contact de la factura
Sección titulada «4. Las claves planas cinN_value / cinN_scheme ya no se aceptan en el contact de la factura»El objeto contact en línea en POST /accounts/{account}/invoices ya no acepta las claves planas cin1_value/cin1_scheme … cin5_value/cin5_scheme. Muévelas a un objeto contact.routing_codes — la misma forma utilizada por POST /accounts/{account}/contacts.
{ "invoice": { "contact": { "tin_value": "ESA13585625", "name": "Buyer Full Name AS", "cin1_value": "ESR_MISSION_FACTURES_DEPLACEMENTS", "cin1_scheme": "8017" } }}{ "invoice": { "contact": { "tin_value": "ESA13585625", "name": "Buyer Full Name AS", "routing_codes": { "cin1_value": "ESR_MISSION_FACTURES_DEPLACEMENTS", "cin1_scheme": "8017" } } }}Las peticiones que todavía usan las claves planas retornan 422 Unprocessable Entity.
Endpoints afectados: POST /accounts/{account}/invoices
5. Los campos de enrutamiento a nivel de factura se sustituyen por un objeto routing_codes
Sección titulada «5. Los campos de enrutamiento a nivel de factura se sustituyen por un objeto routing_codes»En el nivel superior de la factura, tanto las claves planas cinN_value / cinN_scheme como los campos de enrutamiento dedicados (dire, accounting_unit, managing_unit, processing_unit, proponent_unit, nadby, naddp, nadiv, nadpr, nadud) ya no se aceptan. Usa en su lugar el objeto routing_codes a nivel de factura — lleva los códigos de enrutamiento propios de la factura (p. ej. los códigos de servicio DIR3 / Chorus Pro del comprador), independientes de los del contacto.
| 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 |
{ "invoice": { "number": "F-2026-0001", "accounting_unit": "ESR_MISSION_FACTURES_DEPLACEMENTS" }}{ "invoice": { "number": "F-2026-0001", "routing_codes": { "cin1_value": "ESR_MISSION_FACTURES_DEPLACEMENTS", "cin1_scheme": "8014" } }}Los códigos aplicados se retornan en un objeto routing_codes en el nivel superior de la factura de la respuesta. Las peticiones que todavía usan los campos antiguos retornan 422 Unprocessable Entity.
Endpoints afectados: POST /accounts/{account}/invoices, PUT /invoices/{id}
6. generate_tax_report ahora retorna 201 Created
Sección titulada «6. generate_tax_report ahora retorna 201 Created»POST /invoices/{id}/generate_tax_report ahora retorna 201 Created en caso de éxito en lugar de 200 OK. El cuerpo de la respuesta no cambia. Esto solo afecta a los clientes que comprueban un estado exacto de 200 — los clientes que comprueban cualquier éxito 2xx no se ven afectados.
Endpoints afectados: POST /invoices/{id}/generate_tax_report
7. El filtro number del listado de facturas ahora coincide por prefijo
Sección titulada «7. El filtro number del listado de facturas ahora coincide por prefijo»GET /accounts/{account}/invoices?number=... ahora realiza una coincidencia de prefijo en lugar de una coincidencia exacta. Si tu integración depende del comportamiento anterior de coincidencia exacta, añade una comprobación en el lado cliente para filtrar coincidencias de prefijo no deseadas, o cambia a un valor más específico.
GET /accounts/{account}/invoices?number=INV-2ahora también retorna INV-20, INV-21, … además de una factura numerada exactamente INV-2. Hay disponible un nuevo filtro series_code para filtrado de coincidencia exacta por serie.
Endpoints afectados: GET /accounts/{account}/invoices
Nuevos campos en respuestas existentes
Sección titulada «Nuevos campos en respuestas existentes»Se han añadido los siguientes campos. Son compatibles con versiones anteriores — tu integración seguirá funcionando sin cambios. Sin embargo, si tu código falla cuando encuentra campos JSON inesperados, actualiza tus modelos de respuesta para permitirlos.
Respuestas de contacto (GET /contacts/{id}, POST, PUT, DELETE):
parent_id—nullpara los contactos de nivel superior, el ID del contacto padre para las oficinas
Listado de facturas (GET /accounts/{account}/invoices):
taxable_base— subtotal de la factura antes de impuestostax_amount— importe total de impuestos de todos los desgloses de impuesto
Respuestas de factura (mark_as, crear, actualizar):
refuse_reason_code— código de motivo estructurado definido por DGFiP para los rechazos del proceso 210 (se acepta enPOST /invoices/{id}/mark_asjunto areason)
Respuestas de cuenta (GET /accounts/{account}, GET /accounts):
unit_code_format—internal(por defecto) ounece_rec20; consulta la funcionalidad opt-in a continuación para el efecto sobreuniten las líneas de factura
Nuevas funcionalidades disponibles en esta versión
Sección titulada «Nuevas funcionalidades disponibles en esta versión»Webhooks de facturas recibidas — suscríbete a received_invoice.created y received_invoice.state_change para recibir notificaciones cuando se crean facturas recibidas o cambian de estado.
Oficinas via POST /accounts — crea una oficina (filial) directamente bajo una cuenta padre pasando parent_id; los campos obligatorios habituales pasan a ser opcionales y la oficina hereda la integración del grupo.
issue_after_import — pasa este indicador al crear o importar facturas para transicionar de forma síncrona la factura a state=issued dentro de la misma petición, en lugar de depender del flujo de envío.
Preferencia de cuenta unit_code_format — establécela a unece_rec20 para intercambiar el campo unit de la línea de factura como un código en cadena de la Recomendación 20 de UN/ECE (p. ej. "HUR") en lugar del id entero interno de B2Brouter. El valor por defecto internal no afecta a las integraciones existentes.
apply_taxes_per_line por factura (cuentas premium) — sobrescribe el modo de redondeo de IVA a nivel de cuenta para una sola factura, útil cuando una administración pública recalcula los totales con una regla de redondeo diferente. Consulta la guía de cálculo de facturas.
Lista de comprobación de migración
Sección titulada «Lista de comprobación de migración»Usa esta lista antes de cambiar a v2026-06-26 en producción.
Contactos y oficinas:
- Si estableces
cin_value/cin_schemeal crear o actualizar oficinas, verifica que el valor es único dentro de la cuenta (los duplicados ahora retornan422) - Actualiza el código que lee
parent_iden las respuestas de contacto si necesitas distinguir oficinas de contactos de nivel superior
Creación de facturas con contacto en línea:
- Mueve cualquier clave
cinN_value/cinN_schemedentro deinvoice.contactainvoice.contact.routing_codes - Mueve cualquier
cinN_value/cinN_schemeo campo dedicado (dire,accounting_unit, etc.) en el nivel superior de la factura al objetorouting_codesa nivel de factura - Decide si necesitas
update_contact: truepara preservar el comportamiento anterior de sobrescritura de datos descriptivos - Prueba: crea una factura con un contacto en línea cuyos datos descriptivos difieran de un contacto existente, y confirma que gestionas la respuesta
422 data_mismatch(o pasaupdate_contact: true)
Informes fiscales:
- Actualiza cualquier comprobación de estado en
POST /invoices/{id}/generate_tax_reportque espere exactamente200 OK
Filtrado del listado de facturas:
- Revisa cualquier uso del filtro
numberque dependa del comportamiento de coincidencia exacta; cambia aseries_codesi necesitas coincidencia exacta por serie
Consultas al directorio francés:
- Gestiona
202 Acceptedconpolling_urly reintenta - Gestiona
424 Failed DependencyconRetry-Aftercomo error transitorio, no como un404 - Gestiona
422 Unprocessable Entitycon códigoinvalid_identifier
Probando tu integración
Sección titulada «Probando tu integración»Cambia a la nueva cabecera de versión en tu entorno de sandbox o staging primero:
X-B2B-API-Version: 2026-06-26Puedes establecer esta cabecera por petición, de modo que puedes probar contra sandbox (o staging) sin tocar tu configuración de producción. Una vez hayas validado la lista de comprobación anterior, actualiza la versión en la configuración de tu clave de API de producción o en las cabeceras de petición.