GET/v1/health
Se a API está a funcionar. Pública: sem chave, sem dados, sem acesso à base de dados.
A Advanta consulta esta rota a cada 5 minutos; os resultados estão na página de estado pública.
curl -s "$BASE/v1/health"Advanta / Bancos e financiadores / Programadores
O seu próprio sistema lê os pedidos de financiamento que a Advanta lhe encaminha, envia as suas decisões, define o que exige antes de financiar, gere os seus limites, envia o seu extrato bancário para conciliação, convida os seus próprios clientes e fornecedores e recebe webhooks assinados quando algo acontece. Cada escrita tem o mesmo efeito que a mesma ação no portal do financiador. E leva todos os seus dados, quando quiser: o seu direito de saída.
Um só URL base serve chaves live e de sandbox: é a chave que decide o que vê.
https://bzsengbmlzzhztjfvcag.supabase.co/functions/v1/funder-apiAuthorization: Bearer adv_fk_… em cada chamada: adv_fk_ seguido de 64 caracteres hexadecimais.Comece por GET /v1/me: diz a que financiador pertence a chave, o seu ambiente e os seus âmbitos. Depois, liste os pedidos que lhe foram encaminhados.
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 assim:
{
"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"
}
}Há um só URL base. É a chave que decide o ambiente, e GET /v1/me devolve-o em environment.
| environment | O financiador | O que a chave vê |
|---|---|---|
live | Classificado pela Advanta como real ou piloto. | Apenas clientes reais. |
sandbox | Um financiador de demonstração. | Apenas empresas fictícias, no plano de demonstração. |
unclassified | Ainda não classificado pela Advanta. | Nenhum pedido. |
Um pedido do outro plano nunca é visível, seja qual for a chave.
key.prospect em GET /v1/me). Como qualquer chave, é mostrada uma só vez e apenas o seu SHA-256 fica guardado.key.expires_at); a partir daí, todas as chamadas respondem 401 key_expired. A Advanta também a pode revogar a qualquer momento.decisions:write. Os prescritores e as ligações do financiador de demonstração são partilhados por todas as demonstrações.Pode ter uma chave de sandbox hoje: o seu próprio sistema contra os nossos dados de demonstração, antes de qualquer contrato. Escreva para diogo@advanta.pt. A chave real é emitida no dia em que quiser ligar-se.
Cada chamada leva Authorization: Bearer adv_fk_<64 hex>. As chaves são emitidas pelas operações da Advanta e pertencem a um financiador. Uma chave é mostrada uma só vez, apenas o seu SHA-256 fica guardado, e pode expirar.
Cada chave tem âmbitos. Uma chamada para a qual a chave não tem âmbito responde 403 forbidden.
| Âmbito | O que permite |
|---|---|
requests:read | Ler pedidos (GET /v1/requests, GET /v1/requests/{id} e os seus documentos). Também lê as suas definições e os documentos que exige, os livros de limites, o histórico de pagador, os seus clientes (prescritores, ligações, convites e o relatório), as suas ligações de adesão, os seus endpoints de webhook e os respetivos registos de entregas. Também lê os termos do seu programa (GET /v1/programme), os acionamentos de recurso (GET /v1/recourse), os seus dados bancários (GET /v1/bank-data), e as notificações de um pedido e o fluxo de caixa que o cedente partilha consigo. |
limits:read | Ler os livros de limites (GET /v1/credit-limits, GET /v1/seller-limits) e o histórico de pagador. |
limits:write | Definir, rever ou recusar limites (PUT /v1/credit-limits, PUT /v1/seller-limits). |
decisions:write | Propor, recusar, financiar e liquidar (POST /v1/requests/{id}/decision), e subir o que os devedores de um pedido têm de assinar (POST /v1/requests/{id}/consent-level). Também permite todas as escritas em definições, limites, extratos, clientes, ligações de adesão e endpoints de webhook, e ler os endpoints de webhook, os clientes e as ligações de adesão. Também permite exportar todos os seus dados. Também anuncia um pedido confidencial (POST /v1/requests/{id}/announce), fecha um acionamento de recurso (POST /v1/recourse/{id}/close) e altera os termos do seu programa. |
settings:write | Alterar o que os seus devedores têm de assinar antes de financiar (PUT /v1/settings) e os documentos que exige aos cedentes (PUT /v1/required-documents). Também os termos do seu programa (PUT /v1/programme). |
statements:write | Enviar um extrato bancário (POST /v1/statements). |
clients:write | Gerir os seus clientes: adicionar e desativar prescritores (POST /v1/prescribers, POST /v1/prescribers/{id}/disable), emitir, substituir e desativar ligações (POST /v1/client-links, POST /v1/client-links/{id}/disable), e lê-los, bem como os convites e o relatório. |
webhooks:write | Gerir endpoints de webhook: criar, parar, rodar o segredo, enviar um teste, e ler a lista e os registos de entregas. |
onboarding:write | Criar ligações de adesão para os seus fornecedores (POST /v1/onboarding-links) e lê-las. |
exports:write | Exportar todos os seus dados (POST /v1/exports, GET /v1/exports, GET /v1/exports/{id} e os seus documentos). Só chaves de produção. |
Os caminhos são relativos ao URL base. Qualquer chamada pode responder 401 (unauthorized ou key_expired), uma chamada que precise de um âmbito pode responder 403 forbidden (a chave não tem o âmbito, ou o financiador não está ativo), e 500 significa tentar mais tarde. Não se repetem abaixo; a secção Erros lista todos os códigos.
A que financiador pertence uma chave, o seu ambiente e os seus âmbitos. Comece por aqui.
/v1/healthSe a API está a funcionar. Pública: sem chave, sem dados, sem acesso à base de dados.
A Advanta consulta esta rota a cada 5 minutos; os resultados estão na página de estado pública.
curl -s "$BASE/v1/health"/v1/meQuem está a chamar: a chave, o seu financiador, o seu ambiente e os seus âmbitos.
key.prefix são os primeiros 12 caracteres da chave. key.expires_at é null para uma chave que não expira; key.prospect indica a quem foi emitida uma chave 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"
}
}Leia os pedidos que a Advanta lhe encaminhou e depois proponha, recuse, financie ou registe dinheiro recebido; e exija mais aos devedores de um pedido quando precisar.
/v1/requestsOs pedidos que lhe foram encaminhados (pode agir sobre eles) e aqueles sobre os quais já agiu (só leitura, mesmo depois de um reencaminhamento), do mais recente para o mais antigo, cada um com a sua própria oferta em my_offer, se a fez.
| Nome | Em | Descrição |
|---|---|---|
status | query | open (por omissão: pending, submitted, under_review, terms_sent, accepted, approved), all, ou um só estado. |
limit | query | De 1 a 200, 50 por omissão. |
Um pedido traz id, request_ref, type (factoring ou confirming), status, total_amount, advance_amount, o cedente em company_name e company_nif, invoice_count, assigned_bank_id, consent_level_required (o que cada devedor tem de assinar antes de o pedido poder ser financiado, fixado quando foi encaminhado), as suas datas e, por devedor, debtor_consent. A especificação lista todos os 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}O dossiê de análise de um pedido: o pedido, os seus créditos, o Advanta Score mais recente do cedente, a sua própria oferta e risk, os sinais de fraude e as contestações do pedido, tal como o seu portal os mostra.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
score vai de 300 a 850, com uma classe de A a E e as suas dimensões. É calculado na hora quando o cedente ainda não tem nenhum, e é null se isso falhar. Cada crédito tem invoice_no, invoice_amount, invoice_date, invoice_due_date e o devedor em customer_name. debtor_consent dá, por devedor, o estado da notificação, o nível exigido e o nível assinado (level_achieved), meets_requirement, o canal, o texto da declaração assinado e quem o assinou.
risk.signals lista os sinais de fraude ainda abertos ou confirmados, cada um com um code estável (por exemplo amount_above_history) e uma severity. Um sinal hard (por exemplo um montante alterado enquanto a fatura está num pedido, uma nota de crédito sobre ela ou uma contestação em aberto) trava o encaminhamento e o financiamento até a equipa de operações da Advanta o rever; os outros apenas assinalam. risk.disputes lista todas as contestações registadas contra o pedido.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/requests/{id}/decisionPropor condições, recusar, financiar ou registar uma liquidação. O pedido tem de lhe estar encaminhado; caso contrário, 409 not_routed_to_you.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
O corpo tem uma de quatro formas, escolhida por decision:
decision | Campos | Efeito |
|---|---|---|
offer | rate (percentagem, acima de 0 e até 100) e advance_pct (mesmo intervalo), ambos obrigatórios; days, notes, valid_days (de 1 a 90). | Envia as suas condições e passa um pedido pending, submitted ou under-review para terms_sent. A oferta expira ao fim de valid_days ou, sem ele, da validade configurada (7 dias por omissão). Recusada com 409 credit_limit quando um dos seus limites não a comporta, com 409 debtor_not_eligible_for_funder quando só aceita compradores da sua lista e um devedor não está nela, e com 409 documents_missing_for_funder quando um documento que exige ao cedente falta, não está verificado ou expirou. |
decline | reason ou notes, pelo menos um; notes é a mensagem que o cedente lê. internal_note opcional: fica para a sua equipa, nunca é mostrada ao cedente. | Fecha o pedido. reason é um de payer_credit, invoice_ineligible, documentation, concentration, amount_out_of_range, sector_excluded, no_funder_capacity, withdrawn_by_client ou other; texto livre fica guardado como nota com o motivo other. |
fund | value_date (AAAA-MM-DD, a data-valor da sua transferência para o cedente, até 7 dias à frente) e reference (a referência da transferência, 3 a 140 caracteres); amount opcional, verificado contra o adiantamento aceite. | Só depois de o cedente aceitar as suas condições (estado approved). Em factoring, a notificação de cada devedor tem de estar confirmada antes (caso contrário, 409 funding_gate_failed), e os documentos que exige ao cedente têm de estar válidos na data do financiamento (caso contrário, 409 documents_missing_for_funder). |
settle | amount (obrigatório); received_at (por omissão agora, no máximo um dia à frente); reference (até 140 caracteres); note (até 1000); final. | Regista dinheiro recebido num pedido financiado. Os pagamentos parciais somam-se; o pedido passa a settled quando o total atinge o montante do pedido ou final é 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 o que os devedores de um pedido têm de assinar. Só para cima, só num pedido de factoring que lhe está encaminhado e em curso, e só antes de algum dos seus devedores ter respondido.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
level obrigatório | body | receipt, acknowledgment ou acceptance, do mais baixo para o mais alto. |
reason obrigatório | body | Porquê, com pelo 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"}'O que tem de estar em ordem antes de financiar: os documentos que exige aos cedentes, por país do cedente, e o que cada devedor tem de assinar. Cada pedido guarda as versões que cumpriram as suas exigências.
/v1/requests/{id}/documentsO dossiê documental de um pedido. Quando o pedido lhe foi encaminhado, e de novo quando foi financiado, a Advanta registou que versão de cada documento que exige o satisfez: o nome do ficheiro, o SHA-256, as datas de emissão e de validade, e quando e como a Advanta o verificou. Esse registo nunca muda, mesmo quando o cedente carrega versões mais recentes; cada entrada diz também em que ponto está hoje o documento, e current lista os documentos atuais do cedente.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
Cada entrada com ficheiro traz um download_url válido durante dois minutos (url_expires_in), e cada URL emitido fica registado. Compare o SHA-256 do que descarregar com o registado.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/documents" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/required-documentsOs documentos que exige aos cedentes, por país do cedente, e o catálogo de onde são escolhidos: o código de cada documento, o nome em sete línguas, a entidade emissora, a validade habitual e a sensibilidade. A validade habitual só serve de pré-preenchimento: conta a data impressa no documento, que o cedente regista e a Advanta verifica.
Um pedido só lhe é encaminhado, a sua oferta só é registada e o pedido só é financiado enquanto todos os documentos da sua lista para o país do cedente estiverem verificados pela Advanta e válidos nessa data; caso contrário, 409 documents_missing_for_funder.
curl -s "$BASE/v1/required-documents" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/required-documentsSubstituir a sua lista para um país de cedentes; uma lista vazia apaga-a. Os códigos vêm do catálogo, e a alteração fica guardada na cadeia de evidências da Advanta com note. Os pedidos que já tem continuam consigo; a sua próxima oferta ou financiamento num deles espera até o cedente cumprir a nova lista (open_requests_not_meeting conta-os).
| Nome | Em | Descrição |
|---|---|---|
country obrigatório | body | O país do cedente, duas letras. |
codes obrigatório | body | Códigos de documento do catálogo. |
note | body | Até 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/settingsO que os seus devedores têm de assinar antes de financiar: o nível que cada devedor tem de assinar antes de um pedido de factoring encaminhado para si poder ser financiado (receipt, depois acknowledgment, depois acceptance), se só contam textos de declaração aprovados por um advogado, os seus pedidos em aberto por nível, e que níveis tem cada lei aplicável em texto de declaração, e em que línguas.
curl -s "$BASE/v1/settings" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/settingsAlterar o que os seus devedores têm de assinar. A alteração aplica-se aos pedidos encaminhados para si a partir desse momento; um pedido já encaminhado mantém o nível com que foi encaminhado. reason fica guardado na cadeia de evidências da Advanta.
| Nome | Em | Descrição |
|---|---|---|
debtor_consent_level | body | receipt, acknowledgment ou acceptance. |
require_counsel_approved_texts | body | true para contar apenas textos de declaração aprovados por um advogado. |
reason obrigatório | body | Porquê, com pelo 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"}'Escolha, por omissão e por empresa, se cada devedor é notificado antes de financiar (anunciado) ou se a notificação fica preparada e pronta a enviar (confidencial), com ou sem recurso, e se pede os dados bancários do cedente. Depois, anuncie um pedido confidencial, leia as suas notificações e o fluxo de caixa que o cedente partilha consigo, e acompanhe os seus acionamentos de recurso.
/v1/programmeOs termos do seu programa: os seus termos por omissão, os termos que definiu para empresas concretas, as empresas para as quais pode definir termos (as que têm um pedido encaminhado para si e os seus próprios clientes) e os seus pedidos de factoring contados pelos termos que têm. Um pedido recebe os termos em vigor quando é encaminhado para si e mantém-nos.
disclosure: announced (por omissão): cada devedor é notificado e confirma a cessão antes de financiar. confidential: quando o pedido é encaminhado para si, a notificação a cada devedor é preparada, com a sua impressão digital (SHA-256), e guardada pronta a enviar, e o financiamento não espera pelo devedor. Antes de financiar, todas as verificações bloqueantes das faturas têm de passar, as faturas têm de vir da contabilidade do próprio cedente (ERP, fatura eletrónica ou SAF-T), cada devedor tem de ter uma notificação preparada e atual que o nomeia a si e um endereço para onde enviá-la, e a verificação do cedente tem de estar aprovada. As notificações são enviadas quando anuncia o pedido e, automaticamente, num pedido financiado, quando se cumpre um gatilho que ativou: announce_overdue_days, announce_on_dispute, announce_on_kyc_lapse.
recourse: with (com recurso) ou without (sem recurso). recourse_days: dias depois do vencimento de uma fatura até um pedido financiado ainda não liquidado abrir um acionamento (null: nenhum). bank_data: off, requested (pede-se ao cedente que ligue a sua conta bancária empresarial para si, só de leitura e com o seu consentimento) ou required (o financiamento espera também que a conta para onde paga seja confirmada como sendo do próprio 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/programmeAlterar os seus termos por omissão (sem seller_id) ou os de uma empresa. Só mudam as chaves que enviar; {"reset": true} com um seller_id devolve essa empresa aos seus termos por omissão. A alteração aplica-se aos pedidos encaminhados para si a partir desse momento; os pedidos já encaminhados mantêm os seus termos. reason fica guardado na cadeia de evidências da Advanta.
| Nome | Em | Descrição |
|---|---|---|
seller_id | body | O id de uma empresa, de sellers em GET /v1/programme. Ausente ou null: os seus termos por omissão. |
terms obrigatório | body | Os termos a alterar: disclosure, recourse, recourse_days, announce_overdue_days, announce_on_dispute, announce_on_kyc_lapse, bank_data; ou reset. |
reason obrigatório | body | Porquê, com pelo 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 um pedido confidencial encaminhado para si: passa a anunciado e as notificações preparadas para ele são enviadas aos devedores, que depois as confirmam como num programa anunciado. Possível enquanto o pedido está pendente, em análise, com condições enviadas, aprovado ou financiado. Segue-se um evento request.announced; depois de uma notificação enviada, o pedido fica anunciado.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
reason obrigatório | body | Porquê, com pelo menos 8 caracteres. Fica guardado na cadeia de evidências da 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}/noticesAs notificações de cessão do pedido, uma por devedor, cada uma com o seu documento preparado quando existe: o assunto e o HTML exatos que o devedor recebe, a língua, a lei aplicável e o SHA-256. Para um pedido encaminhado para si, ou um em que já atuou.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
O HTML tem um marcador, ACK_LINK entre chavetas duplas, onde vai a ligação de confirmação do devedor; a ligação contém um segredo e nunca é mostrada. current diz se o documento ainda corresponde às faturas e ao montante da notificação.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/notices" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/requests/{id}/cash-flowO que o cedente partilha consigo da sua conta bancária empresarial, só de leitura e com o seu consentimento, através de um prestador licenciado de informação sobre contas: a ligação, as contas (os últimos quatro caracteres de cada IBAN) e os saldos, doze meses de movimentos por mês e a verificação da sua conta de pagamento. cash_flow é null enquanto o cedente não tiver ligado uma conta para si.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
bank_data_problems diz o que o financiamento ainda espera quando os seus termos exigem dados bancários. payment_alerts são os pagamentos que o cedente recebeu de um devedor deste pedido depois de o financiar em termos confidenciais. O consentimento de um cedente é dado a um financiador: só vê o que ele partilha consigo.
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/cash-flow" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/recourseOs seus pedidos de factoring financiados por tipo de recurso (with, without, e not_recorded para os encaminhados antes de 28 de setembro de 2026), os acionamentos contados por tipo e estado, e os próprios acionamentos, primeiro os abertos. Abre-se um acionamento por pedido quando um pedido financiado não está liquidado recourse_days depois do vencimento de uma fatura: recourse, contra o cedente, pelo montante adiantado mais as suas comissões, menos o que já cobrou; debtor_default, sem recurso, para a sua própria cobrança e seguro.
| Nome | Em | Descrição |
|---|---|---|
status | query | open, settled, withdrawn ou written_off. Ausente: todos os acionamentos. |
O cedente reembolsa um acionamento de recurso para pay_to_iban indicando pay_reference. Quando os pagamentos que registar a partir daí (uma linha de extrato que confirma, ou a decisão settle) cobrem claim_amount, o acionamento fica liquidado e o pedido fecha como liquidado por recurso: as faturas voltam ao cedente, ainda por pagar pelo devedor.
curl -s "$BASE/v1/recourse?status=open" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/recourse/{id}/closeFechar um acionamento seu em aberto: um acionamento de recurso fica withdrawn (prescindiu dele, ou acordou outra coisa com o cedente), um incumprimento do devedor fica written_off (passou para a sua cobrança ou para a sua seguradora). reason fica guardado na cadeia de evidências da Advanta.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do acionamento (claim_id). |
status obrigatório | body | withdrawn ou written_off. |
reason obrigatório | body | Porquê, com pelo 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-dataA sua própria conta de cobrança, ligada pelo seu administrador no portal e lida da mesma forma: os movimentos passam pela mesma conciliação que POST /v1/statements, para que as cobranças correspondam aos seus pedidos financiados sem enviar ficheiros. Também quantos cedentes partilham a conta consigo, os alertas de pagamento nos seus pedidos (os últimos 180 dias) e os custos do prestador registados em seu nome, por mês.
unit_price_eur e amount_eur são null até o preço do prestador estar fixado.
curl -s "$BASE/v1/bank-data" \
-H "Authorization: Bearer $ADVANTA_KEY"A sua exposição por devedor e por cedente, aplicada pela própria plataforma, com limites definidos um a um ou até 2000 de uma vez; como um comprador paga aos seus fornecedores; e o que a Advanta sabe de cada devedor de um pedido.
/v1/credit-limitsO seu livro por devedor: o seu limite e o que está em dívida, comprometido, oferecido e ainda disponível, em euros.
Cada devedor traz debtor_key, debtor_name, debtor_country, limit_status, limit_amount, outstanding, committed, offered, available, overdue_count, oldest_overdue, frozen, decided_at e note.
curl -s "$BASE/v1/credit-limits" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/credit-limitsDefinir ou rever o seu limite para um devedor, ou recusar o devedor. A base de dados recusa qualquer oferta posterior que este limite não comporte.
| Nome | Em | Descrição |
|---|---|---|
debtor_tax_id obrigatório | body | O NIF ou número de IVA do devedor. |
debtor_country | body | ISO 3166 alfa-2. |
debtor_name | body | O nome do devedor. |
amount | body | Euros, 0 ou mais. Obrigatório para um limite ativo. |
status | body | active (por omissão), refused ou suspended. |
note | body | Texto livre. |
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/importCarregar até 2000 limites sobre devedores numa só chamada: o seu próprio livro, ou os limites da sua seguradora de crédito. Cada linha é verificada exatamente como PUT /v1/credit-limits verifica um limite e tem a sua própria resposta: uma linha que falha não trava as outras, e um devedor que aparece duas vezes na mesma chamada é recusado da segunda vez.
| Nome | Em | Descrição |
|---|---|---|
rows obrigatório | body | De 1 a 2000 linhas, cada uma com debtor_tax_id e, como em PUT /v1/credit-limits, debtor_country, debtor_name, amount, status e note. amount é um número ou dígitos com ponto decimal; é obrigatório para um limite ativo. Também é aceite só a lista de linhas, sem o objeto à volta (com source import). |
source | body | import (os seus próprios limites, por omissão) ou insurer (os limites da sua seguradora de crédito). |
source_ref | body | O ficheiro ou lote de onde vêm os limites, no máximo 200 caracteres. |
Cada limite escrito regista a sua origem e referência, no limite e no seu histórico. A resposta conta received, written e refused, e responde a cada linha com row (a contar de 1), debtor_tax_id e ok: uma linha escrita acrescenta debtor_key, status e amount; uma linha recusada dá o seu error (invalid_amount, debtor_tax_id_required, duplicate_debtor, invalid_status, amount_required, invalid_country, row_invalid ou invalid_limit) e pode acrescentar um 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-limitsO seu livro por cedente, com os mesmos números do livro de devedores.
Cada cedente traz seller_id, seller_name, seller_nif, seller_country e os mesmos campos de limite e exposição de um devedor.
curl -s "$BASE/v1/seller-limits" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/seller-limitsDefinir ou rever o seu limite para um cedente, ou recusar o cedente.
| Nome | Em | Descrição |
|---|---|---|
seller_id obrigatório | body | Tal como devolvido por GET /v1/seller-limits. |
amount | body | Euros, 0 ou mais. |
status | body | active (por omissão), refused ou suspended. |
note | body | Texto livre. |
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-recordComo um comprador paga aos seus fornecedores, só em agregado, a partir da contabilidade dos fornecedores ligados à Advanta. O histórico é publicado quando pelo menos três fornecedores observam o comprador; caso contrário, status diz porquê e todos os números são null. Só o pode ler para um comprador num pedido no seu âmbito ou na sua lista de devedores; uma chave de sandbox lê o histórico do plano de demonstração.
| Nome | Em | Descrição |
|---|---|---|
tax_id obrigatório | query | O NIF ou número de IVA do comprador. |
country | query | ISO 3166 alfa-2. |
Os números incluem observers, invoice_count, avg_days_to_pay, median_days_to_pay, on_time_pct, o atraso no pagamento (avg_settle_delay_days, median_settle_delay_days, p75_settle_delay_days, worst_settle_delay_days), contagens em aberto e vencidas, window_from e refreshed_at. payer_record é null quando não há histórico.
curl -s "$BASE/v1/payer-record?tax_id=A00000000&country=ES" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/requests/{id}/debtorsO que a Advanta sabe de cada devedor de um pedido de factoring encaminhado para si, ou de um em que já atuou: o seu level na Advanta desde level_since (notice: conhece a Advanta só pela notificação; account: ativou a sua conta de pagador; books: ligou o seu sistema de contabilidade; buyer: tem um programa de comprador, e buyer_programme é true), o histórico do próprio cedente com ele, o seu prazo médio de pagamento oficial quando é uma entidade pública, e o seu limite sobre ele.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do pedido. |
score é a pontuação do próprio devedor (classe, de 0 a 100, quando e com que versão do modelo). Só é dada quando o devedor partilha os seus dados com os financiadores que financiam faturas devidas por ele, está no nível books ou buyer, e o pedido está encaminhado para si (não um em que só atuou); caso contrário é null. pair_history é o histórico do cedente com este devedor ao longo de 36 meses, com as regras do histórico de pagador: só faturas reais, e atraso só face a datas de vencimento indicadas no documento ou no ERP. public_payment_period é o prazo médio de pagamento oficial mais recente de uma entidade pública (DGAL para os municípios portugueses, Hacienda para as entidades locais espanholas). credit_limit é o seu limite sobre o devedor, de onde veio (source, source_ref) e o que está usado (exposure: em dívida mais comprometido mais oferecido, em euros).
curl -s "$BASE/v1/requests/4c1e0d2a-8f3b-4f6e-9a55-3c2b1d0e9f87/debtors" \
-H "Authorization: Bearer $ADVANTA_KEY"Envie o extrato da sua conta de cobrança e cada crédito é conciliado com os seus pedidos financiados; confirma cada correspondência no portal. Para registar um pagamento diretamente, envie a decisão settle.
/v1/statementsEnviar o extrato da sua conta de cobrança para conciliação: um ficheiro CAMT.053 (XML) ou CSV, no máximo 4 MiB e 5000 movimentos. Cada crédito é conciliado com os seus próprios pedidos financiados, primeiro pela referência que o devedor indicou. Nada é liquidado até confirmar uma correspondência no portal. O mesmo ficheiro enviado duas vezes é recusado, pelo seu SHA-256.
| Nome | Em | Descrição |
|---|---|---|
file_name | query | O nome do ficheiro (opcional). |
kind | query | camt053 ou csv; detetado quando omitido. |
| o ficheiro obrigatório | body | O ficheiro original, enviado como application/xml ou text/csv; ou 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.xmlTraga os seus próprios clientes: uma ligação aberta sua, uma ligação por prescritor, e os convites e o relatório que mostram quem chegou por cada uma. As empresas que traz são encaminhadas só para si.
/v1/client-linksA sua própria ligação aberta (prescriber_id null) e a ligação atual de cada prescritor, com o seu state (active, disabled ou expired) e o seu url enquanto funciona.
| Nome | Em | Descrição |
|---|---|---|
lang | query | A língua da página que cada ligação abre: pt, es, en, fr, de, it ou nl, acrescentada ao seu url. |
Uma empresa que abre uma ligação indica o nome, o número fiscal, o país e o email, e recebe o seu convite por email. Quando o aceita, passa a ser sua cliente: os pedidos dela são encaminhados só para si, e a sua origem (a ligação, o prescritor, a data) fica registada. Abrir uma ligação nunca cria uma conta por si só.
Cada ligação traz também arrivals (as empresas cuja primeira chegada até si foi por ela) e claims_last_day (as adesões por ela nas últimas 24 horas; uma ligação aceita no máximo 20 por hora e 100 por dia).
curl -s "$BASE/v1/client-links?lang=es" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/client-linksEmitir a sua própria ligação aberta, ou a de um prescritor com prescriber_id. Há uma ligação ativa por titular: enquanto uma ainda funciona, envie replace: true para a substituir (a anterior deixa de funcionar de imediato); caso contrário, 409 link_exists. Só fica guardado o SHA-256 do token da ligação, e a emissão fica registada na cadeia de evidências da Advanta.
| Nome | Em | Descrição |
|---|---|---|
prescriber_id | body | Um dos seus prescritores ativos; omita-o, ou envie null, para a sua própria ligação. |
expires_at | body | Opcional: entre uma hora e três anos a partir de agora. |
replace | body | true para substituir uma ligação que ainda funciona. Por omissão false. |
reason | body | O motivo, até 200 caracteres. Fica guardado na ligação substituída e na cadeia de evidências. |
lang | body | A língua da página que a ligação abre, acrescentada ao seu url. |
Uma ligação emitida com uma chave de sandbox só gera convites de teste, e a chave precisa de decisions:write: as ligações do financiador de demonstração são partilhadas por todas as demonstrações.
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}/disableDesativar uma ligação. Deixa de funcionar de imediato; as empresas que já chegaram por ela mantêm a sua origem. Desativar uma ligação já desativada não muda nada (changed é false). Para dar uma nova, chame POST /v1/client-links.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id da ligação, de GET /v1/client-links. |
reason | body | O motivo, até 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/prescribersOs seus prescritores, as pessoas e empresas que lhe trazem clientes (contabilistas, consultores, intermediários), os ativos primeiro, cada um com a sua ligação atual e o número de empresas que chegaram por ela. São seus, não parceiros da Advanta. A mesma lista da página Clientes do seu portal.
| Nome | Em | Descrição |
|---|---|---|
lang | query | A língua da página que cada ligação abre: pt, es, en, fr, de, it ou nl, acrescentada ao seu url. |
Uma chave de sandbox lê os prescritores do financiador de demonstração, que todas as demonstrações partilham.
curl -s "$BASE/v1/prescribers?lang=es" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/prescribersAdicionar um prescritor. A sua própria ligação aberta é emitida com ele, em prescriber.link.url. O nome e o email dele ficam fora da cadeia de evidências da Advanta: só os seus hashes lá entram.
| Nome | Em | Descrição |
|---|---|---|
name obrigatório | body | De 2 a 120 caracteres, único entre os seus prescritores ativos. |
email | body | Opcional. Um financiador de sandbox só regista endereços reservados (terminados em .example, .invalid, .test ou .demo). |
notes | body | Opcional, até 1000 caracteres. |
lang | body | A língua da página que a ligação dele abre, acrescentada ao seu url. |
Com uma chave de sandbox isto altera o estado de demonstração partilhado, por isso a chave precisa de 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}/disableDesativar um prescritor. A ligação dele deixa de funcionar de imediato; as empresas que trouxe continuam atribuídas a ele. Desativar um prescritor já desativado não muda nada (changed é false). Fica registado na cadeia de evidências da Advanta.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do prescritor. |
reason | body | O motivo, até 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/reportO que cada prescritor lhe trouxe: um grupo por prescritor, depois a sua própria ligação (own_link), os seus convites pelo nome (named) e as suas ligações de adesão (api). Por grupo e por empresa: quando chegou, quando a conta foi aberta (joined), quando a verificação da empresa foi aprovada (onboarded), os pedidos encaminhados para si, o montante pedido e o montante financiado. Os mesmos números do seu portal.
Uma empresa conta uma vez, para quem a trouxe primeiro até si. O montante financiado é o adiantamento (ou, na falta dele, o total) dos pedidos financiados ou liquidados, em euros; totals soma todos os grupos. Só os seus dados e só empresas do seu plano de dados: uma chave de sandbox não vê o que outras chaves de sandbox fizeram pela 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-invitationsTodos os seus convites, os mais recentes primeiro: por uma ligação, pelo nome no portal ou com uma ligação de adesão. Cada um diz como a empresa chegou (via: link, named ou api), o prescritor que a trouxe, se houver, o seu state (pending, accepted, revoked ou expired), a empresa, o contacto e as datas.
| Nome | Em | Descrição |
|---|---|---|
limit | query | De 1 a 500, 200 por omissão. |
Só o seu próprio plano de dados. Uma chave de sandbox não vê os convites feitos por outras chaves de sandbox.
curl -s "$BASE/v1/client-invitations?limit=50" \
-H "Authorization: Bearer $ADVANTA_KEY"Todas as manhãs, as faturas dos seus próprios clientes que durante a noite passaram a cumprir as suas regras, e o que mudou nas que já lhe foram mostradas. O webhook opportunities.daily diz quando há algo para ler.
/v1/opportunitiesO resumo de um dia, dos seus próprios clientes (as empresas de que é o financiador de origem) que lhe permitem ver as faturas deles. Todas as manhãs, por volta das 06:30, hora de Madrid, depois da pré-qualificação noturna, a Advanta lista as faturas que passaram a cumprir as suas regras desde o resumo anterior (kind new) e o que mudou nas que já lhe foram mostradas: paid, disputed (o cliente registou que o devedor a contesta) ou no_longer_eligible.
| Nome | Em | Descrição |
|---|---|---|
date | query | O dia do resumo, YYYY-MM-DD (hora de Madrid). Ausente: o mais recente. Um dia sem resumo responde date null e nenhuma linha. |
Uma linha traz a fatura, o devedor com o seu NIF, o valor ainda em dívida, a data de vencimento, e o cliente com o seu setor (secção NACE), classe e dimensão; primeiro as linhas novas, depois as alterações. no_longer_eligible tem um reason: requested (o cliente pediu para a financiar), cancelled, removed (já não está nos livros do cliente), left_programme, not_shared (o cliente deixou de partilhar) ou rules (já não cumpre as suas regras).
digest tem os totais: quantos clientes partilham e quantos ainda não, o que é elegível hoje, o que é novo e o que mudou. stale é true quando a leitura noturna não terminou: nessa manhã nada foi comparado. Um resumo é uma lista calculada pela base de dados, não uma oferta: um pedido é verificado de novo quando é feito, e decide sobre ele como sempre. O webhook opportunities.daily diz quando há um resumo com 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" }
}
]
}Registe os endpoints que recebem os webhooks, rode os segredos, envie um teste e leia o registo de entregas.
/v1/webhooksOs seus endpoints ativos, sem os segredos, e os tipos de evento que pode subscrever. Uma chave de sandbox vê apenas os endpoints que criou.
curl -s "$BASE/v1/webhooks" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/webhooksRegistar um endpoint. A resposta traz o seu segredo de assinatura, que não volta a ser mostrado.
| Nome | Em | Descrição |
|---|---|---|
url obrigatório | body | https num nome de anfitrião público, porta 443, sem nome de utilizador nem palavra-passe; no máximo 2048 caracteres. Endereços privados, de loopback e link-local são recusados, e os redirecionamentos nunca são seguidos. |
events | body | Uma lista de tipos de evento, ou ["*"] para todos (por omissão). |
description | body | Até 200 caracteres. |
No máximo 10 endpoints ativos.
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}Parar um endpoint. As entregas ainda pendentes são canceladas e os seus segredos são apagados.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do endpoint. |
curl -s -X DELETE "$BASE/v1/webhooks/$WEBHOOK_ID" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/webhooks/{id}/rotate-secretUm novo segredo de assinatura, mostrado uma só vez. O segredo anterior continua a assinar, como segundo v1 no cabeçalho, durante keep_previous_hours, para poder mudar sem perder eventos.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do endpoint. |
keep_previous_hours | body | De 0 a 72, 24 por omissão. |
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}/testPôr em fila um evento webhook.test para este endpoint. A execução seguinte do despachante entrega-o, em cerca de um minuto.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do endpoint. |
curl -s -X POST "$BASE/v1/webhooks/$WEBHOOK_ID/test" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/webhooks/{id}/deliveriesO registo de entregas de um endpoint, do mais recente para o mais antigo: estado (pending, delivered, failed ou cancelled), tentativas, código de resposta, último erro, próxima tentativa e o SHA-256 do corpo exato enviado.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id do endpoint. |
limit | query | De 1 a 200, 50 por omissão. |
curl -s "$BASE/v1/webhooks/$WEBHOOK_ID/deliveries?limit=20" \
-H "Authorization: Bearer $ADVANTA_KEY"A partir do seu próprio produto, entregue a um fornecedor uma ligação de adesão da Advanta de uso único; o fornecedor volta a si com um estado assinado quando termina.
/v1/onboarding-linksUma ligação de adesão de uso único para um dos seus fornecedores, atribuída a si. A Advanta não envia email: entregue o url ao seu fornecedor. Quando o fornecedor tiver submetido a verificação da empresa, recebe onboarding.completed, e o fornecedor é reencaminhado para o seu return_url com um estado assinado.
| Nome | Em | Descrição |
|---|---|---|
company_vat obrigatório | body | O número de IVA ou fiscal do fornecedor, com ou sem o prefixo do país. |
country obrigatório | body | ISO 3166 alfa-2. |
contact_email obrigatório | body | O email do contacto do fornecedor. |
return_url obrigatório | body | https, até 2048 caracteres, numa origem da sua lista de origens de regresso. Essa lista é mantida nas definições do portal ou pela Advanta, nunca por esta API. |
company_name | body | De 2 a 200 caracteres. Pode ser omitido para um número de IVA da UE que o VIES consiga identificar. |
contact_name | body | Até 120 caracteres. |
metadata | body | As suas próprias chaves e valores: no máximo 20 chaves, valores texto, número, true, false ou null, 2 KB de JSON. Devolvidos na ligação e em onboarding.completed. |
locale | body | A língua da adesão: pt, es, en, fr, de, it ou nl. |
valid_days | body | De 1 a 30, 14 por omissão. |
A resposta traz return_secret (ors_ seguido de 64 caracteres hexadecimais), mostrado uma só vez: guarde-o já. Só fica guardado o SHA-256 do token da ligação. Uma ligação criada com uma chave de sandbox regista o fornecedor como empresa de teste no plano de demonstração.
Quando o fornecedor regressa, o return_url traz advanta_onboarding (o id da ligação), advanta_status (completed), advanta_ts (segundos Unix) e advanta_sig: o HMAC-SHA256 em hexadecimal de <advanta_onboarding>.<advanta_status>.<advanta_ts>, com o seu return_secret como chave. Verifique-o antes de a sua página confiar no estado e recuse um regresso a mais de 600 segundos do seu relógio; o último exemplo abaixo faz as duas coisas.
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-linksAs suas ligações de adesão, as mais recentes primeiro, cada uma com o seu status: pending, account_created, completed, expired ou revoked. Uma chave de sandbox vê as ligações que criou.
| Nome | Em | Descrição |
|---|---|---|
limit | query | De 1 a 200, 50 por omissão. |
curl -s "$BASE/v1/onboarding-links?limit=20" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/onboarding-links/{id}Uma ligação de adesão e em que ponto está o fornecedor. Depois de concluída, seller_id é o id que GET /v1/seller-limits usa.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id da ligação. |
curl -s "$BASE/v1/onboarding-links/$ONBOARDING_ID" \
-H "Authorization: Bearer $ADVANTA_KEY"Leve tudo o que pode ver na Advanta, quando quiser, sem pedir: o seu direito de saída (DORA art. 28.º, n.º 8, e art. 30.º, n.º 3, alínea f)). Um ZIP com um CSV e um ficheiro JSON Lines por entidade, schema.json, manifest.json com o SHA-256 de cada ficheiro, um README no seu idioma e verify.py.
/v1/exportsInicia uma exportação de tudo o que o seu financiador pode ver: pedidos e o seu histórico, ofertas, faturas com a sua verificação, vendedores (dados da empresa, o resumo KYC que pode ver, a verificação do representante), devedores, notificações com as respostas dos devedores e os dados dos certificados, as entradas da cadeia de evidência sobre as suas operações com os hashes e as raízes diárias para as verificar, liquidações e extratos, recusas dos controlos, as suas regras e limites, a sua equipa, endpoints de webhook (nunca um segredo), chaves de API (nunca uma chave), o seu registo de auditoria e os seus documentos. É gerada em segundo plano, normalmente em menos de um minuto; export.ready avisa quando.
| Nome | Em | Descrição |
|---|---|---|
lang | body | O idioma do README: pt, es, en, fr, de, it ou nl (en por omissão). |
Só uma chave de produção: uma chave de sandbox responde 403 export_live_key_required (o financiador de demonstração é partilhado). Uma exportação de cada vez, no máximo 10 em 24 horas. A mesma exportação está na página Exportação do portal, nas definições.
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/exportsAs suas exportações, do portal e da API, as mais recentes primeiro, com o estado, o tamanho e manifest_sha256.
| Nome | Em | Descrição |
|---|---|---|
limit | query | De 1 a 200, 50 por omissão. |
curl -s "$BASE/v1/exports?limit=20" \
-H "Authorization: Bearer $ADVANTA_KEY"/v1/exports/{id}Uma exportação. Enquanto é gerada: status queued ou running, com progress. Quando ready, e durante 24 horas: files, cada volume com uma ligação válida no máximo durante uma hora (nunca para lá dessas 24 horas). Peça de novo para ter ligações novas; cada chamada que devolve ligações fica registada. Ao fim de 24 horas os ficheiros são apagados e o registo fica.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id da exportação, de POST /v1/exports ou GET /v1/exports. |
manifest_sha256 é o SHA-256 do manifest.json escrito sem esse campo, com as chaves ordenadas e sem espaços. A Advanta registou o mesmo valor na cadeia de evidência (entrada export.ready); o verify.py recalcula-o e verifica cada ficheiro e as entradas de evidência.
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}/documentsQuando os documentos eram grandes demais para incluir (documents_mode links): cada documento da exportação com uma ligação válida durante 15 minutos, uma página de cada vez. A lista é calculada quando pede, por isso um documento que já não pode ler não aparece.
| Nome | Em | Descrição |
|---|---|---|
id obrigatório | path | O id da exportação. |
after | query | O next_after da página anterior. |
limit | query | De 1 a 200, 100 por omissão. |
curl -s "$BASE/v1/exports/5e1f0a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b/documents?limit=100" \
-H "Authorization: Bearer $ADVANTA_KEY"Registe um endpoint HTTPS e a Advanta envia-lhe um POST assinado quando acontece algo que lhe diz respeito: num pedido encaminhado para si ou no respetivo cedente, ou numa ligação de adesão que criou. Cada endpoint subscreve os tipos de evento de que precisa. Cada envio é assinado e, se falhar, repetido durante 24 horas.
| Evento | Quando | data |
|---|---|---|
request.routed | As operações da Advanta encaminharam-lhe um pedido. Já o pode ler e decidir. | request_id, request_ref, type, status, total_amount, currency, routed_at |
request.unrouted | Um pedido encaminhado para si foi encaminhado para outro lado ou deixou de estar encaminhado. Já não pode agir sobre ele. | request_id, request_ref, unrouted_at |
offer.accepted | A sua oferta foi aceite (request_status é approved quando o cedente aceitou). Pode financiá-la. | offer_id, request_id, request_ref, request_status, rate, advance_pct, days, accepted_at |
notice.acknowledged | Um devedor confirmou a notificação de cessão. Um evento por devedor; channel é online ou offline. | notice_id, request_id, request_ref, debtor_name, debtor_tax_id, invoice_count, total_amount, channel, decided_at |
notice.disputed | Um devedor rejeitou a notificação de cessão. Um evento por devedor. | Os campos de notice.acknowledged, mais reason: as palavras do devedor, no máximo 500 caracteres. |
request.funded | Um pedido encaminhado para si foi financiado. | Os campos do pedido de request.routed, mais funded_at e advance_amount. |
settlement.recorded | Foi registado dinheiro recebido num pedido financiado, parcial ou final: o pagamento que liquida o pedido tem final a true. | settlement_id, request_id, request_ref, amount, received_at, reference, received_total, request_total, outstanding, final, request_status |
seller.documents_expiring | Um documento com validade (por exemplo, uma certidão da Autoridade Tributária ou da Segurança Social) de um cedente com um pedido em aberto ou financiado encaminhado para si expira dentro de 30 dias, de 7 dias ou hoje. Verificado todos os dias; threshold_days é 30, 7 ou 0. | seller_id, company_name, company_tax_id, document_id, document_type, valid_until, days_left, threshold_days, request_ids |
dispute.opened | Um devedor contestou faturas de um pedido encaminhado para si, depois da aprovação ou do financiamento. reason é goods_not_received, defective, amount_incorrect, already_paid, not_our_invoice ou other; channel é 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.resolved | As operações da Advanta encerraram uma contestação; status é resolved_for_debtor, resolved_for_seller ou withdrawn. | Os campos de dispute.opened, com o seu status, mais resolved_at e resolution_note. |
onboarding.completed | Um fornecedor que convidou com uma ligação de adesão submeteu a verificação da empresa. status é completed; metadata é o seu, tal como o enviou. Para uma ligação criada com uma chave de sandbox, só os endpoints dessa chave o recebem. | onboarding_link_id, status, company_name, company_tax_id, country, seller_id, account_created_at, completed_at, verification_status, metadata |
client.joined | Uma empresa que convidou (pelo nome, pela sua ligação aberta, pela ligação de um prescritor ou pela API) aceitou o convite e passa a ser só sua: os pedidos dela chegam apenas a si. origin diz como chegou (named, open_link, prescriber ou api), com o prescritor quando existe. | 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 | Uma exportação que pediu (portal ou API) está pronta: descarregue-a com GET /v1/exports/{id} nas 24 horas seguintes. Leva o seu manifest_sha256, nunca uma ligação. | export_id, status, requested_via, manifest_sha256, size_bytes, file_count, documents_mode, volumes, completed_at, expires_at |
request.announced | Um pedido confidencial encaminhado para si foi anunciado: por si, pelas operações da Advanta ou por um gatilho que ativou (trigger é manual, overdue, dispute ou kyc_lapsed). As notificações preparadas estão a ser enviadas; notices lista cada uma com o SHA-256 do seu documento. | request_id, request_ref, trigger, reason, status, notices, announced_at |
recourse.opened | Um pedido seu financiado não está liquidado recourse_days depois do vencimento de uma fatura: um acionamento de recurso contra o cedente (kind recourse) ou um incumprimento do devedor (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 | Um acionamento foi liquidado: pelos pagamentos que registou desde que abriu (via statement ou manual; o pedido fecha como liquidado por recurso), ou porque o pedido foi liquidado da forma habitual (via request_settled, sem paid). | claim_id, request_id, request_ref, kind, claim_amount, paid, via, request_closed |
payment.reached_seller | Numa conta que o cedente partilha consigo, entrou um pagamento de um devedor de um pedido que financiou em termos confidenciais: a referência tem o número de uma fatura financiada (match_rule invoice_reference), ou o pagador e o montante correspondem (payer_and_amount). | alert_id, request_id, invoice_ids, payer_name, payer_iban, amount, currency, booking_date, match_rule, confidence |
opportunities.daily | O resumo da manhã tem algo: faturas dos seus próprios clientes que passaram a ser elegíveis desde o resumo anterior, ou uma alteração nas que já lhe foram mostradas. Só um sumário, contagens e totais, nunca uma fatura, um devedor ou um cliente: leia as linhas com GET /v1/opportunities?date= (lines). No máximo um por dia; nenhum num dia sem nada de novo e sem alterações. | 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 | Um boletim oficial (o BORME para as empresas espanholas, o Citius para as portuguesas) publicou um ato que bloqueia para novo financiamento um devedor de um pedido que financiou: insolvência declarada ou em curso, liquidação, insolvência encerrada por insuficiência de bens, dissolução, extinção, ou a folha de registo encerrada pela administração tributária ou após uma insolvência. Enquanto se mantiver, nenhuma nova oferta e nenhum novo financiamento vão para as faturas deste devedor. Um evento por pedido e por cada passagem a bloqueado. É o que o boletim publicou, para que o analise, não uma conclusão jurídica; só são vigiadas empresas de Espanha e de Portugal. | request_id, request_ref, debtor (country, tax_id, name), status, note, events (kind, published_on, source, url), detected_at |
pre_offer.accepted | Um cliente pediu o financiamento das faturas de uma pré-proposta que lhe enviou a partir das suas oportunidades da manhã: o pedido, feito com todas as verificações habituais, leva a pré-proposta e chega-lhe como sempre (request.routed), e a sua regra de crédito prepara a sua proposta a partir da sua tabela. terms é o que a sua tabela deu quando a enviou, indicativo: o preço é seu, a Advanta não indica nenhum. Uma vez por pré-proposta. | 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 | O evento de teste que pediu com POST /v1/webhooks/{id}/test. |
Cada entrega é um POST com um corpo JSON, enviado byte a byte tal como está guardado (o seu SHA-256 está no registo de entregas), com três cabeçalhos próprios:
Advanta-Signature: t=<unix seconds>,v1=<hex>, ver Verificar assinaturas.Advanta-Event-Id: o id do evento, também id no corpo.Advanta-Event-Type: o tipo de evento, também type no corpo.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 | O id do evento, igual a Advanta-Event-Id. |
object | Sempre event. |
type | Um dos tipos de evento acima. |
api_version | A revisão da API em que o evento está escrito. |
created | Quando o evento foi criado, em segundos Unix. |
environment | live, sandbox ou unclassified, como em GET /v1/me. |
data | Os campos do evento, listados acima. |
2xx em 10 segundos e o evento fica entregue. Qualquer outra resposta, nenhuma resposta em 10 segundos, ou um redirecionamento é uma falha; os redirecionamentos nunca são seguidos.failed e permanece no registo de entregas.Advanta-Event-Id que já processou e ignore uma repetição.GET /v1/webhooks/{id}/deliveries mostra o estado, as tentativas, o código de resposta, o último erro e a próxima tentativa de cada entrega. POST /v1/webhooks/{id}/test envia um evento webhook.test quando quiser verificar o seu endpoint.https num nome de anfitrião público, na porta 443, sem nome de utilizador nem palavra-passe. Endereços privados, de loopback e link-local são recusados.["*"] para todos (por omissão).whsec_ seguido de 64 caracteres hexadecimais) é devolvido uma só vez: quando o endpoint é criado e, de novo, sempre que o roda. Guarde-o como guardaria uma palavra-passe.POST /v1/webhooks/{id}/rotate-secret. O segredo anterior continua a assinar, como segundo v1 no cabeçalho, durante keep_previous_hours (de 0 a 72, 24 por omissão). Instale o novo segredo dentro desse prazo e nenhum evento se perde.Cada entrega traz Advanta-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256>. Verifique-a antes de confiar no corpo:
<t>.<raw body>, com o segredo do endpoint como chave (a cadeia whsec_… completa, em UTF-8), e codifique-o em hexadecimal.v1 do cabeçalho coincidir, comparado em tempo constante (depois de uma rotação há dois), e se t estiver a menos de 300 segundos do seu relógio. Caso contrário, rejeite-a.Uma entrega rejeitada não responde 2xx, por isso a Advanta volta a tentar, como em qualquer outra falha.
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 erro é JSON, com um code estável e uma message para pessoas. Decida pelo código, nunca pela mensagem.
{
"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 | Uma recusa sem reason nem notes. |
| 401 | unauthorized, key_expired | unauthorized: a chave falta, está mal formada, é desconhecida, foi revogada ou está inativa. key_expired: a chave expirou. |
| 403 | forbidden, not_your_request, export_live_key_required, not_routed_to_you, not_your_claim | forbidden: a chave não tem o âmbito, ou o financiador não está ativo. not_your_request: uma liquidação de um financiador que não é o do pedido. export_live_key_required: uma chave de sandbox não exporta. not_routed_to_you: anunciar um pedido que não lhe está encaminhado. not_your_claim: fechar um acionamento de recurso que não é de um pedido seu. |
| 404 | not_found | Nenhum recurso visível para esta chave, ou uma rota desconhecida. |
| 405 | method_not_allowed | O método não é suportado neste caminho. |
| 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 | Uma escrita que o pedido não permite: não está encaminhado para si, o estado não é o certo, ultrapassa um dos seus limites, uma notificação de factoring ainda não confirmada, um devedor fora da sua lista, um documento exigido ao cedente em falta ou fora de validade, ou um nível de consentimento que desceria, chega depois de um devedor responder, ou visa um pedido que não é de factoring ou não está em curso. Também um extrato já importado, mais de 10 endpoints ativos, um nome de prescritor que já usa, uma ligação que ainda funciona (envie replace: true), e uma ligação de adesão para uma empresa ou um contacto que já tem conta ou um convite pendente, ou num país de onde a Advanta ainda não aceita cedentes. Uma exportação ainda está a ser gerada (export_in_progress, export_not_ready) ou falhou (export_failed). |
| 410 | export_expired | export_expired: os ficheiros da exportação podiam ser descarregados durante 24 horas; inicie uma nova exportação. |
| 413 | file_too_large, too_many_lines, too_many_rows | O extrato tem mais de 4 MiB ou mais de 5000 movimentos, ou uma importação de limites tem mais de 2000 linhas (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 | Um campo ou parâmetro falta ou é inválido; o código diz qual. (Uma recusa sem motivo é 400 reason_required; uma alteração de definições ou de nível sem motivo é 422 reason_required.) Também uma alteração de termos para uma empresa fora do seu programa (seller_not_in_programme), um pedido já anunciado ou fechado (already_announced, request_closed), e um acionamento de recurso já não aberto ou fechado da forma errada (claim_closed, close_invalid). Uma importação de limites sem linhas (rows_required), com um source que não é import nem insurer (invalid_source) ou com um source_ref que não é texto ou tem mais de 200 caracteres (source_ref_invalid, source_ref_too_long) também é recusada, tal como uma date das oportunidades que não é um dia do calendário (invalid_date). |
| 429 | rate_limited, export_rate_limited | rate_limited: mais chamadas do que o limite da chave (120 por minuto e 3000 por hora, salvo se a Advanta definiu outro para a chave), ou chamadas repetidas com uma chave desconhecida a partir do mesmo endereço; volte a enviar depois de Retry-After segundos. export_rate_limited: no máximo 10 exportações em 24 horas. |
| 500 | internal, query_failed, write_failed, ingest_failed | Algo falhou do lado da Advanta. Tente mais tarde. |
debtor_not_eligible_for_funderQuando só aceita compradores da sua lista, uma oferta num pedido com um devedor fora da lista responde 409 com os devedores que a bloqueiam, cada um com um 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 | O devedor não está na sua lista. |
refused | O seu limite para o devedor está como recusado. |
suspended | O seu limite para o devedor está suspenso. |
no_tax_id | Uma fatura não tem o NIF do comprador. |
invoice_missing | Uma linha do pedido não tem fatura. |
no_invoices | O pedido não tem faturas. |
documents_missing_for_funderQuando um documento que exige ao cedente falta, não está verificado ou está fora de validade, uma oferta ou um financiamento responde 409 com os documentos que o bloqueiam, cada um com um 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 | O cedente não entregou o documento. |
unverified | A Advanta ainda não o verificou. |
expired | Já não é válido nessa data. |
rejected | A Advanta rejeitou-o. |
no_validity_date | Não tem data de validade. |
not_in_catalogue | O código não está no catálogo do país do cedente. |
O caminho leva a versão principal, /v1. Dentro da v1 podem ser acrescentados campos e tipos de evento: ignore o que não conhece.
api_version, em GET /v1/me e em cada evento de webhook, indica a revisão que está a ler: hoje, 2026-09-23.
Cada chave pode fazer 120 chamadas por minuto e 3000 por hora, contadas em todos os servidores da Advanta (as operações da Advanta podem definir outro limite para uma chave). Uma chamada acima do limite recebe 429 rate_limited, com um cabeçalho Retry-After em segundos e retry_after_seconds, limit e window_seconds no erro: nada do que pedia foi feito, por isso volte a enviá-la depois desse tempo. Chamadas repetidas com uma chave desconhecida ou mal formada a partir do mesmo endereço também recebem 429. GET /v1/health não tem limite, e as exportações mantêm o seu próprio limite (export_rate_limited).
Tudo o que está nesta página está descrito em openapi.yaml (OpenAPI 3.1). Dúvidas, ou uma chave: diogo@advanta.pt.