Factuarea APIDevelopers

Biblioteca de plantillas PDF

Gestiona las plantillas PDF, las identidades de marca y los valores por defecto de tu empresa — revisiones, impacto, valores por defecto por contacto, subida de activos, precedencia, concurrencia con ETag e idempotencia.

La biblioteca de plantillas PDF es donde tu empresa guarda los diseños y las marcas que dan forma al PDF de cada documento que genera la API. Creas una plantilla (maquetación, preajuste, columnas, textos), le asignas una identidad comercial (logotipo y marca) y decides dónde se aplica: como valor por defecto de la empresa, por tipo de documento, por serie o por contacto.

Todo lo que hay en la biblioteca está versionado. Una plantilla o una identidad es una cabecera (nombre, estado, version) que apunta a su revisión actual; una revisión es una instantánea inmutable del diseño o de la marca. Publicar nunca edita una revisión: añade la siguiente. Un documento conserva el PDF con el que se capturó: cambiar, archivar o restaurar recursos de la biblioteca solo afecta a los documentos que crees o revises después.

RecursoQué esRuta
PlantillaDiseño del PDF: preajuste base, columnas, títulos, secciones, página./v1/companies/{company}/pdf-templates
Revisión de plantillaInstantánea inmutable de una plantilla, numerada desde 1./v1/companies/{company}/pdf-templates/{template}/revisions/{revision}
Identidad comercialMarca: nombre comercial, logotipo, imagen de marca, modo de marca, correo y teléfono./v1/companies/{company}/pdf-commercial-identities
ActivoLogotipo o imagen de marca que subes; privado e inmutable./v1/companies/{company}/pdf-templates/assets
Valores por defecto de la empresaPlantilla e identidad que se usan cuando no hay nada más específico./v1/companies/{company}/pdf-templates/defaults
Valores por defecto por contactoPlantilla preferida por un contacto para un tipo de documento y un propósito./v1/companies/{company}/pdf-templates/contact-defaults/{contact}/{document_type}/{purpose}

Todas las rutas de esta guía cuelgan de /v1/companies/{company}/…: {company} es el id (UUID v7) del NIF con el que operas, y en los ejemplos curl es $COMPANY_ID. Alcanzar un NIF explica cómo resolverlo.

Una identidad comercial nunca sustituye a la identidad fiscal del emisor. La razón social, el NIF, los datos de impuestos y las cuentas bancarias salen de tu empresa y de cada documento; la biblioteca solo guarda su aspecto. Una plantilla o una identidad que intente llevar datos fiscales o bancarios, HTML, CSS, scripts o URLs se rechaza con 422.

Los recursos de la biblioteca se devuelven como objeto plano (sin envoltorio data) y los listados como { "items": [...], "meta": { "page", "per_page", "total" } }. Todos los identificadores son UUID v7 y se exponen como id.

Acceso: módulo, plan, scopes y roles

OperaciónScope
Leer plantillas, identidades, revisiones, activos, impacto y valores por defectopdf_templates:read
Crear, renombrar, publicar, duplicar, archivar, restaurar, subir y cambiar valores por defectopdf_templates:write
Previsualizar una plantilla (véase Vistas previas y artefactos PDF)pdfs:read y pdf_templates:read
  • Roles. Las lecturas están abiertas a los roles admin y user de la empresa; las escrituras y la lectura del impacto exigen admin. Un employee recibe 403 pdf_template_access_denied. Una API key actúa con el rol del usuario al que pertenece, y el rol y las restricciones de módulo se comprueban de nuevo en cada petición.
  • Módulo y plan. La biblioteca es el módulo pdf_templates, disponible en Esencial, Profesional, Avanzado y Enterprise. El editor avanzado (tipografía, colores, columnas, maquetación de página y los preajustes corporative y premium) es el módulo pdf_templates_editor, incluido desde Profesional. Sin él puedes seguir gestionando plantillas que solo cambian la marca sobre los preajustes classic, modern y minimal; cualquier otro cambio devuelve 403 feature_not_available_in_plan. Lee pdf_capabilities en personalización de la cuenta para saberlo de antemano. Un downgrade conserva lo que ya guardaste; solo los cambios avanzados nuevos necesitan el editor.
  • Modo de prueba. La biblioteca funciona igual con claves fact_test_ y fact_live_.

Plantillas

Crear una plantilla

POST /v1/companies/{company}/pdf-templates crea una plantilla con su primera revisión. Solo name es obligatorio; el resto tiene valores por defecto.

CampoSignificado
nameDe 1 a 120 caracteres.
descriptionOpcional, hasta 500 caracteres.
base_presetclassic, modern (por defecto), minimal, corporative o premium.
supported_typesTipos de documento que puede generar: invoice, quote, proforma, delivery-note. Por defecto, los cuatro.
supported_purposesPropósitos por tipo. Facturas: complete, simplified, corrective, simplified_corrective; los demás tipos solo complete. Por defecto, todos.
supported_formatsa4 (por defecto), ticket_80, ticket_58. Los formatos de ticket solo valen para plantillas exclusivas de factura.
commercial_identity_idMarca que usa por defecto, o null para heredar la identidad por defecto de la empresa.
configurationDiseño parcial, combinado sobre los valores del preajuste (véase abajo).
id, revision_idUUID v7 opcionales si quieres elegir tú los identificadores.

configuration es un objeto cerrado con los grupos branding (mode: logo, imago o none; size: small, medium, large o inherit, consulta el tamaño de la marca), typography, colors, page, watermark, titles, columns, company_fields, client_fields, custom_field_definitions y sections. Una clave desconocida, un tipo incorrecto o un valor fuera de rango se rechaza con 422 invalid_pdf_template_configuration y el param señala la ruta exacta, por ejemplo configuration.typography.font_size. Cuando branding.mode es logo o imago, la plantilla necesita una marca efectiva: su propio commercial_identity_id o una identidad por defecto de la empresa que esté activa. Sin ella, la petición devuelve 422 pdf_commercial_identity_required.

curl -X POST https://api.factuarea.com/v1/companies/$COMPANY_ID/pdf-templates \
  -H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Invoices with logo",
    "base_preset": "modern",
    "supported_types": ["invoice"],
    "commercial_identity_id": "0199f39e-1a20-7f6b-a2c8-3d5e9b0c4a71",
    "configuration": { "branding": { "mode": "logo", "size": "medium" } }
  }'

La respuesta es 201 con la plantilla y una cabecera ETag (abreviada aquí):

{
  "id": "0199f3a2-7c4e-7b1a-9d3e-5a2c8f1b6e40",
  "name": "Invoices with logo",
  "description": null,
  "state": "active",
  "version": 1,
  "availability": { "selectable": true, "reason": null },
  "supported_types": ["invoice"],
  "supported_purposes": { "invoice": ["complete", "simplified", "corrective", "simplified_corrective"] },
  "supported_formats": ["a4"],
  "commercial_identity_id": "0199f39e-1a20-7f6b-a2c8-3d5e9b0c4a71",
  "current_revision": {
    "id": "0199f3a2-7c52-7d03-8a41-6b9e0c2d7f15",
    "template_id": "0199f3a2-7c4e-7b1a-9d3e-5a2c8f1b6e40",
    "number": 1,
    "base_preset": "modern",
    "layout_version": "1",
    "schema_version": 1,
    "configuration": { "...": "complete normalized configuration" }
  },
  "created_at": "2026-10-14T09:12:41.000000Z",
  "updated_at": "2026-10-14T09:12:41.000000Z"
}

Listar y leer

  • GET /v1/companies/{company}/pdf-templates acepta q (búsqueda por nombre), state (active por defecto, archived o all), document_type, purpose, format, page y per_page (de 1 a 100, por defecto 25). Los resultados salen ordenados por nombre. Un filtro no válido devuelve 422 con el filtro en param; nunca se ignora en silencio.
  • GET /v1/companies/{company}/pdf-templates/{template} devuelve la plantilla con su revisión actual y el ETag que necesitas para el siguiente PATCH.
  • GET /v1/companies/{company}/pdf-templates/{template}/revisions/{revision} devuelve una revisión exacta, también las archivadas.

Renombrar: solo metadatos

PATCH /v1/companies/{company}/pdf-templates/{template} cambia únicamente name y description (description: null la borra). Nunca toca el diseño: enviar configuration aquí es un 422. Una petición que no cambia nada no crea versión nueva. La precondición es obligatoria, véase concurrencia.

curl -X PATCH https://api.factuarea.com/v1/companies/$COMPANY_ID/pdf-templates/0199f3a2-7c4e-7b1a-9d3e-5a2c8f1b6e40 \
  -H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "00295d3c3bb1b0b0ce5187e46fc6af39f41f507558608c8d14312fba4a710dc6"' \
  -d '{ "name": "Invoices with logo (2026)" }'

Publicar una revisión

Cambiar el diseño significa publicar una revisión nueva, en dos pasos.

  1. Pide el impacto: GET /v1/companies/{company}/pdf-templates/{template}/impact?action=publish. La respuesta enumera las asociaciones que apuntan a la plantilla (company_default, type_default, contact_default, series y recurring), los retained_counts de presentaciones, salidas preparadas y anclajes que quedan intactos, los warnings si los hay, y un impact_fingerprint.
  2. Publica con POST /v1/companies/{company}/pdf-templates/{template}/revisions, enviando el expected_version de la plantilla, ese expected_impact_fingerprint y al menos un cambio entre base_preset, commercial_identity_id, supported_types, supported_purposes, supported_formats y configuration.

Los objetos de configuration se combinan en profundidad sobre la revisión actual; las listas como columns o custom_field_definitions se sustituyen por completo. La respuesta es 201 con la revisión nueva, y la version de la plantilla sube una unidad. Si las asociaciones cambiaron entre las dos llamadas, la huella ya no coincide y recibes 409 pdf_library_impact_conflict: vuelve a leer el impacto y decide.

curl -X POST https://api.factuarea.com/v1/companies/$COMPANY_ID/pdf-templates/0199f3a2-7c4e-7b1a-9d3e-5a2c8f1b6e40/revisions \
  -H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "expected_version": 2,
    "expected_impact_fingerprint": "b8a9f15005a46cf651f5652419b2edba941b3090090a1934a96f37c9cd0b973f",
    "configuration": { "page": { "show_page_numbers": true }, "sections": { "footer_text": "Thank you for your business" } }
  }'

Los documentos nuevos se resuelven con la revisión nueva. Los documentos ya capturados, las salidas preparadas y los anclajes de las facturas recurrentes conservan la revisión que tenían.

Duplicar

POST /v1/companies/{company}/pdf-templates/{template}/duplicate con name y el expected_version de la origen crea una plantilla nueva (version 1, revisión 1, active) con la configuración actual de la origen. La origen puede estar archivada; la copia siempre nace activa. La copia no hereda valores por defecto, asignaciones de series ni preferencias de contacto, y necesita la marca que la origen necesitaría hoy (las capacidades del plan se comprueban en el momento de copiar).

Archivar y restaurar

Una plantilla archivada sigue siendo legible y conserva sus revisiones y activos, pero ya no se puede seleccionar (availability.selectable es false).

  1. GET /v1/companies/{company}/pdf-templates/{template}/impact?action=archive devuelve las asociaciones que dependen de ella y una huella.

  2. POST /v1/companies/{company}/pdf-templates/{template}/archive con expected_version, expected_impact_fingerprint y replacements, una lista (puede ir vacía) con una decisión por cada asociación cuya action sea replace_or_clear o pause:

    DecisiónCampos
    Sustituir por otra plantilla{ "key", "expected_version", "action": "replace", "replacement_id" }
    Quitar el vínculo{ "key", "expected_version", "action": "clear", "replacement_id": null }
    Pausar (facturas recurrentes que siguen la última plantilla){ "key", "expected_version", "action": "pause", "replacement_id": null }

    Copia key y version de la asociación tal como las devolvió el impacto; key es opaca. Las asociaciones marcadas retained no necesitan decisión.

Cada decisión y cada asociación se validan antes de cambiar nada, y el archivado se aplica como un único cambio atómico. Si falta una decisión se devuelve 422 pdf_template_default_replacement_required. POST /v1/companies/{company}/pdf-templates/{template}/restore (solo expected_version) vuelve a activar la plantilla; no reinstala los valores por defecto, los vínculos de serie ni las preferencias de contacto que el archivado sustituyó o quitó.

Identidades comerciales

Una identidad comercial es la marca que muestra una plantilla. Tiene el mismo ciclo de vida que una plantilla, con las mismas operaciones bajo /v1/companies/{company}/pdf-commercial-identities: GET (listado, con q, state, page, per_page), POST (crear), GET /{identity}, PATCH /{identity} (nombre y descripción), GET /{identity}/impact, POST /{identity}/revisions, POST /{identity}/archive, POST /{identity}/restore y GET /{identity}/revisions/{revision}.

La marca vive en configuration, que acepta exactamente estas claves:

ClaveNotas
commercial_nameHasta 120 caracteres.
logo_asset_idUn activo que subiste con kind: logo.
brand_image_asset_idUn activo que subiste con kind: imago.
brand_modelogo, imago o none.
contact_email, contact_phoneHasta 254 y 50 caracteres. Cuando la plantilla muestra el correo o el teléfono de la empresa, el de la marca lo sustituye en la línea de contacto del emisor; cuando la plantilla lo oculta, no sale ninguno. No hay un bloque aparte de contacto comercial.
logo_dark_asset_idOpcional. Versión del logo para fondos oscuros, un activo con kind: logo. Necesita logo_asset_id: al quitar logo_asset_id, envía también null aquí o la petición responde 422 invalid_pdf_template_configuration.
brand_image_dark_asset_idOpcional. Versión de la imagen de marca para fondos oscuros, un activo con kind: imago. Necesita brand_image_asset_id.
dark_background_fallbacksilhouette (por defecto) o plate. Consulta los fondos oscuros.
brand_sizesmall, medium (por defecto) o large. Consulta el tamaño de la marca.

Todas las claves admiten null salvo dark_background_fallback y brand_size. Una marca no tiene dirección: el domicilio del emisor en el PDF es siempre el de la empresa, un dato legal que la marca no puede sustituir.

Los activos deben ser de tu empresa y del tipo correcto; si no, la petición falla (404 pdf_template_asset_not_found o 422). Publicar una revisión pide expected_version, expected_impact_fingerprint y una configuration parcial con al menos una clave. El impacto de una marca también enumera las plantillas que la usan (asociaciones template), y archivarla pide una decisión por asociación, exactamente igual que archivar una plantilla (la decisión sobre una asociación template también puede llevar revision_id).

curl -X POST https://api.factuarea.com/v1/companies/$COMPANY_ID/pdf-commercial-identities \
  -H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Main brand",
    "configuration": {
      "commercial_name": "Acme Studio",
      "logo_asset_id": "0199f39d-52b1-7e34-9c07-1f6a8d3b2e90",
      "logo_dark_asset_id": "0199f39d-6a14-7c52-8e31-2b7c9e4d1f05",
      "brand_mode": "logo",
      "contact_email": "hello@acme.example"
    }
  }'

La marca sobre fondos oscuros

Algunos diseños ponen la marca sobre un fondo oscuro, como el marco del preajuste corporative o la banda de la cabecera del documento de control. En cada captura nueva, la imagen que muestra la plantilla (la de brand_mode) se pinta en este orden:

  1. La versión para fondo oscuro, si la marca la tiene. Sobre un fondo oscuro, logo_dark_asset_id (o brand_image_dark_asset_id para la imagen de marca) se pinta tal cual. Sobre el papel no se usa.
  2. La imagen tal cual, si se lee. Una imagen con fondo propio (un JPEG, o un PNG sin transparencia) se pinta tal cual, y también una cuya tinta contrasta con el fondo.
  3. Si no, una silueta o la placa. Sobre un fondo oscuro decide dark_background_fallback: silhouette (por defecto) pinta la forma de la marca en blanco, y plate la pone sobre una placa clara, siempre que se lea sobre ella (si no, la silueta blanca).
  4. Sobre un fondo claro, como el papel, una imagen que desaparecería (un logo blanco, por ejemplo) se pinta como una silueta negra.

La silueta conserva la forma y la transparencia de la imagen; solo cambia el color de su tinta. En la práctica: sube tu logo en color como logo_asset_id y su versión blanca como logo_dark_asset_id. Los documentos capturados antes de esta regla conservan el aspecto con el que se capturaron.

El tamaño de la marca

brand_size es el tamaño por defecto de la marca: small, medium (por defecto) o large. Una plantilla fija el suyo en configuration.branding.size, o usa inherit, el valor de las plantillas nuevas, para tomar el tamaño de su marca; sin marca, medium. Las plantillas que ya guardaban un tamaño lo conservan. Cada tamaño es una superficie óptica de la tinta, no una caja máxima: un logo apaisado baja de alto y gana ancho, uno vertical crece algo de alto, y el margen transparente que rodea la imagen no cuenta. El mismo tamaño se aplica a todos los diseños, al ticket y al documento de control.

Subir activos

POST /v1/companies/{company}/pdf-templates/assets sube un logotipo o una imagen de marca como multipart/form-data. Idempotency-Key es obligatoria en esta operación.

ParteReglas
kindlogo o imago.
fileJPEG, PNG o WebP, hasta 2 MiB, hasta 6000 px por lado y 24 megapíxeles. El tipo y el tamaño reales se comprueban sobre los bytes, no sobre la extensión.
idUUID v7 opcional.
curl -X POST https://api.factuarea.com/v1/companies/$COMPANY_ID/pdf-templates/assets \
  -H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F kind=logo \
  -F file=@logo.png
{
  "id": "0199f39d-52b1-7e34-9c07-1f6a8d3b2e90",
  "kind": "logo",
  "mime": "image/png",
  "sha256": "7a265f5f003866f84e23c7e237301879b7d4a4ecc0ab80d2041a3c980b12310a",
  "size_bytes": 18342,
  "created_at": "2026-10-14T09:05:12.000000Z"
}

Los activos son privados e inmutables; GET /v1/companies/{company}/pdf-templates/assets/{asset} devuelve estos metadatos en JSON, nunca una ruta de almacenamiento. Con una cabecera Accept image/* devuelve los bytes guardados en línea, con Cache-Control: private, no-store. En JPEG y PNG se eliminan los metadatos EXIF, GPS y de texto. Archivar una plantilla o una marca no borra sus activos, y cada activo cuenta una sola vez para tu espacio de almacenamiento aunque lo compartan varias marcas.

Por MCP, upload_pdf_template_asset recibe la imagen como image_base64 (hasta 2048 KiB ya descodificada), el mime declarado (image/jpeg, image/png o image/webp) y un filename.

Valores por defecto de la empresa

GET /v1/companies/{company}/pdf-templates/defaults devuelve el registro único de tu empresa:

{
  "id": "0199e0aa-4b10-7c33-9a52-6d8e1f3b7a24",
  "version": 1,
  "company_template_id": null,
  "company_commercial_identity_id": null,
  "type_defaults": [],
  "render_activation": "legacy"
}
CampoSignificado
company_template_idPlantilla que se usa cuando no hay nada más específico. Debe poder generar todos los tipos de documento y propósitos.
company_commercial_identity_idMarca que usan las plantillas que no tienen una propia.
type_defaultsLista de { "document_type", "purpose", "template_id" }: la plantilla para un tipo de documento y un propósito.
render_activationSolo lectura. legacy o revisioned: indica si la salida revisionada que se apoya en esta biblioteca está efectivamente activa para tu empresa.

Mientras no escribas nada, la lectura es virtual: id es el UUID de tu empresa, version es 1 y no hay nada guardado. El primer PATCH /v1/companies/{company}/pdf-templates/defaults lo guarda en version 2.

  • Un campo omitido conserva su valor y null lo borra.
  • type_defaults sustituye la lista entera: envía todas las entradas que quieras conservar. El formato de papel no forma parte de la clave.
  • render_activation nunca se acepta: enviarlo, incluso como null, es un 422. Forma parte de la representación, así que cuando cambia también cambia el ETag y un If-Match caducado responde 412 como corresponde.
curl -X PATCH https://api.factuarea.com/v1/companies/$COMPANY_ID/pdf-templates/defaults \
  -H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "expected_version": 1,
    "company_template_id": "0199f3a2-7c4e-7b1a-9d3e-5a2c8f1b6e40",
    "type_defaults": [
      { "document_type": "quote", "purpose": "complete", "template_id": "0199f3b0-2a41-7c88-9e02-d4f6a8b1c3e5" }
    ]
  }'

Una plantilla archivada no puede ser valor por defecto (422 pdf_template_archived), y una plantilla que no admite el tipo de documento o el propósito se rechaza con 422.

El ajuste clásico pdf_template de la personalización de la cuenta es otra capa, anterior. Estos valores por defecto no la sustituyen: véase qué plantilla usa un documento.

Valores por defecto por contacto

Un contacto puede preferir una plantilla para cada tipo de documento y propósito:

  • GET /v1/companies/{company}/pdf-templates/contact-defaults/{contact}/{document_type}/{purpose}
  • PATCH /v1/companies/{company}/pdf-templates/contact-defaults/{contact}/{document_type}/{purpose}

document_type es invoice, quote, proforma o delivery-note, y purpose debe pertenecer a ese tipo (en facturas complete, simplified, corrective o simplified_corrective; en los demás tipos complete).

{
  "id": "0199f2c1-8d10-7a55-8b3e-4c7d2e9f1a06",
  "document_type": "invoice",
  "purpose": "complete",
  "template_id": null,
  "version": 1,
  "persisted": false
}

id es el contacto. Si el contacto se fusionó con otro, configura el contacto resultante: la preferencia del fusionado no se hereda. El contacto debe ser un cliente de tu empresa. Sin preferencia guardada la lectura es virtual (version 1, persisted: false); la primera escritura la guarda en version 2. PATCH recibe template_id (null la borra) y la precondición. Un contacto desconocido o de otra empresa devuelve 404, idéntico al de un contacto inexistente.

Qué plantilla usa un documento

Cuando se crea, se emite o se envía un documento, Factuarea elige su plantilla con este orden, y gana el primer nivel que tenga una plantilla disponible para el tipo de documento, el propósito y el formato de papel:

  1. Selección manual en el documento (selection_mode: manual). Es exclusiva: si esa plantilla ya no está disponible la operación falla, nunca recurre al siguiente nivel.
  2. Valor por defecto de la serie, con GET y PATCH /v1/companies/{company}/series/{series}/pdf-template.
  3. Valor por defecto del contacto canónico.
  4. Valor por defecto de la empresa para el tipo de documento y el propósito (type_defaults).
  5. Plantilla por defecto de la empresa (company_template_id).
  6. Legacy: la personalización de la cuenta (pdf_template, accent_color, logotipo) y el renderizador clásico.

Si un nivel heredado apunta a una plantilla archivada o incompatible, se pasa al siguiente nivel y el documento informa de un aviso en presentation.warnings: pdf_series_template_unavailable cuando era la serie y pdf_inherited_candidate_unavailable para cualquier otro nivel heredado. La marca se resuelve aparte: el commercial_identity_id propio de la plantilla y, si no tiene, la identidad por defecto de la empresa. Cómo lee y cambia un documento concreto su selección está en Presentaciones de documento.

Concurrencia: versiones, ETag e If-Match

Todo recurso mutable de la biblioteca tiene una version, y toda representación que luego puedes cambiar lleva un ETag fuerte: el SHA-256 de su JSON completo, de modo que también cambia cuando cambian availability o render_activation. Las mismas reglas valen para plantillas, identidades, valores por defecto de la empresa y valores por defecto por contacto.

OperaciónPrecondición
PATCH sobre un recursoIf-Match con el ETag, o expected_version en el cuerpo. Al menos una es obligatoria.
Acciones POST (revisions, duplicate, archive, restore)expected_version en el cuerpo. If-Match no se acepta como sustituto.

Si envías las dos en un PATCH, primero se evalúa la etiqueta y después la versión. If-Match acepta una o varias etiquetas de entidad, las débiles (W/"...") y *.

EstadoCódigoSignificado y recuperación
412pdf_template_precondition_failedEl ETag no coincide con la representación actual. Vuelve a leer el recurso y reintenta con la etiqueta nueva.
409pdf_template_version_conflictexpected_version es antigua. error.details trae current_version y recovery: reload_or_keep_local: recarga y vuelve a aplicar tu cambio, o conserva tu copia local y decide.
428pdf_template_precondition_requiredNo enviaste ninguna. Añade If-Match o expected_version.
409pdf_library_impact_conflictLa huella del impacto ha caducado. Vuelve a leer el impacto.

Un conflicto nunca cambia el recurso, y current_version solo sale del recurso de tu propia empresa. Las series usan el mismo patrón con sus propios códigos: series_template_precondition_failed, series_template_version_conflict y series_template_precondition_required.

Idempotencia

Idempotency-Key es obligatoria en POST /v1/companies/{company}/pdf-templates/assets y opcional, pero recomendada, en el resto de escrituras de la biblioteca. Una repetición con la misma clave y el mismo cuerpo devuelve la respuesta guardada con Idempotent-Replayed: true antes de la comprobación de versión, de modo que un reintento tras un timeout no falla con 409 porque tu propio primer intento ya avanzó la versión. La autorización se comprueba de nuevo antes de repetir: si perdiste el rol o el acceso, recibes el error de autorización, no la respuesta guardada. Reutilizar una clave con otro cuerpo devuelve 422 idempotency_key_reused. Consulta Idempotencia para la ventana y el formato.

Errores

EstadoCódigoCuándo
403pdf_template_access_deniedEl rol, el módulo o una restricción del usuario no lo permiten.
403feature_not_available_in_planEl cambio necesita el editor avanzado.
404pdf_template_not_found, pdf_commercial_identity_not_found, pdf_template_asset_not_foundNo existe o es de otra empresa, con la misma respuesta.
409pdf_template_version_conflict, pdf_library_impact_conflictVéase concurrencia.
409pdf_template_asset_conflictEl id que elegiste para la subida del activo ya existe.
409resource_conflictAl crear o duplicar una plantilla, otra petición estaba reservando identificadores en ese momento. No se escribió nada; vuelve a enviarla tras unos segundos.
412 / 428pdf_template_precondition_failed, pdf_template_precondition_requiredVéase concurrencia.
422invalid_pdf_template_configurationClave desconocida, tipo incorrecto, fuera de rango, filtro no válido, contenido prohibido o render_activation en el cuerpo. param trae la ruta.
422pdf_commercial_identity_requiredLa plantilla necesita una marca (branding.mode logo o imago) y ni ella ni la empresa tienen una activa por defecto.
422pdf_template_archived, pdf_commercial_identity_unavailableLa plantilla o la marca está archivada o no se puede seleccionar.
422pdf_template_default_replacement_requiredAl archivado le falta una decisión para una asociación.
422idempotency_key_requiredFalta Idempotency-Key en la subida del activo.
500pdf_library_association_coverage_incompleteEl servidor no pudo inspeccionar todas las asociaciones; no se cambió nada. Reintenta más tarde.

Ramifica según code, nunca según message. Consulta el modelo de errores.

MCP

La biblioteca tiene una tool MCP por operación: list_pdf_templates, get_pdf_template, create_pdf_template, update_pdf_template, publish_pdf_template_revision, duplicate_pdf_template, archive_pdf_template, restore_pdf_template, get_pdf_template_impact, get_pdf_template_revision, los equivalentes de las marcas sin duplicación (list_pdf_commercial_identities, get_pdf_commercial_identity, create_pdf_commercial_identity, update_pdf_commercial_identity, publish_pdf_commercial_identity_revision, archive_pdf_commercial_identity, restore_pdf_commercial_identity, get_pdf_commercial_identity_impact y get_pdf_commercial_identity_revision), get_pdf_template_defaults, set_pdf_template_defaults, get_pdf_template_contact_default, set_pdf_template_contact_default, upload_pdf_template_asset y get_pdf_template_asset. Necesitan los mismos scopes y roles, reciben la versión como expected_version en los argumentos (en MCP no hay cabeceras) y aceptan idempotency_key. Consulta las tools MCP.

En esta página

¿Te echamos una mano?Contactar con soporte