GET/v1/health
Si la API está funcionando. Pública: sin clave, sin datos, sin acceso a la base de datos.
Advanta consulta esta ruta cada 5 minutos; los resultados están en la página de estado pública.
curl -s "$BASE/v1/health"Advanta / Bancos y financiadores / Desarrolladores
Su propio sistema lee las solicitudes de financiación que Advanta le envía, envía sus decisiones, fija lo que exige antes de financiar, gestiona sus límites, envía su extracto bancario para conciliarlo, invita a sus propios clientes y proveedores y recibe webhooks firmados cuando ocurre algo. Cada escritura tiene el mismo efecto que la misma acción en el portal del financiador. Y se lleva todos sus datos, cuando quiera: su derecho de salida.
Una sola URL base sirve a las claves live y de sandbox por igual: la clave decide lo que se ve.
https://bzsengbmlzzhztjfvcag.supabase.co/functions/v1/funder-apiAuthorization: Bearer adv_fk_… en cada llamada: adv_fk_ seguido de 64 caracteres hexadecimales.Empiece por GET /v1/me: indica a qué financiador pertenece la clave, su entorno y sus ámbitos. Después, liste las solicitudes que se le han enviado.
export ADVANTA_KEY="adv_fk_…" # your key, shown once when it was issued
export BASE="https://bzsengbmlzzhztjfvcag.supabase.co/functions/v1/funder-api"
# 1. Who am I: funder, environment, scopes
curl -s "$BASE/v1/me" \
-H "Authorization: Bearer $ADVANTA_KEY"
# 2. The requests routed to me that are still open
curl -s "$BASE/v1/requests?status=open&limit=20" \
-H "Authorization: Bearer $ADVANTA_KEY"// Node.js 18 or later, as an ES module (fetch and top-level await are built in)
const BASE = 'https://bzsengbmlzzhztjfvcag.supabase.co/functions/v1/funder-api';
const headers = { Authorization: `Bearer ${process.env.ADVANTA_KEY}` };
async function call(path) {
const res = await fetch(BASE + path, { headers });
const body = await res.json();
if (!res.ok) throw new Error(`${res.status} ${body.error.code}: ${body.error.message}`);
return body;
}
const me = await call('/v1/me');
console.log(me.environment, me.funder.name, me.key.scopes);
const { count, requests } = await call('/v1/requests?status=open&limit=20');
console.log(`${count} open request(s)`);
for (const r of requests) {
console.log(r.request_ref, r.status, r.total_amount, r.my_offer?.status ?? 'no offer yet');
}GET /v1/me responde así:
{
"api_version": "2026-09-23",
"environment": "sandbox",
"funder": {
"bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3",
"name": "Compartment Demo (LU)"
},
"key": {
"id": "0b3c6a52-5d0e-4b53-9d0e-1c2b3a4d5e6f",
"name": "sandbox · Example prospect",
"prefix": "adv_fk_1a2b3",
"scopes": ["requests:read", "limits:read", "webhooks:write"],
"created_at": "2026-09-23T18:00:00Z",
"expires_at": "2026-10-07T18:00:00Z",
"prospect": "Example prospect"
}
}Hay una sola URL base. La clave decide el entorno, y GET /v1/me lo devuelve en environment.
| environment | El financiador | Lo que ve la clave |
|---|---|---|
live | Clasificado por Advanta como real o piloto. | Solo clientes reales. |
sandbox | Un financiador de demostración. | Solo empresas ficticias, en el plano de demostración. |
unclassified | Aún no clasificado por Advanta. | Ninguna solicitud. |
Una solicitud del otro plano nunca es visible, sea cual sea la clave.
key.prospect en GET /v1/me). Como cualquier clave, se muestra una sola vez y solo se guarda su SHA-256.key.expires_at); a partir de entonces, cada llamada responde 401 key_expired. Advanta también puede revocarla en cualquier momento.decisions:write. Los prescriptores y los enlaces del financiador de demostración los comparten todas las demostraciones.Puede tener una clave de sandbox hoy: su propio sistema contra nuestros datos de demostración, antes de cualquier contrato. Escriba a diogo@advanta.pt. La clave real se emite el día en que quiera conectarse.
Cada llamada lleva Authorization: Bearer adv_fk_<64 hex>. Las claves las emiten las operaciones de Advanta y pertenecen a un financiador. Una clave se muestra una sola vez, solo se guarda su SHA-256 y puede caducar.
Cada clave tiene ámbitos. Una llamada para la que la clave no tiene ámbito responde 403 forbidden.
| Ámbito | Lo que permite |
|---|---|
requests:read | Leer solicitudes (GET /v1/requests, GET /v1/requests/{id} y sus documentos). También lee su configuración y los documentos que exige, los libros de límites, el historial de pagador, sus clientes (prescriptores, enlaces, invitaciones y el informe), sus enlaces de alta, sus endpoints de webhook y sus registros de entregas. También lee los términos de su programa (GET /v1/programme), las reclamaciones de recurso (GET /v1/recourse), sus datos bancarios (GET /v1/bank-data), y las notificaciones de una solicitud y el flujo de caja que su cedente comparte con usted. |
limits:read | Leer los libros de límites (GET /v1/credit-limits, GET /v1/seller-limits) y el historial de pagador. |
limits:write | Fijar, revisar o rechazar límites (PUT /v1/credit-limits, PUT /v1/seller-limits). |
decisions:write | Ofertar, rechazar, financiar y liquidar (POST /v1/requests/{id}/decision), y subir lo que deben firmar los deudores de una solicitud (POST /v1/requests/{id}/consent-level). También permite todas las escrituras de configuración, límites, extractos, clientes, enlaces de alta y endpoints de webhook, y leer los endpoints de webhook, los clientes y los enlaces de alta. También permite exportar todos sus datos. También anuncia una solicitud confidencial (POST /v1/requests/{id}/announce), cierra una reclamación de recurso (POST /v1/recourse/{id}/close) y cambia los términos de su programa. |
settings:write | Cambiar lo que sus deudores deben firmar antes de financiar (PUT /v1/settings) y los documentos que exige a los cedentes (PUT /v1/required-documents). También los términos de su programa (PUT /v1/programme). |
statements:write | Enviar un extracto bancario (POST /v1/statements). |
clients:write | Gestionar sus clientes: añadir y desactivar prescriptores (POST /v1/prescribers, POST /v1/prescribers/{id}/disable), emitir, sustituir y desactivar enlaces (POST /v1/client-links, POST /v1/client-links/{id}/disable), y leerlos, junto con las invitaciones y el informe. |
webhooks:write | Gestionar endpoints de webhook: crear, detener, rotar el secreto, enviar una prueba, y leer la lista y los registros de entregas. |
onboarding:write | Crear enlaces de alta para sus proveedores (POST /v1/onboarding-links) y leerlos. |
exports:write | Exportar todos sus datos (POST /v1/exports, GET /v1/exports, GET /v1/exports/{id} y sus documentos). Solo claves de producción. |
Las rutas son relativas a la URL base. Cualquier llamada puede responder 401 (unauthorized o key_expired), una llamada que necesita un ámbito puede responder 403 forbidden (la clave no tiene el ámbito, o el financiador no está activo), y 500 significa reintentar más tarde. No se repiten abajo; la sección Errores recoge todos los códigos.
A qué financiador pertenece una clave, su entorno y sus ámbitos. Empiece por aquí.
/v1/healthSi la API está funcionando. Pública: sin clave, sin datos, sin acceso a la base de datos.
Advanta consulta esta ruta cada 5 minutos; los resultados están en la página de estado pública.
curl -s "$BASE/v1/health"/v1/meQuién llama: la clave, su financiador, su entorno y sus ámbitos.
key.prefix son los 12 primeros caracteres de la clave. key.expires_at es null para una clave que no caduca; key.prospect indica a quién se emitió una clave de sandbox.
curl -s "$BASE/v1/me" \
-H "Authorization: Bearer $ADVANTA_KEY"{
"api_version": "2026-09-23",
"environment": "sandbox",
"funder": {
"bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3",
"name": "Compartment Demo (LU)"
},
"key": {
"id": "0b3c6a52-5d0e-4b53-9d0e-1c2b3a4d5e6f",
"name": "sandbox · Example prospect",
"prefix": "adv_fk_1a2b3",
"scopes": ["requests:read", "limits:read", "webhooks:write"],
"created_at": "2026-09-23T18:00:00Z",
"expires_at": "2026-10-07T18:00:00Z",
"prospect": "Example prospect"
}
}Lea las solicitudes que Advanta le ha enviado y después oferte, rechace, financie o registre dinero recibido; y exija más a los deudores de una solicitud cuando lo necesite.
/v1/requestsLas solicitudes que se le han enviado (puede actuar sobre ellas) y aquellas sobre las que ya actuó (solo lectura, incluso tras un reenvío a otro financiador), de la más reciente a la más antigua, cada una con su propia oferta en my_offer si la hizo.
| Nombre | En | Descripción |
|---|---|---|
status | query | open (por defecto: pending, submitted, under_review, terms_sent, accepted, approved), all, o un solo estado. |
limit | query | De 1 a 200, 50 por defecto. |
Una solicitud trae id, request_ref, type (factoring o confirming), status, total_amount, advance_amount, el cedente en company_name y company_nif, invoice_count, assigned_bank_id, consent_level_required (lo que cada deudor debe firmar antes de poder financiarla, fijado cuando se envió), sus fechas y, por deudor, debtor_consent. La especificación recoge todos los campos.
curl -s "$BASE/v1/requests?status=all&limit=50" \
-H "Authorization: Bearer $ADVANTA_KEY"const BASE = 'https://bzsengbmlzzhztjfvcag.supabase.co/functions/v1/funder-api';
const headers = { Authorization: `Bearer ${process.env.ADVANTA_KEY}` };
const res = await fetch(`${BASE}/v1/requests?status=open&limit=200`, { headers });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { funder, requests } = await res.json();
// Routed to you (you can act on them) and not priced by you yet
const toPrice = requests.filter((r) => r.assigned_bank_id === funder.bank_id && !r.my_offer);
for (const r of toPrice) console.log(r.request_ref, r.type, r.total_amount, r.company_name);{
"funder": {
"bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3",
"name": "Compartment Demo (LU)"
},
"count": 1,
"requests": [
{
"id": "4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87",
"request_ref": "FR-2026-0042",
"type": "factoring",
"status": "terms_sent",
"total_amount": 18450.00,
"company_name": "Example Seller, S.L.",
"invoice_count": 3,
"assigned_bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3",
"consent_level_required": "acknowledgment",
"created_at": "2026-09-22T09:12:00Z",
"my_offer": {
"funding_request_id": "4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87",
"rate": 2.4,
"advance_pct": 90,
"days": 60,
"status": "pending",
"submitted_at": "2026-09-23T10:30:00Z",
"accepted_at": null
},
"debtor_consent": [
{
"debtor_name": "Example Buyer, S.A.",
"debtor_tax_id": "A00000000",
"status": "pending",
"level_required": "acknowledgment",
"level_achieved": null,
"meets_requirement": false
}
]
}
]
}/v1/requests/{id}El expediente de análisis de una solicitud: la solicitud, sus créditos, el Advanta Score más reciente del cedente, su propia oferta y risk, las señales de fraude y las impugnaciones de la solicitud, tal como las muestra su portal.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
score va de 300 a 850, con una nota de la A a la E y sus dimensiones. Se calcula en el momento cuando el cedente aún no tiene ninguno, y es null si eso falla. Cada crédito tiene invoice_no, invoice_amount, invoice_date, invoice_due_date y el deudor en customer_name. debtor_consent da, por deudor, el estado de la notificación, el nivel exigido y el nivel firmado (level_achieved), meets_requirement, el canal, el texto de la declaración firmado y quién lo firmó.
risk.signals lista las señales de fraude aún abiertas o confirmadas, cada una con un code estable (por ejemplo amount_above_history) y una severity. Una señal hard (por ejemplo un importe cambiado mientras la factura está en una solicitud, una factura rectificativa contra ella o una impugnación abierta) detiene la asignación y la financiación hasta que el equipo de operaciones de Advanta la revise; las demás solo avisan. risk.disputes lista todas las impugnaciones registradas contra la solicitud.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/requests/{id}/decisionOfertar condiciones, rechazar, financiar o registrar una liquidación. La solicitud debe estar enviada a usted; si no, 409 not_routed_to_you.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
El cuerpo tiene una de cuatro formas, según decision:
decision | Campos | Efecto |
|---|---|---|
offer | rate (porcentaje, mayor que 0 y hasta 100) y advance_pct (mismo rango), ambos obligatorios; days, notes, valid_days (de 1 a 90). | Envía sus condiciones y pasa una solicitud pending, submitted o under-review a terms_sent. La oferta caduca a los valid_days o, si no se indica, al final de la validez configurada (7 días por defecto). Se rechaza con 409 credit_limit cuando uno de sus límites no puede cubrirla, con 409 debtor_not_eligible_for_funder cuando solo acepta compradores de su lista y un deudor no está en ella, y con 409 documents_missing_for_funder cuando un documento que exige al cedente falta, no está verificado o ha caducado. |
decline | reason o notes, al menos uno; notes es el mensaje que lee el cedente. internal_note opcional: queda para su equipo, nunca se muestra al cedente. | Cierra la solicitud. reason es uno de payer_credit, invoice_ineligible, documentation, concentration, amount_out_of_range, sector_excluded, no_funder_capacity, withdrawn_by_client u other; el texto libre se guarda como nota con el motivo other. |
fund | value_date (AAAA-MM-DD, la fecha valor de su transferencia al cedente, hasta 7 días por delante) y reference (la referencia de la transferencia, de 3 a 140 caracteres); amount opcional, comprobado con el anticipo aceptado. | Solo cuando el cedente ha aceptado sus condiciones (estado approved). En factoring, la notificación de cada deudor debe estar confirmada antes (si no, 409 funding_gate_failed), y los documentos que exige al cedente deben estar vigentes en la fecha de financiación (si no, 409 documents_missing_for_funder). |
settle | amount (obligatorio); received_at (por defecto ahora, como mucho un día por delante); reference (hasta 140 caracteres); note (hasta 1.000); final. | Registra dinero recibido en una solicitud financiada. Los pagos parciales se suman; la solicitud pasa a settled cuando el total alcanza el importe de la solicitud o final es true. |
curl -s -X POST "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/decision" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"decision":"offer","rate":2.4,"advance_pct":90,"days":60,"valid_days":7,"notes":"Subject to the notice being acknowledged"}'async function offer(requestId, terms) {
const res = await fetch(`${BASE}/v1/requests/${requestId}/decision`, {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify({ decision: 'offer', ...terms }),
});
const body = await res.json();
if (res.status === 201) return body; // { decision, request_id, offer_id, expires_at, status }
const { code, message, debtors } = body.error;
if (code === 'debtor_not_eligible_for_funder') {
for (const d of debtors) console.warn(d.name ?? d.debtor_key, d.reason, d.invoices);
}
throw new Error(`${res.status} ${code}: ${message}`);
}
await offer('4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87', { rate: 2.4, advance_pct: 90, days: 60, valid_days: 7 });{
"decision": "offer",
"request_id": "4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87",
"offer_id": "7a9e3c1b-2d4f-4e6a-8b0c-5d1e2f3a4b5c",
"expires_at": "2026-09-30T10:30:00Z",
"status": "terms_sent"
}{ "decision": "decline", "reason": "concentration", "notes": "We cannot fund this buyer this quarter", "internal_note": "Group exposure above our internal limit" }
{ "decision": "fund", "value_date": "2026-10-01", "reference": "TRF-2026-1001-07" }
{ "decision": "settle", "amount": 12500.00, "received_at": "2026-10-30T10:00:00Z", "reference": "ADV-A1F51301-1000" }/v1/requests/{id}/consent-levelSubir lo que deben firmar los deudores de una solicitud. Solo hacia arriba, solo en una solicitud de factoring enviada a usted y en curso, y solo antes de que alguno de sus deudores haya respondido.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
level obligatorio | body | receipt, acknowledgment o acceptance, de menor a mayor. |
reason obligatorio | body | Por qué, con al menos 8 caracteres. |
curl -s -X POST "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/consent-level" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"level":"acceptance","reason":"Credit committee asked for acceptance on this buyer"}'Lo que debe estar en regla antes de financiar: los documentos que exige a los cedentes, por país del cedente, y lo que cada deudor debe firmar. Cada solicitud guarda las versiones que cumplieron sus requisitos.
/v1/requests/{id}/documentsEl expediente documental de una solicitud. Cuando la solicitud se le envió, y de nuevo cuando se financió, Advanta registró qué versión de cada documento que usted exige le dio conformidad: el nombre del fichero, el SHA-256, las fechas de emisión y de validez, y cuándo y cómo lo verificó Advanta. Ese registro no cambia nunca, aunque el cedente suba versiones más recientes; cada entrada dice también en qué situación está hoy el documento, y current recoge los documentos actuales del cedente.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
Cada entrada con fichero trae una download_url válida durante dos minutos (url_expires_in), y cada URL emitida queda registrada. Compare el SHA-256 de lo que descargue con el registrado.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/documents" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/required-documentsLos documentos que exige a los cedentes, por país del cedente, y el catálogo del que se eligen: el código de cada documento, su nombre en siete idiomas, el emisor, la validez habitual y la sensibilidad. La validez habitual solo sirve para rellenar por defecto: cuenta la fecha impresa en el documento, que el cedente registra y Advanta comprueba.
Una solicitud solo se le envía, su oferta solo se registra y la solicitud solo se financia mientras todos los documentos de su lista para el país del cedente estén verificados por Advanta y vigentes en esa fecha; si no, 409 documents_missing_for_funder.
curl -s "$BASE/v1/required-documents" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/required-documentsSustituir su lista para un país de cedentes; una lista vacía la borra. Los códigos vienen del catálogo, y el cambio queda guardado en la cadena de evidencias de Advanta con note. Las solicitudes que ya tiene siguen con usted; su próxima oferta o financiación en una de ellas espera hasta que el cedente cumpla la nueva lista (open_requests_not_meeting las cuenta).
| Nombre | En | Descripción |
|---|---|---|
country obligatorio | body | El país del cedente, dos letras. |
codes obligatorio | body | Códigos de documento del catálogo. |
note | body | Hasta 500 caracteres. |
curl -s -X PUT "$BASE/v1/required-documents" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"country":"PT","codes":["cert_hacienda","cert_seguridad_social","cirbe"],"note":"Credit committee of 23 September"}'/v1/settingsLo que sus deudores deben firmar antes de financiar: el nivel que cada deudor debe firmar antes de que pueda financiarse una solicitud de factoring enviada a usted (receipt, luego acknowledgment, luego acceptance), si solo cuentan los textos de declaración aprobados por un abogado, sus solicitudes abiertas por nivel, y qué niveles tiene cada ley aplicable en texto de declaración, y en qué idiomas.
curl -s "$BASE/v1/settings" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/settingsCambiar lo que sus deudores deben firmar. El cambio se aplica a las solicitudes que se le envíen a partir de ese momento; una solicitud ya enviada mantiene el nivel con el que se envió. reason queda guardado en la cadena de evidencias de Advanta.
| Nombre | En | Descripción |
|---|---|---|
debtor_consent_level | body | receipt, acknowledgment o acceptance. |
require_counsel_approved_texts | body | true para contar solo los textos de declaración aprobados por un abogado. |
reason obligatorio | body | Por qué, con al menos 8 caracteres. |
curl -s -X PUT "$BASE/v1/settings" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"debtor_consent_level":"acknowledgment","reason":"Credit committee decision of 22 September"}'Elija, por defecto y por empresa, si cada deudor recibe la notificación antes de que usted financie (anunciado) o si la notificación queda preparada y lista para enviar (confidencial), con o sin recurso, y si pide los datos bancarios del cedente. Después, anuncie una solicitud confidencial, lea sus notificaciones y el flujo de caja que el cedente comparte con usted, y siga sus reclamaciones de recurso.
/v1/programmeLos términos de su programa: sus términos por defecto, los que fijó para empresas concretas, las empresas para las que puede fijar términos (las que tienen una solicitud enviada a usted y sus propios clientes) y sus solicitudes de factoring contadas por los términos que llevan. Una solicitud toma los términos vigentes cuando se le envía y los conserva.
disclosure: announced (por defecto): cada deudor recibe la notificación y confirma la cesión antes de que usted financie. confidential: cuando la solicitud se le envía, la notificación a cada deudor se prepara, con su huella (SHA-256), y se guarda lista para enviar, y la financiación no espera al deudor. Antes de financiar, todas las comprobaciones bloqueantes de las facturas deben superarse, las facturas deben venir de la contabilidad del propio cedente (ERP, factura electrónica o SAF-T), cada deudor debe tener una notificación preparada y vigente que le nombra a usted y una dirección a la que enviarla, y la verificación del cedente debe estar aprobada. Las notificaciones se envían cuando usted anuncia la solicitud y, automáticamente, en una solicitud financiada, cuando se cumple un disparador que activó: announce_overdue_days, announce_on_dispute, announce_on_kyc_lapse.
recourse: with (con recurso) o without (sin recurso). recourse_days: días tras el vencimiento de una factura hasta que una solicitud financiada aún no liquidada abre una reclamación (null: ninguna). bank_data: off, requested (se pide al cedente que conecte su cuenta bancaria de empresa para usted, solo lectura y con su consentimiento) o required (la financiación espera además a que la cuenta en la que usted paga se confirme como del propio cedente).
curl -s "$BASE/v1/programme" \
-H "Authorization: Bearer $ADVANTA_KEY"{
"funder": { "bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3", "name": "Example Funder" },
"default": {
"disclosure": "announced",
"recourse": "with",
"recourse_days": 30,
"announce_overdue_days": null,
"announce_on_dispute": false,
"announce_on_kyc_lapse": false,
"bank_data": "requested",
"source": "funder_default",
"updated_at": "2026-09-28T10:00:00Z"
},
"companies": [
{
"seller_id": "2f6d8a4e-1b3c-4d5e-9f70-8a1b2c3d4e5f",
"company_name": "Example Seller, S.L.",
"tax_id": "B00000000",
"terms": { "disclosure": "confidential", "recourse": "with", "recourse_days": 30, "announce_overdue_days": 15, "announce_on_dispute": true, "announce_on_kyc_lapse": true, "bank_data": "required", "source": "seller" },
"reason": "Credit committee of 28 September"
}
],
"requests": { "announced:with:open": 4, "confidential:with:funded": 1 }
}/v1/programmeCambiar sus términos por defecto (sin seller_id) o los de una empresa. Solo cambian las claves que envíe; {"reset": true} con un seller_id devuelve esa empresa a sus términos por defecto. El cambio se aplica a las solicitudes que se le envíen a partir de ese momento; las ya enviadas conservan sus términos. reason queda guardado en la cadena de evidencias de Advanta.
| Nombre | En | Descripción |
|---|---|---|
seller_id | body | El id de una empresa, de sellers en GET /v1/programme. Ausente o null: sus términos por defecto. |
terms obligatorio | body | Los términos a cambiar: disclosure, recourse, recourse_days, announce_overdue_days, announce_on_dispute, announce_on_kyc_lapse, bank_data; o reset. |
reason obligatorio | body | Por qué, con al menos 8 caracteres. |
curl -s -X PUT "$BASE/v1/programme" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"seller_id":"2f6d8a4e-1b3c-4d5e-9f70-8a1b2c3d4e5f","terms":{"disclosure":"confidential","announce_overdue_days":15,"announce_on_dispute":true,"announce_on_kyc_lapse":true,"bank_data":"required"},"reason":"Credit committee of 28 September"}'/v1/requests/{id}/announceAnunciar una solicitud confidencial enviada a usted: pasa a anunciada y las notificaciones preparadas para ella se envían a sus deudores, que después las confirman como en un programa anunciado. Posible mientras la solicitud está pendiente, en estudio, con condiciones enviadas, aprobada o financiada. Le sigue un evento request.announced; una vez enviada una notificación, la solicitud queda anunciada.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
reason obligatorio | body | Por qué, con al menos 8 caracteres. Queda guardado en la cadena de evidencias de Advanta. |
curl -s -X POST "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/announce" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"reason":"Invoice 2026-118 is 20 days overdue"}'/v1/requests/{id}/noticesLas notificaciones de cesión de la solicitud, una por deudor, cada una con su documento preparado cuando lo hay: el asunto y el HTML exactos que recibe el deudor, su idioma, la ley aplicable y su SHA-256. Para una solicitud enviada a usted, o una en la que ya actuó.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
El HTML lleva un marcador, ACK_LINK entre llaves dobles, donde va el enlace de confirmación del deudor; el enlace contiene un secreto y nunca se muestra. current indica si el documento aún coincide con las facturas y el importe de la notificación.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/notices" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/requests/{id}/cash-flowLo que el cedente comparte con usted de su cuenta bancaria de empresa, solo lectura y con su consentimiento, a través de un proveedor autorizado de información sobre cuentas: la conexión, sus cuentas (los cuatro últimos caracteres de cada IBAN) y sus saldos, doce meses de movimientos por mes y la comprobación de su cuenta de cobro. cash_flow es null mientras el cedente no haya conectado una cuenta para usted.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
bank_data_problems indica lo que la financiación aún espera cuando sus términos exigen datos bancarios. payment_alerts son los pagos que el cedente recibió de un deudor de esta solicitud después de que usted la financiara en términos confidenciales. El consentimiento de un cedente se da a un financiador: usted solo ve lo que comparte con usted.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/cash-flow" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/recourseSus solicitudes de factoring financiadas por tipo de recurso (with, without, y not_recorded para las enviadas antes del 28 de septiembre de 2026), las reclamaciones contadas por tipo y estado, y las propias reclamaciones, primero las abiertas. Se abre una reclamación por solicitud cuando una solicitud financiada no está liquidada recourse_days después del vencimiento de una factura: recourse, contra el cedente, por el importe anticipado más sus comisiones, menos lo que ya cobró; debtor_default, sin recurso, para su propio recobro y seguro.
| Nombre | En | Descripción |
|---|---|---|
status | query | open, settled, withdrawn o written_off. Ausente: todas las reclamaciones. |
El cedente reembolsa una reclamación de recurso en pay_to_iban indicando pay_reference. Cuando los pagos que usted registre desde entonces (una línea de extracto que confirma, o la decisión settle) cubren claim_amount, la reclamación queda liquidada y la solicitud se cierra como liquidada por recurso: las facturas vuelven al cedente, aún impagadas por el deudor.
curl -s "$BASE/v1/recourse?status=open" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/recourse/{id}/closeCerrar una reclamación suya abierta: una reclamación de recurso queda withdrawn (renunció a ella, o acordó otra cosa con el cedente), un impago del deudor queda written_off (pasó a su recobro o a su aseguradora). reason queda guardado en la cadena de evidencias de Advanta.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la reclamación (claim_id). |
status obligatorio | body | withdrawn o written_off. |
reason obligatorio | body | Por qué, con al menos 8 caracteres. |
curl -s -X POST "$BASE/v1/recourse/$CLAIM_ID/close" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"withdrawn","reason":"Payment plan agreed with the seller on 2 October"}'/v1/bank-dataSu propia cuenta de cobro, conectada por su administrador en el portal y leída del mismo modo: sus movimientos pasan por la misma conciliación que POST /v1/statements, de modo que los cobros casan con sus solicitudes financiadas sin enviar ficheros. También cuántos cedentes comparten su cuenta con usted, las alertas de pago en sus solicitudes (los últimos 180 días) y los costes del proveedor registrados a su cargo, por mes.
unit_price_eur y amount_eur son null hasta que se fije el precio del proveedor.
curl -s "$BASE/v1/bank-data" \
-H "Authorization: Bearer $ADVANTA_KEY"Su exposición por deudor y por cedente, aplicada por la propia plataforma, con límites fijados uno a uno o hasta 2.000 de una vez; cómo paga un comprador a sus proveedores; y lo que Advanta sabe de cada deudor de una solicitud.
/v1/credit-limitsSu libro por deudor: su límite y lo que está vivo, comprometido, ofertado y aún disponible, en euros.
Cada deudor trae debtor_key, debtor_name, debtor_country, limit_status, limit_amount, outstanding, committed, offered, available, overdue_count, oldest_overdue, frozen, decided_at y note.
curl -s "$BASE/v1/credit-limits" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/credit-limitsFijar o revisar su límite para un deudor, o rechazar al deudor. La base de datos rechaza cualquier oferta posterior que este límite no pueda cubrir.
| Nombre | En | Descripción |
|---|---|---|
debtor_tax_id obligatorio | body | El NIF o número de IVA del deudor. |
debtor_country | body | ISO 3166 alfa-2. |
debtor_name | body | El nombre del deudor. |
amount | body | Euros, 0 o más. Obligatorio para un límite activo. |
status | body | active (por defecto), refused o suspended. |
note | body | Texto libre. |
curl -s -X PUT "$BASE/v1/credit-limits" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"debtor_tax_id":"A00000000","debtor_country":"ES","debtor_name":"Example Buyer, S.A.","amount":250000,"status":"active"}'/v1/credit-limits/importCargar hasta 2.000 límites sobre deudores en una sola llamada: su propio libro, o los límites de su aseguradora de crédito. Cada fila se comprueba exactamente como PUT /v1/credit-limits comprueba uno y recibe su propia respuesta: una fila que falla no detiene a las demás, y un deudor que aparece dos veces en la misma llamada se rechaza la segunda vez.
| Nombre | En | Descripción |
|---|---|---|
rows obligatorio | body | De 1 a 2.000 filas, cada una con debtor_tax_id y, como en PUT /v1/credit-limits, debtor_country, debtor_name, amount, status y note. amount es un número o dígitos con punto decimal; es obligatorio para un límite activo. También se acepta la lista de filas sola, sin el objeto alrededor (con source import). |
source | body | import (sus propios límites, por defecto) o insurer (los límites de su aseguradora de crédito). |
source_ref | body | El fichero o lote del que vienen los límites, como máximo 200 caracteres. |
Cada límite escrito registra su origen y su referencia, en el límite y en su historial. La respuesta cuenta received, written y refused, y responde a cada fila con row (contando desde 1), debtor_tax_id y ok: una fila escrita añade debtor_key, status y amount; una fila rechazada da su error (invalid_amount, debtor_tax_id_required, duplicate_debtor, invalid_status, amount_required, invalid_country, row_invalid o invalid_limit) y puede añadir un detail.
curl -s -X POST "$BASE/v1/credit-limits/import" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"insurer","source_ref":"Insurer limits 2026-09","rows":[{"debtor_tax_id":"A00000000","debtor_country":"ES","debtor_name":"Example Buyer, S.A.","amount":250000},{"debtor_tax_id":"500000000","debtor_country":"PT","status":"refused"}]}'/v1/seller-limitsSu libro por cedente, con las mismas cifras que el libro de deudores.
Cada cedente trae seller_id, seller_name, seller_nif, seller_country y los mismos campos de límite y exposición que un deudor.
curl -s "$BASE/v1/seller-limits" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/seller-limitsFijar o revisar su límite para un cedente, o rechazar al cedente.
| Nombre | En | Descripción |
|---|---|---|
seller_id obligatorio | body | Tal como lo devuelve GET /v1/seller-limits. |
amount | body | Euros, 0 o más. |
status | body | active (por defecto), refused o suspended. |
note | body | Texto libre. |
curl -s -X PUT "$BASE/v1/seller-limits" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"seller_id":"2f6d8a4e-1b3c-4d5e-9f70-8a1b2c3d4e5f","amount":100000,"status":"active","note":"Annual review"}'/v1/payer-recordCómo paga un comprador a sus proveedores, solo en agregado, a partir de la contabilidad de los proveedores conectados a Advanta. El historial se publica cuando al menos tres proveedores observan al comprador; si no, status explica por qué y todas las cifras son null. Solo puede leerlo para un comprador que esté en una solicitud de su ámbito o en su lista de deudores; una clave de sandbox lee el historial del plano de demostración.
| Nombre | En | Descripción |
|---|---|---|
tax_id obligatorio | query | El NIF o número de IVA del comprador. |
country | query | ISO 3166 alfa-2. |
Las cifras incluyen observers, invoice_count, avg_days_to_pay, median_days_to_pay, on_time_pct, el retraso en el pago (avg_settle_delay_days, median_settle_delay_days, p75_settle_delay_days, worst_settle_delay_days), recuentos abiertos y vencidos, window_from y refreshed_at. payer_record es null cuando no hay historial.
curl -s "$BASE/v1/payer-record?tax_id=A00000000&country=ES" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/requests/{id}/debtorsLo que Advanta sabe de cada deudor de una solicitud de factoring enviada a usted, o de una en la que ya actuó: su level en Advanta desde level_since (notice: conoce Advanta solo por la notificación; account: activó su cuenta de pagador; books: conectó su sistema contable; buyer: tiene un programa de comprador, y buyer_programme es true), el historial del propio cedente con él, su periodo medio de pago oficial cuando es un organismo público, y su límite sobre él.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la solicitud. |
score es la puntuación del propio deudor (clase, de 0 a 100, cuándo y con qué versión del modelo). Solo se da cuando el deudor comparte sus datos con los financiadores que financian facturas que él debe, está en el nivel books o buyer, y la solicitud está enviada a usted (no una en la que solo actuó); si no, es null. pair_history es el historial del cedente con este deudor a lo largo de 36 meses, con las reglas del historial de pagador: solo facturas reales, y retraso solo frente a fechas de vencimiento que constan en el documento o en el ERP. public_payment_period es el periodo medio de pago oficial más reciente de un organismo público (DGAL para los municipios portugueses, Hacienda para las entidades locales españolas). credit_limit es su límite sobre el deudor, de dónde viene (source, source_ref) y lo que está usado (exposure: vivo más comprometido más ofertado, en euros).
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/debtors" \
-H "Authorization: Bearer $ADVANTA_KEY"Envíe el extracto de su cuenta de cobro y cada abono se concilia con sus solicitudes financiadas; usted confirma cada coincidencia en el portal. Para registrar un pago directamente, envíe la decisión settle.
/v1/statementsEnviar el extracto de su cuenta de cobro para conciliarlo: un fichero CAMT.053 (XML) o CSV, como máximo 4 MiB y 5.000 movimientos. Cada abono se concilia con sus propias solicitudes financiadas, primero por la referencia que indicó el deudor. No se liquida nada hasta que usted confirme una coincidencia en el portal. El mismo fichero enviado dos veces se rechaza, por su SHA-256.
| Nombre | En | Descripción |
|---|---|---|
file_name | query | El nombre del fichero (opcional). |
kind | query | camt053 o csv; se detecta si se omite. |
| el fichero obligatorio | body | El fichero original, enviado como application/xml o text/csv; o JSON { file_name, kind, content_base64 }. |
curl -s -X POST "$BASE/v1/statements?file_name=statement-2026-10-30.xml&kind=camt053" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/xml" \
--data-binary @statement-2026-10-30.xmlTraiga a sus propios clientes: un enlace abierto propio, un enlace por prescriptor, y las invitaciones y el informe que muestran quién llegó por cada uno. Las empresas que usted trae se le envían solo a usted.
/v1/client-linksSu propio enlace abierto (prescriber_id null) y el enlace actual de cada prescriptor, con su state (active, disabled o expired) y su url mientras funciona.
| Nombre | En | Descripción |
|---|---|---|
lang | query | El idioma de la página que abre cada enlace: pt, es, en, fr, de, it o nl, añadido a su url. |
Una empresa que abre un enlace da su nombre, su número fiscal, su país y su correo, y recibe su invitación por correo. Cuando la acepta, pasa a ser su cliente: sus solicitudes se le envían solo a usted, y su origen (el enlace, el prescriptor, la fecha) queda registrado. Abrir un enlace nunca crea una cuenta por sí solo.
Cada enlace lleva también arrivals (las empresas cuya primera llegada a usted fue por él) y claims_last_day (las altas por él en las últimas 24 horas; un enlace admite como mucho 20 por hora y 100 por día).
curl -s "$BASE/v1/client-links?lang=es" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/client-linksEmitir su propio enlace abierto, o el de un prescriptor con prescriber_id. Hay un enlace activo por titular: mientras uno siga funcionando, envíe replace: true para sustituirlo (el anterior deja de funcionar enseguida); si no, 409 link_exists. Solo se guarda el SHA-256 del token del enlace, y la emisión queda registrada en la cadena de evidencias de Advanta.
| Nombre | En | Descripción |
|---|---|---|
prescriber_id | body | Uno de sus prescriptores activos; omítalo, o envíe null, para su propio enlace. |
expires_at | body | Opcional: entre una hora y tres años desde ahora. |
replace | body | true para sustituir un enlace que sigue funcionando. Por defecto false. |
reason | body | El motivo, hasta 200 caracteres. Queda guardado en el enlace sustituido y en la cadena de evidencias. |
lang | body | El idioma de la página que abre el enlace, añadido a su url. |
Un enlace emitido con una clave de sandbox solo genera invitaciones de prueba, y la clave necesita decisions:write: los enlaces del financiador de demostración los comparten todas las demostraciones.
curl -s -X POST "$BASE/v1/client-links" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"replace":true,"reason":"The old link was forwarded too widely","lang":"es"}'{
"client_link": {
"id": "8d3e1f2a-4b5c-4d6e-9f70-1a2b3c4d5e6f",
"prescriber_id": null,
"state": "active",
"created_at": "2026-09-26T10:00:00Z",
"expires_at": null,
"disabled_at": null,
"disabled_reason": null,
"replaced_by": null,
"arrivals": 0,
"claims_last_day": 0,
"url": "https://app.advanta.capital/join?link=…&lang=es"
}
}/v1/client-links/{id}/disableDesactivar un enlace. Deja de funcionar enseguida; las empresas que ya llegaron por él conservan su origen. Desactivar un enlace ya desactivado no cambia nada (changed es false). Para dar uno nuevo, llame a POST /v1/client-links.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id del enlace, de GET /v1/client-links. |
reason | body | El motivo, hasta 200 caracteres. |
curl -s -X POST "$BASE/v1/client-links/$LINK_ID/disable" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"reason":"Campaign ended"}'/v1/prescribersSus prescriptores, las personas y firmas que le traen clientes (gestorías, asesores, intermediarios), primero los activos, cada uno con su enlace actual y el número de empresas que llegaron por él. Son suyos, no socios de Advanta. La misma lista que la página Clientes de su portal.
| Nombre | En | Descripción |
|---|---|---|
lang | query | El idioma de la página que abre cada enlace: pt, es, en, fr, de, it o nl, añadido a su url. |
Una clave de sandbox lee los prescriptores del financiador de demostración, que comparten todas las demostraciones.
curl -s "$BASE/v1/prescribers?lang=es" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/prescribersAñadir un prescriptor. Su propio enlace abierto se emite con él, en prescriber.link.url. Su nombre y su correo quedan fuera de la cadena de evidencias de Advanta: solo entran sus hashes.
| Nombre | En | Descripción |
|---|---|---|
name obligatorio | body | De 2 a 120 caracteres, único entre sus prescriptores activos. |
email | body | Opcional. Un financiador de sandbox solo registra direcciones reservadas (terminadas en .example, .invalid, .test o .demo). |
notes | body | Opcional, hasta 1.000 caracteres. |
lang | body | El idioma de la página que abre su enlace, añadido a su url. |
Con una clave de sandbox esto cambia el estado de demostración compartido, así que la clave necesita decisions:write.
curl -s -X POST "$BASE/v1/prescribers" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Gestoría Norte","email":"ana@gestoria-norte.example","notes":"Accountant in Bilbao","lang":"es"}'{
"prescriber": {
"id": "5f1c2a8e-3b7d-4e0a-9c61-2d4b8e7f9a10",
"name": "Gestoría Norte",
"email": "ana@gestoria-norte.example",
"notes": "Accountant in Bilbao",
"active": true,
"created_at": "2026-09-10T09:00:00Z",
"disabled_at": null,
"link": {
"id": "1e2f3a4b-5c6d-4e7f-8a9b-0c1d2e3f4a5b",
"prescriber_id": "5f1c2a8e-3b7d-4e0a-9c61-2d4b8e7f9a10",
"state": "active",
"expires_at": null,
"arrivals": 0,
"url": "https://app.advanta.capital/join?link=…&lang=es"
}
}
}/v1/prescribers/{id}/disableDesactivar un prescriptor. Su enlace deja de funcionar enseguida; las empresas que trajo siguen atribuidas a él. Desactivar un prescriptor ya desactivado no cambia nada (changed es false). Queda registrado en la cadena de evidencias de Advanta.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id del prescriptor. |
reason | body | El motivo, hasta 200 caracteres. |
curl -s -X POST "$BASE/v1/prescribers/$PRESCRIBER_ID/disable" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"reason":"Agreement ended"}'/v1/prescribers/reportLo que le trajo cada prescriptor: un grupo por prescriptor, después su propio enlace (own_link), sus invitaciones por nombre (named) y sus enlaces de alta (api). Por grupo y por empresa: cuándo llegó, cuándo se abrió su cuenta (joined), cuándo se aprobó la verificación de la empresa (onboarded), las solicitudes enviadas a usted, el importe solicitado y el importe financiado. Las mismas cifras que su portal.
Una empresa cuenta una vez, para quien se la trajo primero. El importe financiado es el anticipo (o, si no lo hay, el total) de las solicitudes financiadas o liquidadas, en euros; totals suma todos los grupos. Solo sus datos y solo empresas de su plano de datos: una clave de sandbox no ve lo que otras claves de sandbox hicieron por la API.
curl -s "$BASE/v1/prescribers/report" \
-H "Authorization: Bearer $ADVANTA_KEY"{
"funder": {
"bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3",
"name": "Compartment Demo (LU)"
},
"plane": "sandbox",
"generated_at": "2026-09-26T10:00:00Z",
"currency": "EUR",
"totals": { "arrived": 1, "joined": 1, "onboarded": 1, "requests": 1, "amount_requested": 18450.00, "amount_funded": 16605.00 },
"groups": [
{
"kind": "prescriber",
"prescriber_id": "5f1c2a8e-3b7d-4e0a-9c61-2d4b8e7f9a10",
"name": "Gestoría Norte",
"active": true,
"since": "2026-09-10T09:00:00Z",
"arrived": 1,
"joined": 1,
"onboarded": 1,
"requests": 1,
"amount_requested": 18450.00,
"amount_funded": 16605.00,
"companies": [
{
"company_name": "Example Seller, S.L.",
"company_tax_id": "B00000000",
"country": "ES",
"arrived_at": "2026-09-15T11:02:00Z",
"joined_at": "2026-09-15T11:20:00Z",
"onboarded_at": "2026-09-16T09:15:00Z",
"requests": 1,
"amount_requested": 18450.00,
"amount_funded": 16605.00
}
]
}
]
}/v1/client-invitationsTodas sus invitaciones, las más recientes primero: por un enlace, por nombre en el portal o con un enlace de alta. Cada una indica cómo llegó la empresa (via: link, named o api), el prescriptor que la trajo, si lo hay, su state (pending, accepted, revoked o expired), la empresa, el contacto y las fechas.
| Nombre | En | Descripción |
|---|---|---|
limit | query | De 1 a 500, 200 por defecto. |
Solo su propio plano de datos. Una clave de sandbox no ve las invitaciones que hicieron otras claves de sandbox.
curl -s "$BASE/v1/client-invitations?limit=50" \
-H "Authorization: Bearer $ADVANTA_KEY"Cada mañana, las facturas de sus propios clientes que durante la noche han pasado a cumplir sus reglas, y lo que ha cambiado en las que ya se le mostraron. El webhook opportunities.daily le avisa cuando hay algo que leer.
/v1/opportunitiesEl resumen de un día, de sus propios clientes (las empresas de las que usted es el financiador de origen) que le permiten ver sus facturas. Cada mañana hacia las 06:30, hora de Madrid, después de la precalificación nocturna, Advanta lista las facturas que han pasado a cumplir sus reglas desde el resumen anterior (kind new) y lo que ha cambiado en las que ya se le mostraron: paid, disputed (el cliente registró que su deudor la impugna) o no_longer_eligible.
| Nombre | En | Descripción |
|---|---|---|
date | query | El día del resumen, YYYY-MM-DD (hora de Madrid). Ausente: el más reciente. Un día sin resumen responde date null y ninguna línea. |
Una línea trae la factura, el deudor con su NIF, el importe aún pendiente, la fecha de vencimiento, y el cliente con su sector (sección NACE), clase y tamaño; primero las líneas nuevas, después los cambios. no_longer_eligible tiene un reason: requested (el cliente pidió financiarla), cancelled, removed (ya no está en los libros del cliente), left_programme, not_shared (el cliente dejó de compartir) o rules (ya no cumple sus reglas).
digest lleva los totales: cuántos clientes comparten y cuántos aún no, lo que es elegible hoy, lo que es nuevo y lo que ha cambiado. stale es true cuando la lectura nocturna no terminó: esa mañana no se comparó nada. Un resumen es una lista que calculó la base de datos, no una oferta: una solicitud se comprueba de nuevo cuando se hace, y usted decide sobre ella como siempre. El webhook opportunities.daily avisa cuando hay un resumen con algo dentro.
curl -s "$BASE/v1/opportunities?date=2026-10-07" \
-H "Authorization: Bearer $ADVANTA_KEY"{
"funder": { "bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3", "name": "Example Funder" },
"date": "2026-10-07",
"digest": {
"digest_id": "9b2d4c1e-0f3a-4e5b-8c6d-7a8b9c0d1e2f",
"date": "2026-10-07",
"stale": false,
"snapshot_at": "2026-10-07T03:30:12Z",
"clients": { "sharing": 9, "not_sharing": 1 },
"eligible": { "count": 42, "total": 318450.00 },
"new": { "count": 6, "total": 41200.00 },
"changes": { "paid": 2, "disputed": 0, "no_longer_eligible": 1 },
"currency": "EUR",
"lines": "/v1/opportunities?date=2026-10-07"
},
"lines": [
{
"kind": "new",
"reason": null,
"invoice_id": "0c5e7f3a-2b4d-4c6e-9f81-3a5b7c9d1e2f",
"number": "FV 2026/1184",
"debtor": { "name": "Example Buyer, S.A.", "tax_id": "A00000000", "country": "ES" },
"amount": 12400.00,
"currency": "EUR",
"due_date": "2026-12-15",
"client": { "seller_id": "2f6d8a4e-1b3c-4d5e-9f70-8a1b2c3d4e5f", "name": "Example Seller, S.L.", "tax_id": "B00000000", "sector": "C", "grade": "B", "size_band": "small" }
}
]
}Registre los endpoints que reciben los webhooks, rote sus secretos, envíe una prueba y consulte el registro de entregas.
/v1/webhooksSus endpoints activos, sin sus secretos, y los tipos de evento a los que puede suscribirse. Una clave de sandbox solo ve los endpoints que creó.
curl -s "$BASE/v1/webhooks" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/webhooksRegistrar un endpoint. La respuesta trae su secreto de firma, que no se vuelve a mostrar.
| Nombre | En | Descripción |
|---|---|---|
url obligatorio | body | https en un nombre de host público, puerto 443, sin usuario ni contraseña; como máximo 2.048 caracteres. Se rechazan las direcciones privadas, de loopback y link-local, y las redirecciones nunca se siguen. |
events | body | Una lista de tipos de evento, o ["*"] para todos (por defecto). |
description | body | Hasta 200 caracteres. |
Como máximo 10 endpoints activos.
curl -s -X POST "$BASE/v1/webhooks" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.example.com/advanta","events":["request.routed","notice.acknowledged","notice.disputed","request.funded","settlement.recorded"],"description":"Credit desk"}'const res = await fetch(`${BASE}/v1/webhooks`, {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify({
url: 'https://hooks.example.com/advanta',
events: ['request.routed', 'notice.acknowledged', 'notice.disputed', 'request.funded', 'settlement.recorded'],
description: 'Credit desk',
}),
});
const body = await res.json();
if (res.status !== 201) throw new Error(`${res.status} ${body.error.code}: ${body.error.message}`);
// The secret is shown once: store it now, in your own secret store.
await secretStore.put(`advanta-webhook-${body.webhook.id}`, body.secret);{
"webhook": {
"id": "e3b1c2d4-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
"url": "https://hooks.example.com/advanta",
"description": "Credit desk",
"events": ["notice.acknowledged", "notice.disputed", "request.funded", "request.routed", "settlement.recorded"],
"active": true,
"secret_prefix": "whsec_1a2b3c",
"created_via": "api"
},
"secret": "whsec_…",
"signature": { "header": "Advanta-Signature", "scheme": "HMAC-SHA256 of \"<t>.<raw body>\"", "tolerance_seconds": 300 }
}/v1/webhooks/{id}Detener un endpoint. Las entregas aún pendientes se cancelan y sus secretos se borran.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id del endpoint. |
curl -s -X DELETE "$BASE/v1/webhooks/$WEBHOOK_ID" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/webhooks/{id}/rotate-secretUn nuevo secreto de firma, que se muestra una sola vez. El secreto anterior sigue firmando, como segundo v1 en la cabecera, durante keep_previous_hours, para que pueda cambiar sin perder eventos.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id del endpoint. |
keep_previous_hours | body | De 0 a 72, 24 por defecto. |
curl -s -X POST "$BASE/v1/webhooks/$WEBHOOK_ID/rotate-secret" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"keep_previous_hours":24}'/v1/webhooks/{id}/testPoner en cola un evento webhook.test para este endpoint. La siguiente ejecución del despachador lo entrega, en torno a un minuto.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id del endpoint. |
curl -s -X POST "$BASE/v1/webhooks/$WEBHOOK_ID/test" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/webhooks/{id}/deliveriesEl registro de entregas de un endpoint, de la más reciente a la más antigua: estado (pending, delivered, failed o cancelled), intentos, código de respuesta, último error, próximo intento y el SHA-256 del cuerpo exacto enviado.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id del endpoint. |
limit | query | De 1 a 200, 50 por defecto. |
curl -s "$BASE/v1/webhooks/$WEBHOOK_ID/deliveries?limit=20" \
-H "Authorization: Bearer $ADVANTA_KEY"Desde su propio producto, entregue a un proveedor un enlace de alta de Advanta de un solo uso; el proveedor vuelve a usted con un estado firmado cuando termina.
/v1/onboarding-linksUn enlace de alta de un solo uso para uno de sus proveedores, atribuido a usted. Advanta no envía ningún correo: entregue la url a su proveedor. Cuando el proveedor haya enviado la verificación de su empresa, usted recibe onboarding.completed, y el proveedor vuelve a su return_url con un estado firmado.
| Nombre | En | Descripción |
|---|---|---|
company_vat obligatorio | body | El NIF o número de IVA del proveedor, con o sin el prefijo del país. |
country obligatorio | body | ISO 3166 alfa-2. |
contact_email obligatorio | body | El correo del contacto del proveedor. |
return_url obligatorio | body | https, hasta 2.048 caracteres, en un origen de su lista de orígenes de vuelta. Esa lista se mantiene en la configuración del portal o la mantiene Advanta, nunca por esta API. |
company_name | body | De 2 a 200 caracteres. Puede omitirse para un número de IVA de la UE que VIES sepa nombrar. |
contact_name | body | Hasta 120 caracteres. |
metadata | body | Sus propias claves y valores: como mucho 20 claves, valores de texto, número, true, false o null, 2 KB de JSON. Se devuelven en el enlace y en onboarding.completed. |
locale | body | El idioma del alta: pt, es, en, fr, de, it o nl. |
valid_days | body | De 1 a 30, 14 por defecto. |
La respuesta trae return_secret (ors_ seguido de 64 caracteres hexadecimales), que se muestra una sola vez: guárdelo ya. Solo se guarda el SHA-256 del token del enlace. Un enlace creado con una clave de sandbox registra al proveedor como empresa de prueba en el plano de demostración.
Cuando el proveedor vuelve, la return_url lleva advanta_onboarding (el id del enlace), advanta_status (completed), advanta_ts (segundos Unix) y advanta_sig: el HMAC-SHA256 en hexadecimal de <advanta_onboarding>.<advanta_status>.<advanta_ts>, con su return_secret como clave. Verifíquelo antes de que su página se fíe del estado y rechace una vuelta a más de 600 segundos de su reloj; el último ejemplo de abajo hace ambas cosas.
curl -s -X POST "$BASE/v1/onboarding-links" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"company_vat":"PT500000000","country":"PT","contact_email":"ana@fornecedor.example","contact_name":"Ana Sousa","company_name":"Fornecedor Exemplo, Lda.","return_url":"https://portal.example.com/onboarding/done","metadata":{"supplier_ref":"S-42"},"locale":"pt"}'{
"onboarding_link": {
"id": "c2d4e6f8-1a3b-4c5d-8e7f-9a0b1c2d3e4f",
"status": "pending",
"company_name": "Fornecedor Exemplo, Lda.",
"country": "PT",
"return_url": "https://portal.example.com/onboarding/done",
"metadata": { "supplier_ref": "S-42" },
"expires_at": "2026-10-10T10:00:00Z",
"completed_at": null,
"seller_id": null
},
"url": "https://app.advanta.capital/accept-invite?invitation=…&lang=pt",
"expires_at": "2026-10-10T10:00:00Z",
"environment": "sandbox",
"return_secret": "ors_…",
"return": {
"parameters": ["advanta_onboarding", "advanta_status", "advanta_ts", "advanta_sig"],
"signature": "hex HMAC-SHA256(return_secret, \"<advanta_onboarding>.<advanta_status>.<advanta_ts>\")"
}
}import crypto from 'node:crypto';
// On the page behind your return_url.
// url: the full address the supplier came back to
// returnSecret: the "ors_…" string POST /v1/onboarding-links returned, stored when you made the link
export function verifyAdvantaReturn(url, returnSecret, nowSeconds = Math.floor(Date.now() / 1000)) {
const q = new URL(url).searchParams;
const id = q.get('advanta_onboarding') ?? '';
const status = q.get('advanta_status') ?? '';
const ts = q.get('advanta_ts') ?? '';
const sig = q.get('advanta_sig') ?? '';
if (!id || !status || !/^[0-9]{1,12}$/.test(ts) || !/^[0-9a-f]{64}$/.test(sig)) return null;
if (Math.abs(nowSeconds - Number(ts)) > 600) return null; // too old: ask your back end instead
const expected = crypto.createHmac('sha256', returnSecret).update(`${id}.${status}.${ts}`).digest();
if (!crypto.timingSafeEqual(Buffer.from(sig, 'hex'), expected)) return null;
return { onboardingLinkId: id, status }; // status is "completed"
}/v1/onboarding-linksSus enlaces de alta, los más recientes primero, cada uno con su status: pending, account_created, completed, expired o revoked. Una clave de sandbox ve los enlaces que creó.
| Nombre | En | Descripción |
|---|---|---|
limit | query | De 1 a 200, 50 por defecto. |
curl -s "$BASE/v1/onboarding-links?limit=20" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/onboarding-links/{id}Un enlace de alta y en qué punto está el proveedor. Una vez completado, seller_id es el id que usa GET /v1/seller-limits.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id del enlace. |
curl -s "$BASE/v1/onboarding-links/$ONBOARDING_ID" \
-H "Authorization: Bearer $ADVANTA_KEY"Llévese todo lo que puede ver en Advanta, cuando quiera, sin pedirlo: su derecho de salida (DORA art. 28.8 y art. 30.3.f). Un ZIP con un CSV y un archivo JSON Lines por entidad, schema.json, manifest.json con el SHA-256 de cada archivo, un README en su idioma y verify.py.
/v1/exportsInicia una exportación de todo lo que su financiador puede ver: solicitudes y su historial, ofertas, facturas con su verificación, vendedores (datos de la empresa, el resumen KYC que puede ver, la verificación del representante), deudores, notificaciones con las respuestas de los deudores y los datos de los certificados, las entradas de la cadena de evidencia sobre sus operaciones con los hashes y las raíces diarias para verificarlas, liquidaciones y extractos, rechazos de los controles, sus reglas y límites, su equipo, endpoints de webhook (nunca un secreto), claves de API (nunca una clave), su registro de auditoría y sus documentos. Se genera en segundo plano, normalmente en menos de un minuto; export.ready avisa cuando está.
| Nombre | En | Descripción |
|---|---|---|
lang | body | El idioma del README: pt, es, en, fr, de, it o nl (en por defecto). |
Solo una clave de producción: una clave de sandbox responde 403 export_live_key_required (el financiador de demostración es compartido). Una exportación cada vez, como máximo 10 en 24 horas. La misma exportación está en la página Exportación del portal, en los ajustes.
curl -s -X POST "$BASE/v1/exports" \
-H "Authorization: Bearer $ADVANTA_KEY" \
-H "Content-Type: application/json" \
-d '{"lang":"es"}'{
"funder": { "bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3", "name": "Example Funder" },
"export": {
"id": "5e1f0a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b",
"subject": "funder",
"status": "queued",
"plane": "live",
"requested_via": "api",
"actor_role": "api:treasury",
"lang": "es",
"created_at": "2026-09-27T09:00:02.114000Z",
"download_available": false,
"manifest_sha256": null,
"progress": { "entities_done": 0, "entities_total": 47, "rows": 0, "volumes_written": 0, "phase": "data" }
}
}/v1/exportsSus exportaciones, del portal y de la API, las más recientes primero, con su estado, su tamaño y manifest_sha256.
| Nombre | En | Descripción |
|---|---|---|
limit | query | De 1 a 200, 50 por defecto. |
curl -s "$BASE/v1/exports?limit=20" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/exports/{id}Una exportación. Mientras se genera: status queued o running, con progress. Cuando está ready, y durante 24 horas: files, cada volumen con un enlace válido como máximo una hora (nunca más allá de esas 24 horas). Vuelva a pedirla para tener enlaces nuevos; cada llamada que devuelve enlaces queda registrada. A las 24 horas los archivos se borran y el registro se conserva.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la exportación, de POST /v1/exports o GET /v1/exports. |
manifest_sha256 es el SHA-256 del manifest.json escrito sin ese campo, con las claves ordenadas y sin espacios. Advanta registró el mismo valor en la cadena de evidencia (entrada export.ready); verify.py lo recalcula y comprueba cada archivo y las entradas de evidencia.
curl -s "$BASE/v1/exports/5e1f0a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b" \
-H "Authorization: Bearer $ADVANTA_KEY"{
"funder": { "bank_id": "6d164c92-02cc-4f9a-ae8d-3f7f5ef043d3", "name": "Example Funder" },
"export": {
"id": "5e1f0a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b",
"status": "ready",
"completed_at": "2026-09-27T09:00:41.502000Z",
"expires_at": "2026-09-28T09:00:41.502000Z",
"download_available": true,
"manifest_sha256": "1c822b8797ba58903eca0689cc0c93138e7d396e01a038d133b5c1f3aeec7497",
"size_bytes": 482113,
"file_count": 101,
"documents_mode": "files",
"row_counts": { "requests": 212, "invoices": 1480, "evidence_entries": 903 }
},
"files": [
{
"name": "advanta-export-2026-09-27-5e1f0a2b-v001.zip",
"bytes": 482113,
"sha256": "9b0e5c1d2a7f4e6b8c3d1a0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4b3a291807",
"url": "https://…/object/sign/data-exports/…",
"url_expires_at": "2026-09-27T10:00:41.502000Z"
}
]
}# Every volume into one folder, then the checker the export carries
curl -s "$BASE/v1/exports/$EXPORT_ID" -H "Authorization: Bearer $ADVANTA_KEY" \
| jq -r '.files[].url' | while read -r u; do curl -s -o "v$((++n)).zip" "$u"; done
for z in v*.zip; do unzip -q -o "$z" -d export; done
python3 export/advanta-export-*/verify.py # files, manifest digest and evidence chain/v1/exports/{id}/documentsCuando los documentos eran demasiado grandes para incluirlos (documents_mode links): cada documento de la exportación con un enlace válido durante 15 minutos, una página cada vez. La lista se calcula cuando la pide, así que un documento que ya no puede leer no aparece.
| Nombre | En | Descripción |
|---|---|---|
id obligatorio | path | El id de la exportación. |
after | query | El next_after de la página anterior. |
limit | query | De 1 a 200, 100 por defecto. |
curl -s "$BASE/v1/exports/5e1f0a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b/documents?limit=100" \
-H "Authorization: Bearer $ADVANTA_KEY"Registre un endpoint HTTPS y Advanta le envía un POST firmado cuando ocurre algo que le concierne: en una solicitud enviada a usted o en su cedente, o en un enlace de alta que creó. Cada endpoint se suscribe a los tipos de evento que necesita. Cada envío va firmado y, si falla, se reintenta durante 24 horas.
| Evento | Cuándo | data |
|---|---|---|
request.routed | Las operaciones de Advanta le han enviado una solicitud. Ya puede leerla y decidir. | request_id, request_ref, type, status, total_amount, currency, routed_at |
request.unrouted | Una solicitud enviada a usted se ha enviado a otro financiador o ha dejado de estar asignada. Ya no puede actuar sobre ella. | request_id, request_ref, unrouted_at |
offer.accepted | Su oferta ha sido aceptada (request_status es approved cuando el cedente ha aceptado). Puede financiarla. | offer_id, request_id, request_ref, request_status, rate, advance_pct, days, accepted_at |
notice.acknowledged | Un deudor ha confirmado la notificación de cesión. Un evento por deudor; channel es online u offline. | notice_id, request_id, request_ref, debtor_name, debtor_tax_id, invoice_count, total_amount, channel, decided_at |
notice.disputed | Un deudor ha rechazado la notificación de cesión. Un evento por deudor. | Los campos de notice.acknowledged, más reason: las palabras del deudor, como máximo 500 caracteres. |
request.funded | Una solicitud enviada a usted se ha financiado. | Los campos de la solicitud de request.routed, más funded_at y advance_amount. |
settlement.recorded | Se ha registrado dinero recibido en una solicitud financiada, parcial o final: el pago que liquida la solicitud lleva final a true. | settlement_id, request_id, request_ref, amount, received_at, reference, received_total, request_total, outstanding, final, request_status |
seller.documents_expiring | Un documento con fecha de validez (por ejemplo, un certificado de Hacienda o de la Seguridad Social) de un cedente con una solicitud abierta o financiada enviada a usted caduca dentro de 30 días, de 7 días o hoy. Se comprueba cada día; threshold_days es 30, 7 o 0. | seller_id, company_name, company_tax_id, document_id, document_type, valid_until, days_left, threshold_days, request_ids |
dispute.opened | Un deudor ha impugnado facturas de una solicitud enviada a usted, después de la aprobación o de la financiación. reason es goods_not_received, defective, amount_incorrect, already_paid, not_our_invoice u other; channel es cession_page, letter o email. | dispute_id, request_id, request_ref, notice_id, debtor_name, debtor_tax_id, invoice_numbers, reason, description, amount_disputed, channel, reported_by, received_on, request_status, status |
dispute.resolved | Las operaciones de Advanta han cerrado una impugnación; status es resolved_for_debtor, resolved_for_seller o withdrawn. | Los campos de dispute.opened, con su status, más resolved_at y resolution_note. |
onboarding.completed | Un proveedor al que invitó con un enlace de alta ha enviado la verificación de su empresa. status es completed; metadata es la suya, tal como la envió. Para un enlace creado con una clave de sandbox, solo lo reciben los endpoints de esa clave. | onboarding_link_id, status, company_name, company_tax_id, country, seller_id, account_created_at, completed_at, verification_status, metadata |
client.joined | Una empresa que invitó (por nombre, con su enlace abierto, con el enlace de un prescriptor o por la API) aceptó la invitación y queda solo con usted: sus solicitudes le llegan solo a usted. origin indica cómo llegó (named, open_link, prescriber o api), con el prescriptor cuando lo hay. | seller_id, invitation_id, company_name, company_tax_id, country, origin, channel, link_id, prescriber_id, prescriber_name, arrived_at, joined_at, mode |
export.ready | Una exportación que pidió (portal o API) está lista: descárguela con GET /v1/exports/{id} en las 24 horas siguientes. Lleva su manifest_sha256, nunca un enlace. | export_id, status, requested_via, manifest_sha256, size_bytes, file_count, documents_mode, volumes, completed_at, expires_at |
request.announced | Se ha anunciado una solicitud confidencial enviada a usted: por usted, por las operaciones de Advanta o por un disparador que activó (trigger es manual, overdue, dispute o kyc_lapsed). Sus notificaciones preparadas se están enviando; notices lista cada una con el SHA-256 de su documento. | request_id, request_ref, trigger, reason, status, notices, announced_at |
recourse.opened | Una solicitud suya financiada no está liquidada recourse_days después del vencimiento de una factura: una reclamación de recurso contra el cedente (kind recourse) o un impago del deudor (kind debtor_default). | claim_id, request_id, request_ref, kind, claim_amount, funded_amount, fee_amount, collected_before, first_due_date, days_after_due, invoice_ids, pay_reference |
recourse.settled | Se ha liquidado una reclamación: por los pagos que usted registró desde que se abrió (via statement o manual; la solicitud se cierra como liquidada por recurso), o porque la solicitud se liquidó de la forma habitual (via request_settled, sin paid). | claim_id, request_id, request_ref, kind, claim_amount, paid, via, request_closed |
payment.reached_seller | En una cuenta que el cedente comparte con usted ha entrado un pago de un deudor de una solicitud que usted financió en términos confidenciales: la referencia lleva el número de una factura financiada (match_rule invoice_reference), o el pagador y el importe coinciden (payer_and_amount). | alert_id, request_id, invoice_ids, payer_name, payer_iban, amount, currency, booking_date, match_rule, confidence |
opportunities.daily | El resumen de la mañana trae algo: facturas de sus propios clientes que han pasado a ser elegibles desde el resumen anterior, o un cambio en las que ya se le mostraron. Solo un sumario, recuentos y totales, nunca una factura, un deudor ni un cliente: lea las líneas con GET /v1/opportunities?date= (lines). Como máximo uno al día; ninguno un día sin nada nuevo ni ningún cambio. | digest_id, date, stale, snapshot_at, clients (sharing, not_sharing), eligible (count, total), new (count, total), changes (paid, disputed, no_longer_eligible), currency, lines |
debtor.watch_blocked | Un boletín oficial (el BORME para las empresas españolas, Citius para las portuguesas) publicó un acto que bloquea para nueva financiación a un deudor de una solicitud que usted financió: concurso declarado o en curso, liquidación, conclusión del concurso por insuficiencia de masa, disolución, extinción, o cierre de la hoja registral por la Agencia Tributaria o tras un concurso. Mientras se mantenga, no va ninguna oferta ni financiación nueva a las facturas de este deudor. Un evento por solicitud y por cada paso a bloqueado. Es lo que publicó el boletín, para que usted lo revise, no una conclusión jurídica; solo se vigilan empresas de España y Portugal. | request_id, request_ref, debtor (country, tax_id, name), status, note, events (kind, published_on, source, url), detected_at |
pre_offer.accepted | Un cliente ha pedido la financiación de las facturas de una propuesta previa que usted le envió desde sus oportunidades de la mañana: su solicitud, hecha con todas las comprobaciones habituales, lleva la propuesta previa y le llega como siempre (request.routed), y su regla de crédito prepara su oferta desde su tabla. terms es lo que su tabla dio cuando la envió, orientativo: el precio es suyo, Advanta no indica ninguno. Una vez por propuesta previa. | pre_offer_id, request_id, request_ref, seller_id, company_name, company_tax_id, invoice_ids, invoice_count, total_amount, currency, terms, sent_at, valid_until, accepted_at |
webhook.test | El evento de prueba que pidió con POST /v1/webhooks/{id}/test. |
Cada entrega es un POST con un cuerpo JSON, enviado byte a byte tal como está guardado (su SHA-256 está en el registro de entregas), con tres cabeceras propias:
Advanta-Signature: t=<unix seconds>,v1=<hex>, ver Verificar firmas.Advanta-Event-Id: el id del evento, también id en el cuerpo.Advanta-Event-Type: el tipo de evento, también type en el cuerpo.POST /advanta HTTP/1.1
Host: hooks.example.com
Content-Type: application/json
Advanta-Signature: t=1790179835,v1=5f2b…
Advanta-Event-Id: 9b2f7f64-5a1c-4a57-9d8a-0f2e3c4b5a69
Advanta-Event-Type: request.funded{
"id": "9b2f7f64-5a1c-4a57-9d8a-0f2e3c4b5a69",
"object": "event",
"type": "request.funded",
"api_version": "2026-09-23",
"created": 1790179835,
"environment": "sandbox",
"data": {
"request_id": "4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87",
"request_ref": "FR-2026-0042",
"type": "factoring",
"status": "funded",
"total_amount": 18450.00,
"currency": "EUR",
"funded_at": "2026-09-23T18:10:35Z",
"advance_amount": 16605.00
}
}| Campo | Significado |
|---|---|
id | El id del evento, igual que Advanta-Event-Id. |
object | Siempre event. |
type | Uno de los tipos de evento de arriba. |
api_version | La revisión de la API en la que está escrito el evento. |
created | Cuándo se creó el evento, en segundos Unix. |
environment | live, sandbox o unclassified, como en GET /v1/me. |
data | Los campos del evento, indicados arriba. |
2xx en 10 segundos y el evento queda entregado. Cualquier otra respuesta, ninguna respuesta en 10 segundos o una redirección es un fallo; las redirecciones nunca se siguen.failed y permanece en el registro de entregas.Advanta-Event-Id que ya ha procesado e ignore una repetición.GET /v1/webhooks/{id}/deliveries muestra el estado, los intentos, el código de respuesta, el último error y el próximo intento de cada entrega. POST /v1/webhooks/{id}/test envía un evento webhook.test cuando quiera comprobar su endpoint.https en un nombre de host público, en el puerto 443, sin usuario ni contraseña. Se rechazan las direcciones privadas, de loopback y link-local.["*"] para todos (por defecto).whsec_ seguido de 64 caracteres hexadecimales) se devuelve una sola vez: cuando se crea el endpoint y, de nuevo, cada vez que lo rota. Guárdelo como guardaría una contraseña.POST /v1/webhooks/{id}/rotate-secret. El secreto anterior sigue firmando, como segundo v1 en la cabecera, durante keep_previous_hours (de 0 a 72, 24 por defecto). Despliegue el nuevo secreto dentro de ese plazo y no se pierde ningún evento.Cada entrega lleva Advanta-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256>. Compruébela antes de fiarse del cuerpo:
<t>.<raw body>, con el secreto del endpoint como clave (la cadena whsec_… completa, en UTF-8), y codifíquelo en hexadecimal.v1 de la cabecera coincide, comparado en tiempo constante (tras una rotación hay dos), y si t está a menos de 300 segundos de su reloj. Si no, recháchela.Una entrega rechazada no responde 2xx, así que Advanta la reintenta como cualquier otro fallo.
import crypto from 'node:crypto';
import express from 'express';
const TOLERANCE_SECONDS = 300;
// header: the Advanta-Signature value
// rawBody: the request body as a Buffer, exactly as received (before any JSON parsing)
// secret: your endpoint secret, the whole "whsec_…" string
export function verifyAdvantaSignature(header, rawBody, secret, nowSeconds = Math.floor(Date.now() / 1000)) {
let t = null;
const signatures = [];
for (const part of String(header ?? '').split(',')) {
const i = part.indexOf('=');
if (i <= 0) continue;
const key = part.slice(0, i).trim();
const value = part.slice(i + 1).trim();
if (key === 't' && /^[0-9]{1,12}$/.test(value)) t = Number(value);
else if (key === 'v1' && /^[0-9a-f]{64}$/.test(value)) signatures.push(value);
}
if (t === null || signatures.length === 0) return false;
if (Math.abs(nowSeconds - t) > TOLERANCE_SECONDS) return false; // replay window
const expected = crypto.createHmac('sha256', secret).update(`${t}.`).update(rawBody).digest();
// After a rotation the header carries two v1 values: accept either.
return signatures.some((sig) => crypto.timingSafeEqual(Buffer.from(sig, 'hex'), expected));
}
// Express: keep the body raw on this route.
const app = express();
app.post('/advanta', express.raw({ type: '*/*' }), (req, res) => {
if (!verifyAdvantaSignature(req.get('Advanta-Signature'), req.body, process.env.ADVANTA_WEBHOOK_SECRET)) {
return res.status(400).end();
}
const event = JSON.parse(req.body.toString('utf8'));
// Delivery is at least once: skip an event.id you already processed, then queue the work.
res.status(200).end();
});import hashlib
import hmac
import json
import os
import re
import time
from flask import Flask, request
TOLERANCE_SECONDS = 300
def verify_advanta_signature(header, raw_body, secret, now=None):
"""header: the Advanta-Signature value; raw_body: the request body as bytes, exactly
as received; secret: your endpoint secret, the whole "whsec_..." string."""
t = None
signatures = []
for part in (header or "").split(","):
key, sep, value = part.partition("=")
key, value = key.strip(), value.strip()
if not sep:
continue
if key == "t" and re.fullmatch(r"[0-9]{1,12}", value):
t = int(value)
elif key == "v1" and re.fullmatch(r"[0-9a-f]{64}", value):
signatures.append(value)
if t is None or not signatures:
return False
now = int(time.time()) if now is None else now
if abs(now - t) > TOLERANCE_SECONDS: # replay window
return False
expected = hmac.new(secret.encode("utf-8"), f"{t}.".encode("ascii") + raw_body, hashlib.sha256).hexdigest()
# After a rotation the header carries two v1 values: accept either.
return any(hmac.compare_digest(sig, expected) for sig in signatures)
# Flask
app = Flask(__name__)
@app.post("/advanta")
def advanta_webhook():
raw = request.get_data() # the raw bytes; do not read request.json before verifying
if not verify_advanta_signature(request.headers.get("Advanta-Signature"), raw, os.environ["ADVANTA_WEBHOOK_SECRET"]):
return "", 400
event = json.loads(raw)
# Delivery is at least once: skip an event["id"] you already processed, then queue the work.
return "", 200Cada error es JSON, con un code estable y un message para personas. Decida por el código, nunca por el mensaje.
{
"error": {
"code": "not_routed_to_you",
"message": "This request is not assigned to your institution. Advanta operations routes requests."
}
}| Estado | Códigos | Significado |
|---|---|---|
| 400 | reason_required | Un rechazo sin reason ni notes. |
| 401 | unauthorized, key_expired | unauthorized: la clave falta, está mal formada, es desconocida, se ha revocado o está inactiva. key_expired: la clave ha caducado. |
| 403 | forbidden, not_your_request, export_live_key_required, not_routed_to_you, not_your_claim | forbidden: la clave no tiene el ámbito, o el financiador no está activo. not_your_request: una liquidación de un financiador que no es el de la solicitud. export_live_key_required: una clave de sandbox no exporta. not_routed_to_you: anunciar una solicitud que no está enviada a usted. not_your_claim: cerrar una reclamación de recurso que no es de una solicitud suya. |
| 404 | not_found | Ningún recurso visible para esta clave, o una ruta desconocida. |
| 405 | method_not_allowed | El método no se admite en esta ruta. |
| 409 | not_routed_to_you, invalid_state, credit_limit, funding_gate_failed, funding_amount_mismatch, debtor_not_eligible_for_funder, documents_missing_for_funder, level_lower, notice_already_decided, not_factoring, request_not_in_flight, statement_already_imported, too_many_endpoints, prescriber_exists, link_exists, company_already_registered, email_has_account, invitation_pending_exists, country_not_served, export_in_progress, export_not_ready, export_failed | Una escritura que la solicitud no permite: no está enviada a usted, el estado no es el adecuado, supera uno de sus límites, una notificación de factoring aún sin confirmar, un deudor fuera de su lista, un documento exigido al cedente que falta o no está vigente, o un nivel de consentimiento que bajaría, llega después de que un deudor respondiera, o se refiere a una solicitud que no es de factoring o no está en curso. También un extracto ya importado, más de 10 endpoints activos, un nombre de prescriptor que ya usa, un enlace que sigue funcionando (envíe replace: true), y un enlace de alta para una empresa o un contacto que ya tiene cuenta o una invitación pendiente, o en un país del que Advanta aún no acepta cedentes. Una exportación todavía se está generando (export_in_progress, export_not_ready) o falló (export_failed). |
| 410 | export_expired | export_expired: los archivos de la exportación se podían descargar durante 24 horas; inicie una nueva exportación. |
| 413 | file_too_large, too_many_lines, too_many_rows | El extracto supera 4 MiB o tiene más de 5.000 movimientos, o una importación de límites tiene más de 2.000 filas (too_many_rows). |
| 422 | invalid_terms, invalid_amount, invalid_received_at, invalid_funding_details, step_back_message_required, invalid_decision, level_invalid, invalid_flag, reason_required, debtor_tax_id_required, seller_id_required, invalid_limit, tax_id_required, file_required, file_unreadable, file_empty, statement_unreadable, statement_has_no_transactions, line_invalid, country_invalid, codes_invalid, note_invalid, country_without_catalogue, document_code_unknown, body_required, url_required, url_invalid, url_too_long, url_must_be_https, url_has_credentials, url_port_not_allowed, url_host_not_allowed, url_not_allowed, events_invalid, unknown_event_type, invalid_description, invalid_keep_previous_hours, body_invalid, name_required, name_invalid, email_invalid, email_not_reserved, notes_too_long, lang_invalid, prescriber_id_invalid, expires_at_invalid, replace_invalid, reason_invalid, company_vat_invalid, contact_email_invalid, contact_name_invalid, company_name_invalid, company_name_required, return_url_invalid, return_url_not_allowed, metadata_invalid, locale_invalid, valid_days_invalid, prescriber_not_found, country_not_served, seller_id_invalid, terms_invalid, terms_key_unknown, seller_not_in_programme, already_announced, request_closed, status_invalid, close_invalid, claim_closed, rows_required, invalid_source, source_ref_invalid, source_ref_too_long, invalid_date | Un campo o parámetro falta o no es válido; el código indica cuál. (Un rechazo sin motivo es 400 reason_required; un cambio de configuración o de nivel sin motivo es 422 reason_required.) También un cambio de términos para una empresa fuera de su programa (seller_not_in_programme), una solicitud ya anunciada o cerrada (already_announced, request_closed), y una reclamación de recurso que ya no está abierta o se cierra de forma equivocada (claim_closed, close_invalid). También se rechaza una importación de límites sin filas (rows_required), con un source que no es import ni insurer (invalid_source) o con un source_ref que no es texto o tiene más de 200 caracteres (source_ref_invalid, source_ref_too_long), así como una date de las oportunidades que no es un día del calendario (invalid_date). |
| 429 | rate_limited, export_rate_limited | rate_limited: más llamadas que el límite de la clave (120 por minuto y 3.000 por hora, salvo que Advanta haya fijado otro para la clave), o llamadas repetidas con una clave desconocida desde una misma dirección; vuelva a enviarla pasados Retry-After segundos. export_rate_limited: como máximo 10 exportaciones en 24 horas. |
| 500 | internal, query_failed, write_failed, ingest_failed | Algo ha fallado en Advanta. Reintente más tarde. |
debtor_not_eligible_for_funderCuando solo acepta compradores de su lista, una oferta sobre una solicitud con un deudor fuera de la lista responde 409 con los deudores que la bloquean, cada uno con un reason:
{
"error": {
"code": "debtor_not_eligible_for_funder",
"message": "…",
"debtors": [
{
"debtor_key": "A00000000",
"name": "Example Buyer, S.A.",
"country": "ES",
"reason": "not_listed",
"invoices": 2
}
]
}
}| reason | Significado |
|---|---|
not_listed | El deudor no está en su lista. |
refused | Su límite para el deudor está como rechazado. |
suspended | Su límite para el deudor está suspendido. |
no_tax_id | Una factura no tiene el NIF del comprador. |
invoice_missing | Una línea de la solicitud no tiene factura. |
no_invoices | La solicitud no tiene facturas. |
documents_missing_for_funderCuando un documento que exige al cedente falta, no está verificado o no está vigente, una oferta o una financiación responde 409 con los documentos que la bloquean, cada uno con un reason:
{
"error": {
"code": "documents_missing_for_funder",
"message": "…",
"documents": [
{
"code": "cert_seguridad_social",
"name": "…",
"reason": "expired",
"valid_until": "2026-09-15",
"document_id": "5b7c9d1e-3f2a-4b6c-8d0e-1a2b3c4d5e6f"
}
]
}
}| reason | Significado |
|---|---|
missing | El cedente no ha aportado el documento. |
unverified | Advanta aún no lo ha verificado. |
expired | Ya no está vigente en esa fecha. |
rejected | Advanta lo ha rechazado. |
no_validity_date | No tiene fecha de validez. |
not_in_catalogue | El código no está en el catálogo del país del cedente. |
La ruta lleva la versión principal, /v1. Dentro de la v1 pueden añadirse campos y tipos de evento: ignore lo que no conozca.
api_version, en GET /v1/me y en cada evento de webhook, indica la revisión que está leyendo: hoy, 2026-09-23.
Cada clave puede hacer 120 llamadas por minuto y 3.000 por hora, contadas en todos los servidores de Advanta (las operaciones de Advanta pueden fijar otro límite para una clave). Una llamada por encima del límite recibe 429 rate_limited, con una cabecera Retry-After en segundos y retry_after_seconds, limit y window_seconds en el error: no se hizo nada de lo que pedía, así que vuelva a enviarla pasado ese tiempo. Las llamadas repetidas con una clave desconocida o mal formada desde una misma dirección también reciben 429. GET /v1/health no tiene límite, y las exportaciones mantienen su propio límite (export_rate_limited).
Todo lo que hay en esta página está descrito en openapi.yaml (OpenAPI 3.1). Dudas, o una clave: diogo@advanta.pt.