Advanta / Banques et financeurs / Développeurs

API financeur d’Advanta

Votre propre système lit les demandes de financement qu’Advanta vous adresse, envoie vos décisions, fixe ce que vous exigez avant de financer, gère vos limites, envoie votre relevé bancaire pour rapprochement, invite vos propres clients et fournisseurs et reçoit des webhooks signés quand quelque chose se passe. Chaque écriture a le même effet que la même action dans le portail financeur. Et il emporte toutes vos données, quand vous le voulez : votre droit de sortie.

  • OpenAPI 3.1
  • Version 2026-09-23
  • JSON sur HTTPS

Démarrage rapide

Une seule URL de base sert les clés live comme les clés sandbox : c’est la clé qui décide de ce que vous voyez.

URL de base
https://bzsengbmlzzhztjfvcag.supabase.co/functions/v1/funder-api
Authentification
Authorization: Bearer adv_fk_… à chaque appel : adv_fk_ suivi de 64 caractères hexadécimaux.
Format
JSON en entrée et en sortie. Un relevé bancaire peut aussi être envoyé tel quel, en fichier XML ou CSV.

Commencez par GET /v1/me : il indique à quel financeur appartient la clé, son environnement et ses portées. Listez ensuite les demandes qui vous sont adressées.

curl
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"
JavaScript
// 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 répond ainsi :

Réponse · GET /v1/me
{
  "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"
  }
}

Environnements et sandbox

Il n’y a qu’une URL de base. C’est la clé qui décide de l’environnement, et GET /v1/me le renvoie dans environment.

environmentLe financeurCe que voit la clé
liveClassé par Advanta comme réel ou pilote.Uniquement des clients réels.
sandboxUn financeur de démonstration.Uniquement des entreprises fictives, sur le plan de démonstration.
unclassifiedPas encore classé par Advanta.Aucune demande.

Une demande de l’autre plan n’est jamais visible, quelle que soit la clé.

Clés sandbox

  • Advanta émet une clé sandbox pour un prospect nommé (key.prospect dans GET /v1/me). Comme toute clé, elle n’est affichée qu’une fois et seul son SHA-256 est conservé.
  • Elle expire 1 à 90 jours après son émission (key.expires_at) ; ensuite, chaque appel répond 401 key_expired. Advanta peut aussi la révoquer à tout moment.
  • Elle ne voit que des entreprises fictives, sur le plan de démonstration. Ces données sont partagées avec d’autres démonstrations et reconstruites quand le scénario est réinitialisé : attendez-vous à ce qu’elles changent.
  • Elle lit les demandes, les paramètres, les limites, l’historique de paiement et vos clients (prescripteurs, liens, invitations et rapport), et gère ses propres endpoints de webhook et liens d’entrée en relation : elle ne voit que ceux qu’elle a créés. Un fournisseur invité avec une clé sandbox est enregistré comme entreprise de test sur le plan de démonstration.
  • Elle ne peut prendre de décisions (proposer, refuser, financer, régler), ajouter des prescripteurs et émettre des liens que si Advanta l’a activé sur la clé, ce qui ajoute la portée decisions:write. Les prescripteurs et les liens du financeur de démonstration sont partagés par toutes les démonstrations.

Vous pouvez avoir une clé sandbox dès aujourd’hui : votre propre système face à nos données de démonstration, avant tout contrat. Écrivez à diogo@advanta.pt. La clé réelle est émise le jour où vous voulez vous connecter.

Authentification et portées

Chaque appel porte Authorization: Bearer adv_fk_<64 hex>. Les clés sont émises par les opérations d’Advanta et appartiennent à un financeur. Une clé n’est affichée qu’une fois, seul son SHA-256 est conservé, et elle peut expirer.

Chaque clé porte des portées. Un appel pour lequel la clé n’a pas la portée répond 403 forbidden.

PortéeCe qu’elle permet
requests:readLire les demandes (GET /v1/requests, GET /v1/requests/{id} et ses documents). Elle lit aussi vos paramètres et les documents que vous exigez, les registres de limites, l’historique de paiement, vos clients (prescripteurs, liens, invitations et rapport), vos liens d’entrée en relation, vos endpoints de webhook et leurs journaux de livraison. Elle lit aussi les conditions de votre programme (GET /v1/programme), les réclamations de recours (GET /v1/recourse), vos données bancaires (GET /v1/bank-data), ainsi que les notifications d’une demande et le flux de trésorerie que son cédant partage avec vous.
limits:readLire les registres de limites (GET /v1/credit-limits, GET /v1/seller-limits) et l’historique de paiement.
limits:writeFixer, réviser ou refuser des limites (PUT /v1/credit-limits, PUT /v1/seller-limits).
decisions:writeProposer, refuser, financer et régler (POST /v1/requests/{id}/decision), et relever ce que les débiteurs d’une demande doivent signer (POST /v1/requests/{id}/consent-level). Elle permet aussi toutes les écritures sur les paramètres, les limites, les relevés, les clients, les liens d’entrée en relation et les endpoints de webhook, ainsi que la lecture des endpoints de webhook, des clients et des liens d’entrée en relation. Elle permet aussi d’exporter toutes vos données. Elle permet aussi d’annoncer une demande confidentielle (POST /v1/requests/{id}/announce), de clore une réclamation de recours (POST /v1/recourse/{id}/close) et de modifier les conditions de votre programme.
settings:writeModifier ce que vos débiteurs doivent signer avant que vous financiez (PUT /v1/settings) et les documents que vous exigez des cédants (PUT /v1/required-documents). Aussi les conditions de votre programme (PUT /v1/programme).
statements:writeEnvoyer un relevé bancaire (POST /v1/statements).
clients:writeGérer vos clients : ajouter et désactiver des prescripteurs (POST /v1/prescribers, POST /v1/prescribers/{id}/disable), émettre, remplacer et désactiver des liens (POST /v1/client-links, POST /v1/client-links/{id}/disable), et les lire, ainsi que les invitations et le rapport.
webhooks:writeGérer les endpoints de webhook : créer, arrêter, changer le secret, envoyer un test, et lire la liste et les journaux de livraison.
onboarding:writeCréer des liens d’entrée en relation pour vos fournisseurs (POST /v1/onboarding-links) et les lire.
exports:writeExporter toutes vos données (POST /v1/exports, GET /v1/exports, GET /v1/exports/{id} et ses documents). Clés de production uniquement.

Endpoints

Les chemins sont relatifs à l’URL de base. Tout appel peut répondre 401 (unauthorized ou key_expired), un appel qui exige une portée peut répondre 403 forbidden (la clé n’a pas la portée, ou le financeur n’est pas actif), et 500 signifie de réessayer plus tard. Ils ne sont pas répétés ci-dessous ; la section Erreurs liste tous les codes.

Votre clé

À quel financeur appartient une clé, son environnement et ses portées. Commencez ici.

GET/v1/health

Indique si l’API fonctionne. Publique : sans clé, sans données, sans accès à la base de données.

Portée
Aucune : publique, sans clé
Renvoie
200{ status, api_version, time }
Erreurs
Aucune

Advanta interroge cette route toutes les 5 minutes ; les résultats sont publiés sur la page d’état publique.

curl
curl -s "$BASE/v1/health"

GET/v1/me

Qui appelle : la clé, son financeur, son environnement et ses portées.

Portée
Toute clé valide
Renvoie
200{ api_version, environment, funder, key }
Erreurs
405method_not_allowed

key.prefix correspond aux 12 premiers caractères de la clé. key.expires_at vaut null pour une clé qui n’expire pas ; key.prospect indique à qui une clé sandbox a été émise.

curl
curl -s "$BASE/v1/me" \
  -H "Authorization: Bearer $ADVANTA_KEY"
Réponse · 200
{
  "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"
  }
}

Demandes et décisions

Lisez les demandes qu’Advanta vous a adressées, puis proposez, refusez, financez ou enregistrez un encaissement ; et exigez davantage des débiteurs d’une demande quand il le faut.

GET/v1/requests

Les demandes qui vous sont adressées (vous pouvez agir dessus) et celles sur lesquelles vous avez déjà agi (en lecture seule, même après une réaffectation), de la plus récente à la plus ancienne, chacune avec votre propre offre dans my_offer si vous en avez fait une.

NomOùDescription
statusqueryopen (par défaut : pending, submitted, under_review, terms_sent, accepted, approved), all, ou un seul statut.
limitqueryDe 1 à 200, 50 par défaut.
Portée
requests:read
Renvoie
200{ funder, count, requests[] }
Erreurs
Seulement les codes communs (401, 403, 500).

Une demande comporte id, request_ref, type (factoring ou confirming), status, total_amount, advance_amount, le cédant dans company_name et company_nif, invoice_count, assigned_bank_id, consent_level_required (ce que chaque débiteur doit signer avant qu’elle puisse être financée, fixé à son adressage), ses dates et, par débiteur, debtor_consent. La spécification liste tous les champs.

curl
curl -s "$BASE/v1/requests?status=all&limit=50" \
  -H "Authorization: Bearer $ADVANTA_KEY"
JavaScript
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);
Réponse, abrégée · 200
{
  "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
        }
      ]
    }
  ]
}

GET/v1/requests/{id}

Le dossier d’analyse d’une demande : la demande, ses créances, le dernier Advanta Score du cédant, votre propre offre et risk, les signaux de fraude et les contestations de la demande, tels que votre portail les montre.

NomOùDescription
id obligatoirepathL’id de la demande.
Portée
requests:read
Renvoie
200{ request, debtor_consent[], receivables[], score, my_offer, risk }
Erreurs
404not_found

score va de 300 à 850, avec une note de A à E et ses dimensions. Il est calculé à la volée quand le cédant n’en a pas encore, et vaut null si ce calcul échoue. Chaque créance a invoice_no, invoice_amount, invoice_date, invoice_due_date et le débiteur dans customer_name. debtor_consent donne, par débiteur, le statut de la notification, le niveau exigé et le niveau signé (level_achieved), meets_requirement, le canal, le texte de déclaration signé et le signataire.

risk.signals liste les signaux de fraude encore ouverts ou confirmés, chacun avec un code stable (par exemple amount_above_history) et une severity. Un signal hard (par exemple un montant modifié pendant que la facture est dans une demande, un avoir sur cette facture ou une contestation ouverte) bloque l’adressage et le financement jusqu’à ce que l’équipe des opérations d’Advanta l’examine ; les autres ne font que signaler. risk.disputes liste toutes les contestations enregistrées contre la demande.

curl
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87" \
  -H "Authorization: Bearer $ADVANTA_KEY"

POST/v1/requests/{id}/decision

Proposer des conditions, refuser, financer ou enregistrer un règlement. La demande doit vous être adressée ; sinon, 409 not_routed_to_you.

NomOùDescription
id obligatoirepathL’id de la demande.

Le corps prend l’une de quatre formes, selon decision :

decisionChampsEffet
offerrate (pourcentage, supérieur à 0 et jusqu’à 100) et advance_pct (même plage), tous deux obligatoires ; days, notes, valid_days (de 1 à 90).Envoie vos conditions et fait passer une demande pending, submitted ou under-review à terms_sent. L’offre expire après valid_days, sinon au terme de la validité configurée (7 jours par défaut). Refusée avec 409 credit_limit quand une de vos limites ne peut pas l’absorber, avec 409 debtor_not_eligible_for_funder quand vous n’acceptez que les acheteurs de votre liste et qu’un débiteur n’y figure pas, et avec 409 documents_missing_for_funder quand un document que vous exigez du cédant manque, n’est pas vérifié ou a expiré.
declinereason ou notes, au moins l’un des deux ; notes est le message que lit le cédant. internal_note facultatif : réservé à votre équipe, jamais montré au cédant.Clôt la demande. reason est l’un de payer_credit, invoice_ineligible, documentation, concentration, amount_out_of_range, sector_excluded, no_funder_capacity, withdrawn_by_client ou other ; le texte libre est conservé en note avec le motif other.
fundvalue_date (AAAA-MM-JJ, la date de valeur de votre virement au cédant, au plus 7 jours à l’avance) et reference (la référence du virement, de 3 à 140 caractères) ; amount facultatif, vérifié par rapport à l’avance acceptée.Seulement une fois que le cédant a accepté vos conditions (statut approved). En affacturage, la notification de chaque débiteur doit d’abord être confirmée (sinon 409 funding_gate_failed), et les documents que vous exigez du cédant doivent être valides à la date du financement (sinon 409 documents_missing_for_funder).
settleamount (obligatoire) ; received_at (maintenant par défaut, au plus un jour dans le futur) ; reference (jusqu’à 140 caractères) ; note (jusqu’à 1 000) ; final.Enregistre un encaissement sur une demande financée. Les paiements partiels s’additionnent ; la demande passe à settled quand le total atteint le montant de la demande ou que final vaut true.
Portée
decisions:write
Renvoie
201{ decision, request_id, offer_id, expires_at, status } (offer)
200{ decision, request_id, status } (decline)
200{ decision, request_id, status, funded_at } (fund)
200{ decision, request_id, settlement_id, status, received_total, request_total, outstanding } (settle)
Erreurs
400reason_required
403not_your_request (settle uniquement : vous n’êtes pas le financeur de la demande)
404not_found
409not_routed_to_you, invalid_state, credit_limit, funding_gate_failed, funding_amount_mismatch, debtor_not_eligible_for_funder, documents_missing_for_funder
422invalid_terms, invalid_amount, invalid_received_at, invalid_funding_details, step_back_message_required, invalid_decision
curl
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"}'
JavaScript
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 });
Réponse · 201
{
  "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"
}
Corps pour refuser, financer et régler
{ "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" }

Documents et règles

Ce qui doit être en place avant de financer : les documents que vous exigez des cédants, par pays du cédant, et ce que chaque débiteur doit signer. Chaque demande garde les versions qui ont satisfait vos exigences.

GET/v1/requests/{id}/documents

Le dossier documentaire d’une demande. Quand la demande vous a été adressée, puis quand elle a été financée, Advanta a enregistré quelle version de chaque document que vous exigez vous a donné satisfaction : nom du fichier, SHA-256, dates d’émission et de validité, et quand et comment Advanta l’a vérifié. Cet enregistrement ne change jamais, même quand le cédant dépose des versions plus récentes ; chaque entrée indique aussi où en est le document aujourd’hui, et current liste les documents actuels du cédant.

NomOùDescription
id obligatoirepathL’id de la demande.
Portée
requests:read
Renvoie
200{ request_id, seller_country, today, required_now, snapshots[], current[] }
Erreurs
404not_found

Chaque entrée avec un fichier porte une download_url valable deux minutes (url_expires_in), et chaque URL émise est journalisée. Comparez le SHA-256 de ce que vous téléchargez avec celui enregistré.

curl
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/documents" \
  -H "Authorization: Bearer $ADVANTA_KEY"

GET/v1/required-documents

Les documents que vous exigez des cédants, par pays du cédant, et le catalogue dans lequel ils sont choisis : le code de chaque document, son nom en sept langues, l’émetteur, la validité habituelle et la sensibilité. La validité habituelle ne sert qu’à pré-remplir : c’est la date imprimée sur le document qui compte, celle que le cédant saisit et qu’Advanta vérifie.

Portée
requests:read
Renvoie
200{ funder, required, catalogue[] }
Erreurs
Seulement les codes communs (401, 403, 500).

Une demande ne vous est adressée, votre offre n’est enregistrée et la demande n’est financée que tant que chaque document de votre liste pour le pays du cédant est vérifié par Advanta et valide à cette date ; sinon, 409 documents_missing_for_funder.

curl
curl -s "$BASE/v1/required-documents" \
  -H "Authorization: Bearer $ADVANTA_KEY"

PUT/v1/required-documents

Remplacer votre liste pour un pays de cédants ; une liste vide l’efface. Les codes viennent du catalogue, et le changement est conservé dans la chaîne de preuves d’Advanta avec note. Les demandes déjà chez vous y restent ; votre prochaine offre ou votre prochain financement sur l’une d’elles attend que le cédant satisfasse la nouvelle liste (open_requests_not_meeting les compte).

NomOùDescription
country obligatoirebodyLe pays du cédant, deux lettres.
codes obligatoirebodyDes codes de document du catalogue.
notebodyJusqu’à 500 caractères.
Portée
settings:write ou decisions:write
Renvoie
200{ …required documents, changed, country, codes, open_requests_not_meeting }
Erreurs
422body_required, country_invalid, codes_invalid, note_invalid, country_without_catalogue, document_code_unknown
curl
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"}'

GET/v1/settings

Ce que vos débiteurs doivent signer avant que vous financiez : le niveau que chaque débiteur doit signer avant qu’une demande d’affacturage qui vous est adressée puisse être financée (receipt, puis acknowledgment, puis acceptance), si seuls comptent les textes de déclaration approuvés par un avocat, vos demandes ouvertes par niveau, et les niveaux pour lesquels chaque droit applicable a un texte de déclaration, et dans quelles langues.

Portée
requests:read
Renvoie
200{ funder, debtor_consent_level, require_counsel_approved_texts, open_requests_by_level, levels, levels_by_law, texts_counsel_approved }
Erreurs
Seulement les codes communs (401, 403, 500).
curl
curl -s "$BASE/v1/settings" \
  -H "Authorization: Bearer $ADVANTA_KEY"

PUT/v1/settings

Modifier ce que vos débiteurs doivent signer. Le changement s’applique aux demandes qui vous sont adressées à partir de ce moment ; une demande déjà adressée garde le niveau avec lequel elle l’a été. reason est conservé dans la chaîne de preuves d’Advanta.

NomOùDescription
debtor_consent_levelbodyreceipt, acknowledgment ou acceptance.
require_counsel_approved_textsbodytrue pour ne compter que les textes de déclaration approuvés par un avocat.
reason obligatoirebodyPourquoi, au moins 8 caractères.
Portée
settings:write ou decisions:write
Renvoie
200{ …settings, changed, open_requests_keep_their_level }
Erreurs
422level_invalid, invalid_flag, reason_required
curl
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"}'

Conditions du programme et recours

Choisissez, par défaut et par entreprise, si chaque débiteur reçoit la notification avant que vous financiez (annoncé) ou si la notification est préparée et gardée prête à l’envoi (confidentiel), avec ou sans recours, et si vous demandez les données bancaires du cédant. Ensuite, annoncez une demande confidentielle, lisez ses notifications et le flux de trésorerie que le cédant partage avec vous, et suivez vos réclamations de recours.

GET/v1/programme

Les conditions de votre programme : vos conditions par défaut, celles que vous avez fixées pour certaines entreprises, les entreprises pour lesquelles vous pouvez en fixer (celles qui ont une demande qui vous est adressée, et vos propres clients) et vos demandes d’affacturage comptées selon les conditions qu’elles portent. Une demande prend les conditions en vigueur quand elle vous est adressée et les garde.

Portée
requests:read
Renvoie
200{ funder, bank_id, default, companies[], sellers[], requests }
Erreurs
Seulement les codes communs (401, 403, 500).

disclosure : announced (par défaut) : chaque débiteur reçoit la notification et confirme la cession avant que vous financiez. confidential : quand la demande vous est adressée, la notification à chaque débiteur est préparée, avec son empreinte (SHA-256), et conservée prête à l’envoi, et le financement n’attend pas le débiteur. Avant le financement, tous les contrôles bloquants des factures doivent être passés, les factures doivent venir de la comptabilité du cédant lui-même (ERP, facture électronique ou SAF-T), chaque débiteur doit avoir une notification préparée et à jour qui vous nomme et une adresse où l’envoyer, et la vérification du cédant doit être approuvée. Les notifications sont envoyées quand vous annoncez la demande, et automatiquement, sur une demande financée, quand un déclencheur que vous avez activé se produit : announce_overdue_days, announce_on_dispute, announce_on_kyc_lapse.

recourse : with (avec recours) ou without (sans recours). recourse_days : jours après l’échéance d’une facture avant qu’une demande financée pas encore réglée n’ouvre une réclamation (null : aucune). bank_data : off, requested (le cédant est invité à connecter pour vous son compte bancaire professionnel, en lecture seule et avec son consentement) ou required (le financement attend aussi que le compte sur lequel vous payez soit confirmé comme celui du cédant lui-même).

curl
curl -s "$BASE/v1/programme" \
  -H "Authorization: Bearer $ADVANTA_KEY"
Réponse, abrégée · 200
{
  "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 }
}

PUT/v1/programme

Modifier vos conditions par défaut (sans seller_id) ou celles d’une entreprise. Seules les clés envoyées changent ; {"reset": true} avec un seller_id ramène cette entreprise à vos conditions par défaut. Le changement s’applique aux demandes qui vous sont adressées à partir de ce moment ; les demandes déjà adressées gardent leurs conditions. reason est conservé dans la chaîne de preuves d’Advanta.

NomOùDescription
seller_idbodyL’id d’une entreprise, tiré de sellers dans GET /v1/programme. Absent ou null : vos conditions par défaut.
terms obligatoirebodyLes conditions à modifier : disclosure, recourse, recourse_days, announce_overdue_days, announce_on_dispute, announce_on_kyc_lapse, bank_data ; ou reset.
reason obligatoirebodyPourquoi, au moins 8 caractères.
Portée
settings:write ou decisions:write
Renvoie
200{ funder, bank_id, seller_id, terms, changed, open_requests_keep_their_terms }
Erreurs
422body_invalid, seller_id_invalid, terms_invalid, terms_key_unknown, reason_required, seller_not_in_programme
curl
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"}'

POST/v1/requests/{id}/announce

Annoncer une demande confidentielle qui vous est adressée : elle devient annoncée et les notifications préparées pour elle sont envoyées à ses débiteurs, qui les confirment ensuite comme dans un programme annoncé. Possible tant que la demande est en attente, à l’étude, avec des conditions envoyées, approuvée ou financée. Un événement request.announced suit ; une fois une notification envoyée, la demande reste annoncée.

NomOùDescription
id obligatoirepathL’id de la demande.
reason obligatoirebodyPourquoi, au moins 8 caractères. Conservé dans la chaîne de preuves d’Advanta.
Portée
decisions:write
Renvoie
200{ request_id, disclosure, trigger, notices, sending_queued }
Erreurs
403not_routed_to_you
404not_found
422body_invalid, reason_required, already_announced, request_closed
curl
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"}'

GET/v1/requests/{id}/notices

Les notifications de cession de la demande, une par débiteur, chacune avec son document préparé quand il existe : l’objet et le HTML exacts que reçoit le débiteur, sa langue, le droit applicable et son SHA-256. Pour une demande qui vous est adressée, ou une sur laquelle vous avez déjà agi.

NomOùDescription
id obligatoirepathL’id de la demande.
Portée
requests:read
Renvoie
200{ request_id, count, notices[] }
Erreurs
404not_found

Le HTML porte un marqueur, ACK_LINK entre doubles accolades, à l’endroit du lien de confirmation du débiteur ; le lien contient un secret et n’est jamais montré. current indique si le document correspond encore aux factures et au montant de la notification.

curl
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/notices" \
  -H "Authorization: Bearer $ADVANTA_KEY"

GET/v1/requests/{id}/cash-flow

Ce que le cédant partage avec vous de son compte bancaire professionnel, en lecture seule et avec son consentement, par un prestataire agréé d’information sur les comptes : la connexion, ses comptes (les quatre derniers caractères de chaque IBAN) et leurs soldes, douze mois de mouvements par mois, et la vérification de son compte de versement. cash_flow vaut null tant que le cédant n’a pas connecté de compte pour vous.

NomOùDescription
id obligatoirepathL’id de la demande.
Portée
requests:read
Renvoie
200{ request_id, bank_data, cash_flow, bank_data_problems[], payment_alerts[] }
Erreurs
404not_found

bank_data_problems dit ce que le financement attend encore quand vos conditions exigent des données bancaires. payment_alerts sont les paiements que le cédant a reçus d’un débiteur de cette demande après que vous l’avez financée en conditions confidentielles. Le consentement d’un cédant est donné à un financeur : vous ne voyez que ce qu’il partage avec vous.

curl
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/cash-flow" \
  -H "Authorization: Bearer $ADVANTA_KEY"

GET/v1/recourse

Vos demandes d’affacturage financées par type de recours (with, without, et not_recorded pour celles adressées avant le 28 septembre 2026), les réclamations comptées par type et statut, et les réclamations elles-mêmes, les ouvertes d’abord. Une réclamation s’ouvre une fois par demande, quand une demande financée n’est pas réglée recourse_days après l’échéance d’une facture : recourse, contre le cédant, pour le montant avancé plus vos frais, moins ce que vous avez déjà encaissé ; debtor_default, sans recours, pour votre propre recouvrement et votre assurance.

NomOùDescription
statusqueryopen, settled, withdrawn ou written_off. Absent : toutes les réclamations.
Portée
requests:read
Renvoie
200{ funder, bank_id, currency, as_of, by_type[], claims[], list[] }
Erreurs
422status_invalid

Le cédant rembourse une réclamation de recours sur pay_to_iban en indiquant pay_reference. Quand les paiements que vous enregistrez à partir de là (une ligne de relevé que vous confirmez, ou la décision settle) couvrent claim_amount, la réclamation est réglée et la demande se clôt comme réglée par recours : les factures reviennent au cédant, toujours impayées par le débiteur.

curl
curl -s "$BASE/v1/recourse?status=open" \
  -H "Authorization: Bearer $ADVANTA_KEY"

POST/v1/recourse/{id}/close

Clore une de vos réclamations ouvertes : une réclamation de recours devient withdrawn (vous y renoncez, ou vous avez convenu autre chose avec le cédant), un défaut du débiteur devient written_off (transmis à votre recouvrement ou à votre assureur). reason est conservé dans la chaîne de preuves d’Advanta.

NomOùDescription
id obligatoirepathL’id de la réclamation (claim_id).
status obligatoirebodywithdrawn ou written_off.
reason obligatoirebodyPourquoi, au moins 8 caractères.
Portée
decisions:write
Renvoie
200{ claim_id, status }
Erreurs
403not_your_claim
404not_found
422body_invalid, status_invalid, reason_required, close_invalid, claim_closed
curl
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"}'

GET/v1/bank-data

Votre propre compte d’encaissement, connecté par votre administrateur dans le portail et lu de la même façon : ses mouvements passent par le même rapprochement que POST /v1/statements, pour que les encaissements correspondent à vos demandes financées sans envoyer de fichier. Aussi : combien de cédants partagent leur compte avec vous, les alertes de paiement sur vos demandes (les 180 derniers jours) et les frais du prestataire enregistrés à votre charge, par mois.

Portée
requests:read
Renvoie
200{ funder, bank_id, own_accounts[], sellers_sharing, payment_alerts[], charges[] }
Erreurs
Seulement les codes communs (401, 403, 500).

unit_price_eur et amount_eur valent null tant que le prix du prestataire n’est pas fixé.

curl
curl -s "$BASE/v1/bank-data" \
  -H "Authorization: Bearer $ADVANTA_KEY"

Limites et historique de paiement

Votre exposition par débiteur et par cédant, appliquée par la plateforme elle-même, avec des limites fixées une à une ou jusqu’à 2 000 d’un coup ; la façon dont un acheteur paie ses fournisseurs ; et ce qu’Advanta sait de chaque débiteur d’une demande.

GET/v1/credit-limits

Votre registre par débiteur : votre limite et ce qui est en cours, engagé, proposé et encore disponible, en euros.

Portée
limits:read ou requests:read
Renvoie
200{ funder, currency, count, debtors[] }
Erreurs
Seulement les codes communs (401, 403, 500).

Chaque débiteur comporte debtor_key, debtor_name, debtor_country, limit_status, limit_amount, outstanding, committed, offered, available, overdue_count, oldest_overdue, frozen, decided_at et note.

curl
curl -s "$BASE/v1/credit-limits" \
  -H "Authorization: Bearer $ADVANTA_KEY"

PUT/v1/credit-limits

Fixer ou réviser votre limite sur un débiteur, ou refuser le débiteur. La base de données refuse toute offre ultérieure que cette limite ne peut pas absorber.

NomOùDescription
debtor_tax_id obligatoirebodyLe numéro de TVA ou d’identification fiscale du débiteur.
debtor_countrybodyISO 3166 alpha-2.
debtor_namebodyLe nom du débiteur.
amountbodyEn euros, 0 ou plus. Obligatoire pour une limite active.
statusbodyactive (par défaut), refused ou suspended.
notebodyTexte libre.
Portée
limits:write ou decisions:write
Renvoie
200{ credit_limit }
Erreurs
422debtor_tax_id_required, invalid_amount, invalid_limit
curl
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"}'

POST/v1/credit-limits/import

Charger jusqu’à 2 000 limites sur des débiteurs en un seul appel : votre propre registre, ou les limites de votre assureur-crédit. Chaque ligne est vérifiée exactement comme PUT /v1/credit-limits en vérifie une et reçoit sa propre réponse : une ligne en échec n’arrête pas les autres, et un débiteur présent deux fois dans le même appel est refusé la seconde fois.

NomOùDescription
rows obligatoirebodyDe 1 à 2 000 lignes, chacune avec debtor_tax_id et, comme dans PUT /v1/credit-limits, debtor_country, debtor_name, amount, status et note. amount est un nombre ou des chiffres avec un point décimal ; il est obligatoire pour une limite active. Une simple liste de lignes, sans l’objet autour, est aussi acceptée (avec source import).
sourcebodyimport (vos propres limites, par défaut) ou insurer (les limites de votre assureur-crédit).
source_refbodyLe fichier ou le lot d’où viennent les limites, 200 caractères au plus.
Portée
limits:write ou decisions:write
Renvoie
200{ funder, source, source_ref, received, written, refused, rows[] }
Erreurs
413too_many_rows
422rows_required, invalid_source, source_ref_invalid, source_ref_too_long

Chaque limite écrite enregistre sa source et sa référence, sur la limite et dans son historique. La réponse compte received, written et refused, et répond à chaque ligne avec row (à partir de 1), debtor_tax_id et ok : une ligne écrite ajoute debtor_key, status et amount ; une ligne refusée donne son error (invalid_amount, debtor_tax_id_required, duplicate_debtor, invalid_status, amount_required, invalid_country, row_invalid ou invalid_limit) et peut ajouter un detail.

curl
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"}]}'

GET/v1/seller-limits

Votre registre par cédant, avec les mêmes chiffres que le registre des débiteurs.

Portée
limits:read ou requests:read
Renvoie
200{ funder, currency, count, sellers[] }
Erreurs
Seulement les codes communs (401, 403, 500).

Chaque cédant comporte seller_id, seller_name, seller_nif, seller_country et les mêmes champs de limite et d’exposition qu’un débiteur.

curl
curl -s "$BASE/v1/seller-limits" \
  -H "Authorization: Bearer $ADVANTA_KEY"

PUT/v1/seller-limits

Fixer ou réviser votre limite sur un cédant, ou refuser le cédant.

NomOùDescription
seller_id obligatoirebodyTel que renvoyé par GET /v1/seller-limits.
amountbodyEn euros, 0 ou plus.
statusbodyactive (par défaut), refused ou suspended.
notebodyTexte libre.
Portée
limits:write ou decisions:write
Renvoie
200{ seller_limit }
Erreurs
404not_found
422seller_id_required, invalid_amount, invalid_limit
curl
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"}'

GET/v1/payer-record

Comment un acheteur paie ses fournisseurs, uniquement en agrégé, à partir de la comptabilité des fournisseurs connectés à Advanta. L’historique est publié quand au moins trois fournisseurs observent l’acheteur ; sinon, status dit pourquoi et tous les chiffres valent null. Vous ne pouvez le lire que pour un acheteur présent sur une demande de votre périmètre ou sur votre liste de débiteurs ; une clé sandbox lit l’historique du plan de démonstration.

NomOùDescription
tax_id obligatoirequeryLe numéro de TVA ou d’identification fiscale de l’acheteur.
countryqueryISO 3166 alpha-2.
Portée
limits:read ou requests:read
Renvoie
200{ funder, payer_record }
Erreurs
404not_found (l’acheteur n’est sur aucune demande de votre périmètre ni sur votre liste de débiteurs)
422tax_id_required

Les chiffres comprennent observers, invoice_count, avg_days_to_pay, median_days_to_pay, on_time_pct, le retard de paiement (avg_settle_delay_days, median_settle_delay_days, p75_settle_delay_days, worst_settle_delay_days), des comptes de factures ouvertes et échues, window_from et refreshed_at. payer_record vaut null quand il n’y a pas d’historique.

curl
curl -s "$BASE/v1/payer-record?tax_id=A00000000&country=ES" \
  -H "Authorization: Bearer $ADVANTA_KEY"

GET/v1/requests/{id}/debtors

Ce qu’Advanta sait de chaque débiteur d’une demande d’affacturage qui vous est adressée, ou d’une sur laquelle vous avez déjà agi : son level sur Advanta depuis level_since (notice : il ne connaît Advanta que par la notification ; account : il a activé son compte de payeur ; books : il a connecté son logiciel comptable ; buyer : il gère un programme acheteur, et buyer_programme vaut true), l’historique du cédant lui-même avec lui, son délai moyen de paiement officiel quand c’est un organisme public, et votre limite sur lui.

NomOùDescription
id obligatoirepathL’id de la demande.
Portée
requests:read
Renvoie
200{ funder, request_id, count, debtors[] }
Erreurs
404not_found

score est le score propre du débiteur (note, de 0 à 100, quand et avec quelle version du modèle). Il n’est donné que si le débiteur partage ses données avec les financeurs qui financent des factures qu’il doit, est au niveau books ou buyer, et que la demande vous est adressée (pas une sur laquelle vous avez seulement agi) ; sinon il vaut null. pair_history est l’historique du cédant avec ce débiteur sur 36 mois, selon les règles de l’historique de paiement : uniquement des factures réelles, et un retard mesuré seulement par rapport aux échéances indiquées sur le document ou dans l’ERP. public_payment_period est le dernier délai moyen de paiement officiel d’un organisme public (DGAL pour les communes portugaises, Hacienda pour les collectivités locales espagnoles). credit_limit est votre limite sur le débiteur, son origine (source, source_ref) et ce qui est utilisé (exposure : en cours plus engagé plus proposé, en euros).

curl
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/debtors" \
  -H "Authorization: Bearer $ADVANTA_KEY"

Relevés et règlements

Envoyez le relevé de votre compte d’encaissement et chaque crédit est rapproché de vos demandes financées ; vous confirmez chaque rapprochement dans le portail. Pour enregistrer vous-même un paiement, envoyez la décision settle.

POST/v1/statements

Envoyer le relevé de votre compte d’encaissement pour rapprochement : un fichier CAMT.053 (XML) ou CSV, au plus 4 Mio et 5 000 opérations. Chaque crédit est rapproché de vos propres demandes financées, d’abord sur la référence indiquée par le débiteur. Rien n’est réglé tant que vous n’avez pas confirmé un rapprochement dans le portail. Le même fichier envoyé deux fois est refusé, d’après son SHA-256.

NomOùDescription
file_namequeryLe nom du fichier (facultatif).
kindquerycamt053 ou csv ; détecté s’il est omis.
le fichier obligatoirebodyLe fichier tel quel, envoyé en application/xml ou text/csv ; ou du JSON { file_name, kind, content_base64 }.
Portée
statements:write ou decisions:write
Renvoie
201{ import_id, file_sha256, lines, credits, duplicates, proposed, suggested, unmatched, ignored, … }
Erreurs
409statement_already_imported
413file_too_large, too_many_lines
422file_required, file_unreadable, file_empty, statement_unreadable, statement_has_no_transactions, line_invalid
curl
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.xml

Clients et prescripteurs

Amenez vos propres clients : un lien ouvert à vous, un lien par prescripteur, et les invitations et le rapport qui montrent qui est arrivé par chacun. Les entreprises que vous amenez ne sont adressées qu’à vous.

GET/v1/prescribers

Vos prescripteurs, les personnes et cabinets qui vous apportent des clients (experts-comptables, conseillers, courtiers), les actifs d’abord, chacun avec son lien actuel et le nombre d’entreprises arrivées par ce lien. Ce sont les vôtres, pas des partenaires d’Advanta. La même liste que la page Clients de votre portail.

NomOùDescription
langqueryLa langue de la page qu’ouvre chaque lien : pt, es, en, fr, de, it ou nl, ajoutée à son url.
Portée
requests:read, clients:write ou decisions:write
Renvoie
200{ funder, count, prescribers[] }
Erreurs
422lang_invalid

Une clé sandbox lit les prescripteurs du financeur de démonstration, que toutes les démonstrations partagent.

curl
curl -s "$BASE/v1/prescribers?lang=es" \
  -H "Authorization: Bearer $ADVANTA_KEY"

POST/v1/prescribers

Ajouter un prescripteur. Son propre lien ouvert est émis avec lui, dans prescriber.link.url. Son nom et son e-mail restent hors de la chaîne de preuves d’Advanta : seuls leurs hachages y figurent.

NomOùDescription
name obligatoirebodyDe 2 à 120 caractères, unique parmi vos prescripteurs actifs.
emailbodyFacultatif. Un financeur sandbox n’enregistre que des adresses réservées (se terminant par .example, .invalid, .test ou .demo).
notesbodyFacultatif, jusqu’à 1 000 caractères.
langbodyLa langue de la page qu’ouvre son lien, ajoutée à son url.
Portée
clients:write ou decisions:write
Renvoie
201{ prescriber }
Erreurs
409prescriber_exists
422body_required, name_required, name_invalid, email_invalid, email_not_reserved, notes_too_long, lang_invalid

Avec une clé sandbox, cela modifie l’état de démonstration partagé : la clé a donc besoin de decisions:write.

curl
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"}'
Réponse, abrégée · 201
{
  "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"
    }
  }
}

POST/v1/prescribers/{id}/disable

Désactiver un prescripteur. Son lien cesse aussitôt de fonctionner ; les entreprises qu’il a apportées lui restent attribuées. Désactiver un prescripteur déjà désactivé ne change rien (changed vaut false). Enregistré dans la chaîne de preuves d’Advanta.

NomOùDescription
id obligatoirepathL’id du prescripteur.
reasonbodyLe motif, jusqu’à 200 caractères.
Portée
clients:write ou decisions:write
Renvoie
200{ prescriber, changed }
Erreurs
404not_found
405method_not_allowed
422body_invalid, reason_invalid
curl
curl -s -X POST "$BASE/v1/prescribers/$PRESCRIBER_ID/disable" \
  -H "Authorization: Bearer $ADVANTA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Agreement ended"}'

GET/v1/prescribers/report

Ce que chaque prescripteur vous a apporté : un groupe par prescripteur, puis votre propre lien (own_link), vos invitations par nom (named) et vos liens d’entrée en relation (api). Par groupe et par entreprise : quand elle est arrivée, quand son compte a été ouvert (joined), quand la vérification de l’entreprise a été approuvée (onboarded), les demandes qui vous ont été adressées, le montant demandé et le montant financé. Les mêmes chiffres que votre portail.

Portée
requests:read, clients:write ou decisions:write
Renvoie
200{ funder, plane, generated_at, currency, totals, groups[] }
Erreurs
405method_not_allowed

Une entreprise compte une fois, pour qui vous l’a apportée en premier. Le montant financé est l’avance (à défaut, le total) des demandes financées ou réglées, en euros ; totals additionne tous les groupes. Seulement vos données et seulement les entreprises de votre plan de données : une clé sandbox ne voit pas ce que d’autres clés sandbox ont fait par l’API.

curl
curl -s "$BASE/v1/prescribers/report" \
  -H "Authorization: Bearer $ADVANTA_KEY"
Réponse, abrégée · 200
{
  "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
        }
      ]
    }
  ]
}

GET/v1/client-invitations

Toutes vos invitations, les plus récentes d’abord : par un lien, par nom dans le portail ou avec un lien d’entrée en relation. Chacune indique comment l’entreprise est arrivée (via : link, named ou api), le prescripteur qui l’a apportée le cas échéant, son state (pending, accepted, revoked ou expired), l’entreprise, le contact et les dates.

NomOùDescription
limitqueryDe 1 à 500, 200 par défaut.
Portée
requests:read, clients:write ou decisions:write
Renvoie
200{ funder, count, invitations[] }
Erreurs
405method_not_allowed

Seulement votre propre plan de données. Une clé sandbox ne voit pas les invitations faites par d’autres clés sandbox.

curl
curl -s "$BASE/v1/client-invitations?limit=50" \
  -H "Authorization: Bearer $ADVANTA_KEY"

Opportunités du jour

Chaque matin, les factures de vos propres clients devenues éligibles selon vos règles pendant la nuit, et ce qui a changé dans celles qui vous ont été montrées. Le webhook opportunities.daily signale quand il y a quelque chose à lire.

GET/v1/opportunities

Le résumé d’un jour, pour vos propres clients (les entreprises dont vous êtes le financeur d’origine) qui vous permettent de voir leurs factures. Chaque matin vers 6 h 30, heure de Madrid, après la préqualification de la nuit, Advanta liste les factures devenues éligibles selon vos règles depuis le résumé précédent (kind new) et ce qui a changé dans celles qui vous ont déjà été montrées : paid, disputed (le client a enregistré que son débiteur la conteste) ou no_longer_eligible.

NomOùDescription
datequeryLe jour du résumé, YYYY-MM-DD (heure de Madrid). Absent : le plus récent. Un jour sans résumé répond date null et aucune ligne.
Portée
requests:read
Renvoie
200{ funder, date, digest, lines[] }
Erreurs
404not_found
405method_not_allowed
422invalid_date

Une ligne porte la facture, le débiteur avec son numéro fiscal, le montant encore dû, l’échéance, et le client avec son secteur (section NACE), sa note et sa taille ; d’abord les nouvelles lignes, puis les changements. no_longer_eligible a un reason : requested (le client a demandé à la financer), cancelled, removed (elle n’est plus dans les livres du client), left_programme, not_shared (le client a cessé de partager) ou rules (elle ne respecte plus vos règles).

digest donne les totaux : combien de clients partagent et combien pas encore, ce qui est éligible aujourd’hui, ce qui est nouveau et ce qui a changé. stale vaut true quand le traitement de la nuit ne s’est pas terminé : rien n’a été comparé ce matin-là. Un résumé est une liste calculée par la base de données, pas une offre : une demande est vérifiée à nouveau quand elle est faite, et vous décidez comme toujours. Le webhook opportunities.daily signale qu’un résumé avec du contenu est prêt.

curl
curl -s "$BASE/v1/opportunities?date=2026-10-07" \
  -H "Authorization: Bearer $ADVANTA_KEY"
Réponse, abrégée · 200
{
  "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" }
    }
  ]
}

Endpoints de webhook

Enregistrez les endpoints qui reçoivent les webhooks, changez leurs secrets, envoyez un test et lisez le journal de livraison.

GET/v1/webhooks

Vos endpoints actifs, sans leurs secrets, et les types d’événements auxquels vous pouvez vous abonner. Une clé sandbox ne voit que les endpoints qu’elle a créés.

Portée
webhooks:write, decisions:write ou requests:read
Renvoie
200{ count, webhooks[], event_types[] }
Erreurs
Seulement les codes communs (401, 403, 500).
curl
curl -s "$BASE/v1/webhooks" \
  -H "Authorization: Bearer $ADVANTA_KEY"

POST/v1/webhooks

Enregistrer un endpoint. La réponse contient son secret de signature, qui ne sera plus affiché.

NomOùDescription
url obligatoirebodyhttps sur un nom d’hôte public, port 443, sans nom d’utilisateur ni mot de passe ; 2 048 caractères au plus. Les adresses privées, de bouclage et link-local sont refusées, et les redirections ne sont jamais suivies.
eventsbodyUne liste de types d’événements, ou ["*"] pour tous (par défaut).
descriptionbodyJusqu’à 200 caractères.
Portée
webhooks:write ou decisions:write
Renvoie
201{ webhook, secret, signature }
Erreurs
409too_many_endpoints
422body_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

Au plus 10 endpoints actifs.

curl
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"}'
JavaScript
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);
Réponse, abrégée · 201
{
  "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 }
}

DELETE/v1/webhooks/{id}

Arrêter un endpoint. Les livraisons encore en attente sont annulées et ses secrets sont supprimés.

NomOùDescription
id obligatoirepathL’id de l’endpoint.
Portée
webhooks:write ou decisions:write
Renvoie
200{ id, active: false, deleted: true, cancelled_deliveries }
Erreurs
404not_found
curl
curl -s -X DELETE "$BASE/v1/webhooks/$WEBHOOK_ID" \
  -H "Authorization: Bearer $ADVANTA_KEY"

POST/v1/webhooks/{id}/rotate-secret

Un nouveau secret de signature, affiché une seule fois. L’ancien secret continue de signer, en second v1 dans l’en-tête, pendant keep_previous_hours, pour que vous puissiez basculer sans perdre d’événements.

NomOùDescription
id obligatoirepathL’id de l’endpoint.
keep_previous_hoursbodyDe 0 à 72, 24 par défaut.
Portée
webhooks:write ou decisions:write
Renvoie
200{ webhook, secret, previous_secret_valid_until }
Erreurs
404not_found
422invalid_keep_previous_hours
curl
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}'

POST/v1/webhooks/{id}/test

Mettre en file un événement webhook.test vers cet endpoint. La prochaine exécution du répartiteur le livre, en une minute environ.

NomOùDescription
id obligatoirepathL’id de l’endpoint.
Portée
webhooks:write ou decisions:write
Renvoie
202{ endpoint_id, event_id, delivery_id, status: "pending" }
Erreurs
404not_found
curl
curl -s -X POST "$BASE/v1/webhooks/$WEBHOOK_ID/test" \
  -H "Authorization: Bearer $ADVANTA_KEY"

GET/v1/webhooks/{id}/deliveries

Le journal de livraison d’un endpoint, du plus récent au plus ancien : statut (pending, delivered, failed ou cancelled), tentatives, code de réponse, dernière erreur, prochaine tentative, et le SHA-256 du corps exact envoyé.

NomOùDescription
id obligatoirepathL’id de l’endpoint.
limitqueryDe 1 à 200, 50 par défaut.
Portée
webhooks:write, decisions:write ou requests:read
Renvoie
200{ count, deliveries[] }
Erreurs
404not_found
curl
curl -s "$BASE/v1/webhooks/$WEBHOOK_ID/deliveries?limit=20" \
  -H "Authorization: Bearer $ADVANTA_KEY"

Liens d’entrée en relation

Depuis votre propre produit, remettez à un fournisseur un lien Advanta d’entrée en relation à usage unique ; le fournisseur vous revient avec un statut signé quand il a terminé.

L’export de vos données

Emportez tout ce que vous pouvez voir sur Advanta, quand vous le voulez, sans le demander : votre droit de sortie (DORA art. 28, par. 8, et art. 30, par. 3, point f). Un ZIP avec un CSV et un fichier JSON Lines par entité, schema.json, manifest.json avec le SHA-256 de chaque fichier, un README dans votre langue et verify.py.

POST/v1/exports

Lance un export de tout ce que votre financeur peut voir : demandes et leur historique, offres, factures avec leur vérification, vendeurs (données de l’entreprise, le résumé KYC que vous pouvez voir, la vérification du représentant), débiteurs, notifications avec les réponses des débiteurs et les données des certificats, les entrées de la chaîne de preuve sur vos opérations avec les hachages et les racines quotidiennes pour les vérifier, règlements et relevés, refus des contrôles, vos règles et limites, votre équipe, endpoints de webhook (jamais un secret), clés d’API (jamais une clé), votre piste d’audit et vos documents. Il est généré en arrière-plan, en général en moins d’une minute ; export.ready vous prévient.

NomOùDescription
langbodyLa langue du README : pt, es, en, fr, de, it ou nl (en par défaut).
Portée
exports:write ou decisions:write
Renvoie
202{ funder, export }
Erreurs
403export_live_key_required
409export_in_progress
422body_invalid, lang_invalid
429export_rate_limited

Une clé de production uniquement : une clé sandbox répond 403 export_live_key_required (le financeur de démonstration est partagé). Un export à la fois, au plus 10 en 24 heures. Le même export est sur la page Export du portail, dans les réglages.

curl
curl -s -X POST "$BASE/v1/exports" \
  -H "Authorization: Bearer $ADVANTA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"lang":"es"}'
Réponse · 202
{
  "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" }
  }
}

GET/v1/exports

Vos exports, depuis le portail et l’API, les plus récents d’abord, avec leur état, leur taille et manifest_sha256.

NomOùDescription
limitqueryDe 1 à 200, 50 par défaut.
Portée
exports:write ou decisions:write
Renvoie
200{ funder, count, exports[] }
Erreurs
403export_live_key_required
405method_not_allowed
curl
curl -s "$BASE/v1/exports?limit=20" \
  -H "Authorization: Bearer $ADVANTA_KEY"

GET/v1/exports/{id}

Un export. Pendant sa génération : status queued ou running, avec progress. Une fois ready, et pendant 24 heures : files, chaque volume avec un lien valable une heure au plus (jamais au-delà de ces 24 heures). Redemandez-le pour de nouveaux liens ; chaque appel qui renvoie des liens est enregistré. Après 24 heures les fichiers sont supprimés et l’enregistrement reste.

NomOùDescription
id obligatoirepathL’id de l’export, de POST /v1/exports ou GET /v1/exports.
Portée
exports:write ou decisions:write
Renvoie
200{ funder, export, files[] }
Erreurs
403export_live_key_required
404not_found
405method_not_allowed

manifest_sha256 est le SHA-256 de manifest.json écrit sans ce champ, clés triées, sans espaces. Advanta a enregistré la même valeur dans la chaîne de preuve (entrée export.ready) ; verify.py la recalcule et vérifie chaque fichier et les entrées de preuve.

curl
curl -s "$BASE/v1/exports/5e1f0a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b" \
  -H "Authorization: Bearer $ADVANTA_KEY"
Réponse, abrégée · 200
{
  "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"
    }
  ]
}
Télécharger et vérifier · shell
# 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

GET/v1/exports/{id}/documents

Quand les documents étaient trop volumineux pour être inclus (documents_mode links) : chaque document de l’export avec un lien valable 15 minutes, une page à la fois. La liste est calculée au moment de la demande : un document que vous ne pouvez plus lire n’y figure pas.

NomOùDescription
id obligatoirepathL’id de l’export.
afterqueryLe next_after de la page précédente.
limitqueryDe 1 à 200, 100 par défaut.
Portée
exports:write ou decisions:write
Renvoie
200{ funder, export_id, documents[], next_after }
Erreurs
403export_live_key_required
404not_found
409export_not_ready, export_failed
410export_expired
curl
curl -s "$BASE/v1/exports/5e1f0a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b/documents?limit=100" \
  -H "Authorization: Bearer $ADVANTA_KEY"

Webhooks

Enregistrez un endpoint HTTPS et Advanta lui envoie un POST signé quand quelque chose vous concerne : sur une demande qui vous est adressée ou sur son cédant, ou sur un lien d’entrée en relation que vous avez créé. Chaque endpoint s’abonne aux types d’événements dont il a besoin. Chaque envoi est signé et, en cas d’échec, relancé pendant 24 heures.

Événements

ÉvénementQuanddata
request.routedLes opérations d’Advanta vous ont adressé une demande. Vous pouvez maintenant la lire et décider.request_id, request_ref, type, status, total_amount, currency, routed_at
request.unroutedUne demande qui vous était adressée a été adressée ailleurs ou retirée. Vous ne pouvez plus agir dessus.request_id, request_ref, unrouted_at
offer.acceptedVotre offre a été acceptée (request_status vaut approved une fois que le cédant a accepté). Vous pouvez la financer.offer_id, request_id, request_ref, request_status, rate, advance_pct, days, accepted_at
notice.acknowledgedUn débiteur a confirmé la notification de cession. Un événement par débiteur ; channel vaut online ou offline.notice_id, request_id, request_ref, debtor_name, debtor_tax_id, invoice_count, total_amount, channel, decided_at
notice.disputedUn débiteur a rejeté la notification de cession. Un événement par débiteur.Les champs de notice.acknowledged, plus reason : les mots du débiteur, 500 caractères au plus.
request.fundedUne demande qui vous est adressée a été financée.Les champs de demande de request.routed, plus funded_at et advance_amount.
settlement.recordedUn encaissement sur une demande financée a été enregistré, partiel ou final : le paiement qui solde la demande a final à true.settlement_id, request_id, request_ref, amount, received_at, reference, received_total, request_total, outstanding, final, request_status
seller.documents_expiringUn document daté (par exemple une attestation fiscale ou sociale) d’un cédant ayant une demande ouverte ou financée qui vous est adressée expire dans 30 jours, dans 7 jours ou aujourd’hui. Vérifié chaque jour ; threshold_days vaut 30, 7 ou 0.seller_id, company_name, company_tax_id, document_id, document_type, valid_until, days_left, threshold_days, request_ids
dispute.openedUn débiteur a contesté des factures d’une demande qui vous est adressée, après l’approbation ou le financement. reason vaut goods_not_received, defective, amount_incorrect, already_paid, not_our_invoice ou other ; channel vaut cession_page, letter ou 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.resolvedLes opérations d’Advanta ont clos une contestation ; status vaut resolved_for_debtor, resolved_for_seller ou withdrawn.Les champs de dispute.opened, avec son status, plus resolved_at et resolution_note.
onboarding.completedUn fournisseur que vous avez invité avec un lien d’entrée en relation a soumis la vérification de son entreprise. status vaut completed ; metadata est la vôtre, telle que vous l’avez envoyée. Pour un lien créé avec une clé sandbox, seuls les endpoints de cette clé le reçoivent.onboarding_link_id, status, company_name, company_tax_id, country, seller_id, account_created_at, completed_at, verification_status, metadata
client.joinedUne entreprise que vous avez invitée (par son nom, par votre lien ouvert, par le lien d'un prescripteur ou par l'API) a accepté l'invitation et n'est plus qu'à vous : ses demandes n'arrivent qu'à vous. origin indique comment elle est arrivée (named, open_link, prescriber ou api), avec le prescripteur s'il y en a un.seller_id, invitation_id, company_name, company_tax_id, country, origin, channel, link_id, prescriber_id, prescriber_name, arrived_at, joined_at, mode
export.readyUn export que vous avez demandé (portail ou API) est prêt : téléchargez-le avec GET /v1/exports/{id} dans les 24 heures. Il porte son manifest_sha256, jamais un lien.export_id, status, requested_via, manifest_sha256, size_bytes, file_count, documents_mode, volumes, completed_at, expires_at
request.announcedUne demande confidentielle qui vous est adressée a été annoncée : par vous, par les opérations d’Advanta ou par un déclencheur que vous avez activé (trigger vaut manual, overdue, dispute ou kyc_lapsed). Ses notifications préparées sont en cours d’envoi ; notices liste chacune avec le SHA-256 de son document.request_id, request_ref, trigger, reason, status, notices, announced_at
recourse.openedUne de vos demandes financées n’est pas réglée recourse_days après l’échéance d’une facture : une réclamation de recours contre le cédant (kind recourse) ou un défaut du débiteur (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.settledUne réclamation a été réglée : par les paiements que vous avez enregistrés depuis son ouverture (via statement ou manual ; la demande se clôt comme réglée par recours), ou parce que la demande a été réglée de la façon habituelle (via request_settled, sans paid).claim_id, request_id, request_ref, kind, claim_amount, paid, via, request_closed
payment.reached_sellerSur un compte que le cédant partage avec vous, un paiement est arrivé d’un débiteur d’une demande que vous avez financée en conditions confidentielles : sa référence porte le numéro d’une facture financée (match_rule invoice_reference), ou le payeur et le montant correspondent (payer_and_amount).alert_id, request_id, invoice_ids, payer_name, payer_iban, amount, currency, booking_date, match_rule, confidence
opportunities.dailyLe résumé du matin contient quelque chose : des factures de vos propres clients devenues éligibles depuis le résumé précédent, ou un changement dans celles qui vous ont été montrées. Un sommaire seulement, des comptes et des totaux, jamais une facture, un débiteur ou un client : lisez les lignes avec GET /v1/opportunities?date= (lines). Au plus un par jour ; aucun un jour sans rien de nouveau ni de changé.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_blockedUn bulletin officiel (le BORME pour les sociétés espagnoles, Citius pour les portugaises) a publié un acte qui bloque pour tout nouveau financement un débiteur d’une demande que vous avez financée : insolvabilité déclarée ou en cours, liquidation, procédure close pour insuffisance d’actif, dissolution, extinction, ou feuille du registre fermée par l’administration fiscale ou après une insolvabilité. Tant qu’il tient, aucune nouvelle offre et aucun nouveau financement ne vont aux factures de ce débiteur. Un événement par demande et par passage à bloqué. C’est ce que le bulletin a publié, à examiner par vous, non une conclusion juridique ; seules les sociétés d’Espagne et du Portugal sont surveillées.request_id, request_ref, debtor (country, tax_id, name), status, note, events (kind, published_on, source, url), detected_at
pre_offer.acceptedUn client a demandé le financement des factures d’une pré-offre que vous lui avez envoyée depuis vos opportunités du matin : sa demande, faite avec tous les contrôles habituels, porte la pré-offre et vous parvient comme toujours (request.routed), et votre règle de crédit prépare votre offre à partir de votre grille. terms est ce que votre grille a donné à l’envoi, à titre indicatif : le prix est le vôtre, Advanta n’en indique aucun. Une fois par pré-offre.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.testL’événement de test demandé avec POST /v1/webhooks/{id}/test.

La livraison

Chaque livraison est un POST avec un corps JSON, envoyé octet pour octet tel qu’il est stocké (son SHA-256 figure dans le journal de livraison), avec trois en-têtes propres :

  • Advanta-Signature : t=<unix seconds>,v1=<hex>, voir Vérifier les signatures.
  • Advanta-Event-Id : l’id de l’événement, aussi id dans le corps.
  • Advanta-Event-Type : le type d’événement, aussi type dans le corps.
En-têtes
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
Corps
{
  "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
  }
}
ChampSignification
idL’id de l’événement, identique à Advanta-Event-Id.
objectToujours event.
typeL’un des types d’événements ci-dessus.
api_versionLa révision de l’API dans laquelle l’événement est écrit.
createdLa création de l’événement, en secondes Unix.
environmentlive, sandbox ou unclassified, comme dans GET /v1/me.
dataLes champs de l’événement, listés ci-dessus.

Livraison et nouvelles tentatives

  • Répondez par n’importe quel 2xx dans les 10 secondes et l’événement est livré. Toute autre réponse, une absence de réponse en 10 secondes ou une redirection est un échec ; les redirections ne sont jamais suivies.
  • Une livraison échouée est retentée après 1, 2, 4, 8 … minutes, en doublant, au plus à 6 heures d’intervalle, avec une dernière tentative 24 heures après l’événement. Elle est ensuite marquée failed et reste dans le journal de livraison.
  • La livraison est « au moins une fois ». Conservez les valeurs de Advanta-Event-Id déjà traitées et ignorez une répétition.
  • GET /v1/webhooks/{id}/deliveries montre le statut, les tentatives, le code de réponse, la dernière erreur et la prochaine tentative de chaque livraison. POST /v1/webhooks/{id}/test envoie un événement webhook.test quand vous voulez vérifier votre endpoint.

Endpoints et secrets

  • L’URL d’un endpoint est en https sur un nom d’hôte public, sur le port 443, sans nom d’utilisateur ni mot de passe. Les adresses privées, de bouclage et link-local sont refusées.
  • Au plus 10 endpoints actifs. Chacun s’abonne à une liste de types d’événements, ou à ["*"] pour tous (par défaut).
  • Le secret de signature (whsec_ suivi de 64 caractères hexadécimaux) n’est renvoyé qu’une fois : à la création de l’endpoint, puis à chaque changement de secret. Gardez-le comme un mot de passe.
  • Pour le changer, appelez POST /v1/webhooks/{id}/rotate-secret. L’ancien secret continue de signer, en second v1 dans l’en-tête, pendant keep_previous_hours (de 0 à 72, 24 par défaut). Déployez le nouveau secret dans ce délai et aucun événement n’est perdu.

Vérifier les signatures

Chaque livraison porte Advanta-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256>. Vérifiez-la avant de vous fier au corps :

  1. Lisez le corps brut de la requête, exactement tel qu’il a été reçu, avant toute analyse JSON.
  2. Calculez le HMAC-SHA256 de <t>.<raw body>, avec le secret de l’endpoint comme clé (la chaîne whsec_… complète, en UTF-8), et encodez-le en hexadécimal.
  3. Acceptez la livraison si l’un des v1 de l’en-tête correspond, comparé en temps constant (après un changement de secret, il y en a deux), et si t est à moins de 300 secondes de votre horloge. Sinon, rejetez-la.

Une livraison rejetée ne répond pas 2xx : Advanta la retente comme tout autre échec.

Node.js
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();
});
Python
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 "", 200

Erreurs

Chaque erreur est du JSON, avec un code stable et un message destiné aux personnes. Décidez d’après le code, jamais d’après le message.

JSON
{
  "error": {
    "code": "not_routed_to_you",
    "message": "This request is not assigned to your institution. Advanta operations routes requests."
  }
}

Codes de statut

StatutCodesSignification
400reason_requiredUn refus sans reason ni notes.
401unauthorized, key_expiredunauthorized : la clé est absente, mal formée, inconnue, révoquée ou inactive. key_expired : la clé a expiré.
403forbidden, not_your_request, export_live_key_required, not_routed_to_you, not_your_claimforbidden : la clé n’a pas la portée, ou le financeur n’est pas actif. not_your_request : un règlement par un financeur qui n’est pas celui de la demande. export_live_key_required : une clé sandbox n’exporte pas. not_routed_to_you : annoncer une demande qui ne vous est pas adressée. not_your_claim : clore une réclamation de recours qui ne porte pas sur une de vos demandes.
404not_foundAucune ressource visible pour cette clé, ou une route inconnue.
405method_not_allowedLa méthode n’est pas prise en charge sur ce chemin.
409not_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_failedUne écriture que la demande ne permet pas : elle ne vous est pas adressée, le statut ne convient pas, elle dépasse une de vos limites, une notification d’affacturage pas encore confirmée, un débiteur hors de votre liste, un document exigé du cédant manquant ou périmé, ou un niveau de consentement qui baisserait, arrive après la réponse d’un débiteur, ou vise une demande qui n’est pas de l’affacturage ou n’est pas en cours. Aussi un relevé déjà importé, plus de 10 endpoints actifs, un nom de prescripteur que vous utilisez déjà, un lien qui fonctionne encore (envoyez replace: true), et un lien d’entrée en relation pour une entreprise ou un contact qui a déjà un compte ou une invitation en attente, ou dans un pays dont Advanta n’accepte pas encore de cédants. Un export est encore en cours de génération (export_in_progress, export_not_ready) ou a échoué (export_failed).
410export_expiredexport_expired : les fichiers de l’export pouvaient être téléchargés pendant 24 heures ; lancez un nouvel export.
413file_too_large, too_many_lines, too_many_rowsLe relevé dépasse 4 Mio ou compte plus de 5 000 opérations, ou un import de limites compte plus de 2 000 lignes (too_many_rows).
422invalid_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_dateUn champ ou un paramètre manque ou n’est pas valide ; le code dit lequel. (Un refus sans motif donne 400 reason_required ; un changement de paramètres ou de niveau sans motif donne 422 reason_required.) Aussi un changement de conditions pour une entreprise hors de votre programme (seller_not_in_programme), une demande déjà annoncée ou close (already_announced, request_closed), et une réclamation de recours qui n’est plus ouverte ou close de la mauvaise façon (claim_closed, close_invalid). Sont aussi refusés un import de limites sans lignes (rows_required), avec une source autre que import ou insurer (invalid_source) ou avec une source_ref qui n’est pas du texte ou dépasse 200 caractères (source_ref_invalid, source_ref_too_long), et une date des opportunités qui n’est pas un jour du calendrier (invalid_date).
429rate_limited, export_rate_limitedrate_limited : plus d’appels que la limite de la clé (120 par minute et 3 000 par heure, sauf si Advanta en a fixé une autre pour la clé), ou des appels répétés avec une clé inconnue depuis une même adresse ; renvoyez-le après Retry-After secondes. export_rate_limited : au plus 10 exports en 24 heures.
500internal, query_failed, write_failed, ingest_failedUne erreur côté Advanta. Réessayez plus tard.

debtor_not_eligible_for_funder

Quand vous n’acceptez que les acheteurs de votre liste, une offre sur une demande avec un débiteur hors liste répond 409 avec les débiteurs qui la bloquent, chacun avec un reason :

JSON
{
  "error": {
    "code": "debtor_not_eligible_for_funder",
    "message": "…",
    "debtors": [
      {
        "debtor_key": "A00000000",
        "name": "Example Buyer, S.A.",
        "country": "ES",
        "reason": "not_listed",
        "invoices": 2
      }
    ]
  }
}
reasonSignification
not_listedLe débiteur n’est pas sur votre liste.
refusedVotre limite sur le débiteur est au statut refusé.
suspendedVotre limite sur le débiteur est suspendue.
no_tax_idUne facture n’a pas le numéro fiscal de l’acheteur.
invoice_missingUne ligne de la demande n’a pas de facture.
no_invoicesLa demande n’a aucune facture.

documents_missing_for_funder

Quand un document que vous exigez du cédant manque, n’est pas vérifié ou n’est plus valide, une offre ou un financement répond 409 avec les documents qui le bloquent, chacun avec un reason :

JSON
{
  "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"
      }
    ]
  }
}
reasonSignification
missingLe cédant n’a pas fourni le document.
unverifiedAdvanta ne l’a pas encore vérifié.
expiredIl n’est plus valide à cette date.
rejectedAdvanta l’a rejeté.
no_validity_dateIl n’a pas de date de validité.
not_in_catalogueLe code n’est pas dans le catalogue du pays du cédant.

Versions et limites

Le chemin porte la version majeure, /v1. Au sein de la v1, des champs et des types d’événements peuvent être ajoutés : ignorez ce que vous ne connaissez pas.

api_version, dans GET /v1/me et dans chaque événement de webhook, indique la révision que vous lisez : aujourd’hui, 2026-09-23.

Chaque clé peut faire 120 appels par minute et 3 000 par heure, comptés sur tous les serveurs d’Advanta (les opérations d’Advanta peuvent fixer une autre limite pour une clé). Un appel au-delà de la limite reçoit 429 rate_limited, avec un en-tête Retry-After en secondes et retry_after_seconds, limit et window_seconds dans l’erreur : rien de ce qu’il demandait n’a été fait, renvoyez-le donc après ce délai. Des appels répétés avec une clé inconnue ou mal formée depuis une même adresse reçoivent aussi 429. GET /v1/health n’est pas limité, et les exports gardent leur propre limite (export_rate_limited).

Tout ce qui figure sur cette page est décrit dans openapi.yaml (OpenAPI 3.1). Des questions, ou une clé : diogo@advanta.pt.