Factuarea APIDevelopers

Webhooks de compte

Rep en un sol endpoint els esdeveniments del teu compte i dels seus NIF, amb la taula d'equivalències respecte als webhooks d'empresa.

Un endpoint de webhook d'empresa escolta un sol NIF. Un endpoint de webhook de compte escolta tot el teu compte: els esdeveniments de cada NIF que té, els esdeveniments dels comptes que aprovisiones per als teus clients i els esdeveniments account.* del compte mateix, com l'entrada d'un membre o l'arribada d'un NIF per traspàs. Un endpoint, un secret de signatura i un historial de lliuraments substitueixen un endpoint d'empresa per a cada NIF.

És un recurs diferent, no un canvi de nom. Viu sota /v1/accounts/{account}/webhooks, té el seu propi topall per tier del pla i les seves pròpies regles sobre qui el pot gestionar, i signa i reintenta com un endpoint d'empresa. Aquesta guia explica què rep, qui el pot gestionar, el catàleg account.* i el sobre, la taula d'equivalències respecte als endpoints d'empresa, els reintents, les proves, la rotació del secret, el topall per tier, els registres de peticions del compte i el que queda fora.

Què rep un endpoint de compte

Un endpoint rep un esdeveniment només quan està active, està subscrit al tipus de l'esdeveniment, el seu filtre account_relationship admet l'esdeveniment i el seu entorn és l'entorn de l'esdeveniment. Després decideix el subjecte de l'esdeveniment:

L'esdeveniment tracta deArriba a l'endpoint quan
Un NIF del teu compteEl NIF continua sent del teu compte. Un que en surt deixa d'enviar esdeveniments, tret dels que anuncien la seva sortida.
Un NIF d'un compte que gestionesEl teu compte va aprovisionar aquest compte, la gestió és vigent, el teu nivell d'accés no és none i el NIF és dins de l'abast de la clau que va crear l'endpoint.
El compte mateix (account.*)La família de l'esdeveniment el deixa passar.
Un NIF d'un compte que et va cedir accésMai. Un accés cedit no se segueix amb webhooks, de manera que aquests NIF no hi entren.

Un endpoint creat des de l'aplicació web no té clau. Per als NIF d'un compte gestionat, compta aleshores el que arriba la persona que el va crear a l'entorn de l'endpoint.

El filtre account_relationship

ValorL'endpoint escolta
ownEls NIF del teu compte.
managedEls comptes que gestiona el teu compte.
allTots dos. És el valor per defecte.

El fixes en crear l'endpoint i el canvies amb PATCH. Cada lliurament porta el seu propi account_relationship, own o managed i mai all: et diu com es relaciona aquest esdeveniment amb el teu compte, no com està configurat l'endpoint.

Els esdeveniments de la relació mateixa, com account.management_ended, continuen arribant al proveïdor de comptes la gestió del qual acaba de terminar o de baixar a none, perquè l'esdeveniment és la relació.

L'entorn de l'endpoint

Un endpoint pertany a un compte i un entorn, live o test. El fixa la credencial o la sessió que el crea, un environment enviat al body s'ignora i no canvia mai. Un endpoint live no rep mai esdeveniments de l'entorn de proves i un de test no rep mai els de producció: els esdeveniments d'un compte gestionat de proves només arriben a endpoints test.

Un endpoint test no surt mai a la xarxa. Cada lliurament es registra amb el seu sobre, es queda en pending amb attempt a 0, i la llegeixes amb una clau fact_test_ als lliuraments de l'endpoint. Una clau de proves no pot crear ni canviar endpoints, i una clau de producció no en veu cap de test, de manera que crees un endpoint test a l'aplicació web en mode de prova i l'API només el llegeix. Provar comptes gestionats recorre tot el camí, des de crear l'endpoint fins a llegir-ne els lliuraments.

Qui pot gestionar un endpoint

Tenir el scope webhooks:* no n'hi ha prou. A cada petició a una ruta de webhooks o de registres de peticions de compte, lectures incloses, Factuarea comprova això, en aquest ordre:

  1. El compte és teu. {account} ha de ser el compte de la credencial. Un compte que no és teu, un que gestiona el teu compte, un que no existeix i un valor que no és un identificador responen el mateix 404 account_not_found, mai un 403.
  2. Escriure exigeix una credencial de producció. Una clau fact_test_ llegeix, però no crea, canvia, rota, prova, reintenta ni esborra, ni tan sols sobre un compte de proves.
  3. La persona que va emetre la clau és avui titular o administradora del compte. Es torna a llegir a cada petició, de manera que degradar aquesta persona talla les claus que va emetre a la crida següent. Una clau emesa per un member falla aquí, tingui els grants que tingui.
  4. L'abast de NIF de la clau cobreix tots els NIF del compte. Una clau acotada amb scoped_company_ids a una part del compte no gestiona els webhooks de compte.

El tercer i el quart responen el mateix 403 forbidden_action amb el mateix missatge, de manera que la resposta no revela quin dels dos ha fallat.

Una clau de proves que intenta escriure rep un 403 i no es crea ni es canvia res. És insufficient_scope quan la clau no porta cap scope d'escriptura, que és el normal perquè una clau de proves no s'emet amb ells, module_not_available_in_sandbox per l'API quan en porta un igualment, i live_credential_required pel servidor MCP.

Les eines MCP apliquen les mateixes comprovacions i n'afegeixen una: funcionen només amb una clau d'API. Una connexió per OAuth no llista les dotze eines de webhooks i de registres de peticions de compte, i cridar-ne una respon 403 forbidden_action.

L'endpoint es comprova de nou a cada lliurament

Abans de cada lliurament, Factuarea aplica de nou les regles de què rep un endpoint, de manera que un lliurament mai no surt amb una decisió del passat:

  • Si l'endpoint ja no l'ha de rebre, per exemple perquè el NIF ha sortit del compte, la gestió ha acabat o has tret la subscripció al tipus, el lliurament passa a cancelled amb el seu cancel_reason, no s'envia res i el seu payload es descarta.
  • Si el creador ha perdut la capacitat, l'endpoint mateix es desactiva amb disabled_reason: "creator_lost_capability", el canvi s'audita i el lliurament es cancel·la sense enviar res. La persona que el va crear ha deixat de ser titular o administradora o, en els esdeveniments dels teus propis NIF, la clau que el va crear s'ha revocat, ha caducat o ja no cobreix tots els NIF del compte.

Un endpoint desactivat es pot tornar a activar. Envia PATCH amb status: active: qui el reactiva passa a ser el seu creador, de manera que l'endpoint es comprova des de llavors contra aquesta persona o aquesta clau. No cal esborrar-lo i crear-ne un altre. Mentre està desactivat conserva la seva plaça al topall per tier i la llista continua mostrant el seu disabled_reason. Un endpoint creat amb una clau d'API depèn d'aquesta clau per als esdeveniments dels teus propis NIF, de manera que crea els teus endpoints amb una clau que conservis: revocar-la o deixar que caduqui desactiva l'endpoint al seu següent lliurament d'aquest tipus.

Crear un endpoint

curl -X POST https://api.factuarea.com/v1/accounts/{account}/webhooks \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/factuarea-account",
    "description": "Alerts of the account.",
    "enabled_events": ["invoice.created", "account.member_added"],
    "account_relationship": "all"
  }'

La resposta és un 201 amb la URL canònica de l'endpoint a la capçalera Location. El secret es retorna una sola vegada:

{
  "data": {
    "id": "01933b70-8a41-7c3e-9d52-4b6e8f1a2c01",
    "object": "account_webhook",
    "environment": "live",
    "url": "https://example.com/hooks/factuarea-account",
    "enabled_events": ["invoice.created", "account.member_added"],
    "account_relationship": "all",
    "status": "active",
    "disabled_reason": null,
    "api_version": "2026-09-23",
    "description": "Alerts of the account.",
    "created_at": "2026-09-28T10:15:00+00:00",
    "updated_at": "2026-09-28T10:15:00+00:00",
    "secret": "whsec_01HKQS5N8VR7QXJ9K3T6BWPMZA9876543210ABCDEF"
  }
}
  • url és una URL HTTPS de fins a 2048 caràcters.
  • enabled_events necessita almenys un tipus, i barreja els esdeveniments d'empresa del catàleg públic amb els esdeveniments account.*. Un tipus desconegut, reservat o no alliberat respon 422 i no es crea res. Un endpoint d'empresa no es pot subscriure a esdeveniments account.*.
  • account_relationship és own, managed o all, el valor per defecte.
  • description és opcional, de fins a 255 caràcters.
  • api_version és una data YYYY-MM-DD. Sense ella, l'endpoint queda fixat a l'última versió en el moment de crear-lo. Una versió no admesa respon 422.
  • L'entorn no és mai un camp. L'endpoint neix a l'entorn de la credencial.
  • Idempotency-Key és opcional en crear i en actualitzar, i obligatòria en esborrar, rotar el secret, provar i reintentar.

Les altres operacions de l'endpoint funcionen així:

  • Llistar. GET /v1/accounts/{account}/webhooks llista els endpoints de l'entorn de la credencial amb paginació per cursor: limit d'1 a 100, 25 per defecte, i starting_after. ending_before no s'admet i respon 400 parameter_unknown.
  • Actualitzar. PATCH canvia url, enabled_events, account_relationship, description o api_version. Els camps que omets conserven el seu valor, i description: null esborra la descripció.
  • Esborrar. DELETE atura l'endpoint a l'acte, cancel·la els seus lliuraments en cua i fallits i respon 204. No es pot desfer.
  • No trobat. Un endpoint que no existeix, s'ha esborrat o és d'un altre compte o entorn respon el mateix 404 webhook_endpoint_not_found.

El secret de signatura mai no forma part de l'endpoint que tornes a llegir. Per obtenir-ne un de nou, rota'l.

El catàleg account.*

Hi ha 15 esdeveniments de compte. No són a GET /v1/event-catalog, que llista només els esdeveniments d'empresa. Els seus noms són l'esquema AccountEventType de la referència, i només els endpoints de compte s'hi poden subscriure.

Esdevenimentdata.objectCamps de data.object
account.member_addedaccount_memberobject, id, user_id, email, role, previous_role (null)
account.member_removedaccount_memberEls mateixos camps que account.member_added.
account.member_role_changedaccount_memberEls mateixos camps, amb previous_role emplenat amb el rol anterior.
account.owner_transferredaccount_ownerobject, user_id, previous_user_id
account.member_grant_changedaccount_member_grantobject, member_id, company_id, level, previous_level. Un sol nom per a un grant donat, canviat i retirat.
account.access_grantedaccount_relationobject, id, origin, level, previous_level, grantor_account_id, grantee_account_id, status
account.access_revokedaccount_relationEls mateixos camps. Cobreix una revocació, una renúncia i la fi d'una gestió. Una invitació rebutjada no es publica.
account.access_level_changedaccount_relationEls mateixos camps, amb previous_level emplenat amb el nivell anterior.
account.managed_account_provisionedaccount_relationEls camps d'account_relation més managed_account_id i external_ref.
account.managed_account_claimedaccount_relationEls mateixos camps que account.managed_account_provisioned.
account.management_endedaccount_relationEls mateixos camps que account.managed_account_provisioned.
account.nif_addedcompanyobject, id, tax_id, name. Cobreix un NIF creat i un de registrat.
account.nif_transferredcompanyEls camps de company més direction, in o out.
account.nif_archivedcompanyEls camps de company, sense direction.
account.import_completedmanaged_account_importobject, id, stats

Tots els identificadors de data.object són UUID v7 opacs i mai interns. La guia d'accés cedit i la guia de comptes gestionats expliquen què signifiquen aquests esdeveniments en els seus propis fluxos.

Qui sent cada esdeveniment

La família d'un esdeveniment decideix si pot sortir del compte en què passa:

  • Membres, titularitat, grants i fi d'una importació es queden al seu compte. Mai no arriben al proveïdor d'un compte gestionat.
  • Els esdeveniments de NIF (account.nif_added, account.nif_transferred i account.nif_archived) arriben a més al proveïdor que gestiona el compte, dins de l'abast de la clau que va crear l'endpoint.
  • Els esdeveniments d'accés i de gestió arriben al proveïdor només quan la relació és d'aprovisionament. L'accés que un compte cedeix a un altre es queda amb el compte cedent, i al compte receptor no se li envia res.

El que no es publica

  • El client assumeix el pagament. La relació aprovisionada passa a ser un accés cedit i no es publica cap esdeveniment account.*. El proveïdor simplement deixa de rebre els esdeveniments d'aquest compte. Per adonar-te'n, llegeix GET /v1/accounts/{account}, que respon 404 quan la gestió ja no és vigent, o busca el compte a client_accounts de GET /v1/me amb origin: "granted", cosa que necessita el scope privilegiat accounts:read.
  • Un canvi dels NIF d'un accés cedit. Els seus efectes t'arriben com a NIF que entren o surten, no com un esdeveniment propi.
  • Un NIF eliminat o exclòs administrativament. El catàleg de compte no té nom per a ells: un NIF eliminat ja l'anuncia el seu propi esdeveniment d'empresa, i un d'exclòs no canvia de titular.
  • Una invitació rebutjada. Mai no va ser un accés, de manera que no hi ha cap accés que acabar.

El sobre i les seves capçaleres

El body de cada lliurament és el sobre d'un esdeveniment d'empresa més account, account_relationship i company_id. Els onze camps són sempre presents:

CampQuè porta
idL'identificador de l'esdeveniment (UUID v7), tal com està desat: el mateix esdeveniment d'un NIF porta el mateix id al sobre d'empresa i al de compte. Consulta la deduplicació.
typeUn tipus account.* o, en un esdeveniment d'un NIF reenviat al compte, un tipus del catàleg d'empresa.
api_versionLa versió (YYYY-MM-DD) en què es dona forma a data.
createdQuan va passar l'esdeveniment, com a timestamp Unix en segons.
livemodetrue per a l'entorn de producció, false per al de proves.
testtrue només en un esdeveniment sintètic enviat per l'operació de prova. No té res a veure amb livemode.
correlation_idUn UUID v7 que segueix l'esdeveniment des de l'operació que el va causar, o null quan l'esdeveniment no té context de correlació.
accountEl compte de l'endpoint, com a { "id": … } amb el seu UUID v7.
account_relationshipown o managed: com es relaciona l'esdeveniment amb el teu compte.
company_idL'UUID v7 del NIF de què tracta l'esdeveniment, o null en els esdeveniments de compte que no són d'un NIF.
data{ "type", "object" }. En un esdeveniment d'empresa, el mateix data que porta el webhook d'empresa.

Un esdeveniment de compte sobre un membre, tal com es lliura a un endpoint:

{
  "id": "01933b70-f2c3-7a15-b8d4-6e9a1b3c4e03",
  "type": "account.member_added",
  "api_version": "2026-09-23",
  "created": 1790590561,
  "livemode": true,
  "test": false,
  "correlation_id": "01933b70-e5a1-7b2c-9d3e-4f5a6b7c8d90",
  "account": { "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a00" },
  "account_relationship": "own",
  "company_id": null,
  "data": {
    "type": "account.member_added",
    "object": {
      "object": "account_member",
      "id": "01933b70-c4d2-7e6a-a1b3-7d8e9f0a1b04",
      "user_id": "01933b70-c4d2-7e6a-a1b3-7d8e9f0a1b05",
      "email": "marta@acme.example",
      "role": "member",
      "previous_role": null
    }
  }
}

Cada lliurament porta aquestes capçaleres:

Factuarea-Signature: t=1747314060,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Factuarea-Event-Id: 01933b70-f2c3-7a15-b8d4-6e9a1b3c4e03
Factuarea-Event-Type: account.member_added
Factuarea-Delivery-Id: 01933b71-1f0a-7d4b-8e63-5c7f9a2b3d02
Idempotency-Key: 01933b70-f2c3-7a15-b8d4-6e9a1b3c4e03
Factuarea-Account-Relationship: own
CapçaleraValor
Factuarea-SignatureLa signatura HMAC del body, feta igual que la d'un endpoint d'empresa. Webhooks explica com verificar-la.
Factuarea-Event-IdL'id de l'esdeveniment.
Factuarea-Event-TypeEl nom de l'esdeveniment.
Factuarea-Delivery-IdL'UUID del lliurament.
Idempotency-KeyEl mateix valor que Factuarea-Event-Id.
Factuarea-Account-Relationshipown o managed, com al sobre.

Equivalència amb els webhooks d'empresa

Cada operació d'un endpoint de compte té la seva bessona a l'eix d'empresa, tret de ping. El scope és el mateix als dos eixos. La primera taula aparella les rutes, i la segona els noms que fan servir els SDK, la CLI i el servidor MCP. Les dues mantenen el mateix ordre.

Ruta de compteRuta d'empresaScope
GET /v1/accounts/{account}/webhooksGET /v1/companies/{company}/webhook-endpointswebhooks:read
POST /v1/accounts/{account}/webhooksPOST /v1/companies/{company}/webhook-endpointswebhooks:write
GET /v1/accounts/{account}/webhooks/{webhook}GET /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}webhooks:read
PATCH /v1/accounts/{account}/webhooks/{webhook}PATCH /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}webhooks:write
DELETE /v1/accounts/{account}/webhooks/{webhook}DELETE /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}webhooks:delete
GET /v1/accounts/{account}/webhooks/{webhook}/deliveriesGET /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliverieswebhooks:read
GET /v1/accounts/{account}/webhooks/{webhook}/deliveries/{delivery}GET /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliveries/{delivery}webhooks:read
POST /v1/accounts/{account}/webhooks/{webhook}/deliveries/{delivery}/retryPOST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliveries/{delivery}/replaywebhooks:write
POST /v1/accounts/{account}/webhooks/{webhook}/secretPOST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/rotate-secretwebhooks:write
POST /v1/accounts/{account}/webhooks/{webhook}/testPOST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/test-eventwebhooks:write
Sense equivalentPOST /v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/pingwebhooks:write
GET /v1/accounts/{account}/request-logsGET /v1/companies/{company}/request-logsdevelopers:read
GET /v1/accounts/{account}/request-logs/{request_id}GET /v1/companies/{company}/request-logs/{request_id}developers:read
Operació de compteEina de compteOperació d'empresaEina d'empresa
public-api.v1.account.webhooks.listlist_account_webhookspublic-api.v1.webhook_endpoints.listsearch_webhook_endpoints
public-api.v1.account.webhooks.createcreate_account_webhookpublic-api.v1.webhook_endpoints.createcreate_webhook_endpoint
public-api.v1.account.webhooks.showget_account_webhookpublic-api.v1.webhook_endpoints.showget_webhook_endpoint
public-api.v1.account.webhooks.updateupdate_account_webhookpublic-api.v1.webhook_endpoints.updateupdate_webhook_endpoint
public-api.v1.account.webhooks.deletedelete_account_webhookpublic-api.v1.webhook_endpoints.deletedelete_webhook_endpoint
public-api.v1.account.webhooks.deliveries.listlist_account_webhook_deliveriespublic-api.v1.webhook_endpoints.deliveries.listlist_webhook_deliveries
public-api.v1.account.webhooks.deliveries.showget_account_webhook_deliverypublic-api.v1.webhook_endpoints.deliveries.showget_webhook_delivery
public-api.v1.account.webhooks.deliveries.retryretry_account_webhook_deliverypublic-api.v1.webhook_endpoints.deliveries.replayreplay_webhook_delivery
public-api.v1.account.webhooks.rotate_secretrotate_account_webhook_secretpublic-api.v1.webhook_endpoints.rotate_secretrotate_webhook_secret
public-api.v1.account.webhooks.testtest_account_webhookpublic-api.v1.webhook_endpoints.test_eventtest_webhook_endpoint
Sense equivalentSense equivalentpublic-api.v1.webhook_endpoints.pingping_webhook_endpoint
public-api.v1.account.request_logs.listlist_account_request_logspublic-api.v1.developers.request_logs.listlist_developers_request_logs
public-api.v1.account.request_logs.showget_account_request_logpublic-api.v1.developers.request_logs.showget_developers_request_logs

Quatre diferències que no són de nom

  • Només el teu propi compte. {account} és sempre el compte de la teva credencial. Un proveïdor no administra per aquesta ruta els webhooks ni els registres de peticions dels comptes que gestiona: rep els seus esdeveniments al seu propi endpoint amb el filtre managed. Qui pot gestionar un endpoint en té la resposta.
  • Un emissor titular o administrador, i un abast que cobreix tot el compte. Un endpoint d'empresa necessita el scope i accés al NIF de la ruta. Un endpoint de compte necessita a més que la persona que va emetre la clau sigui avui titular o administradora i que la clau arribi a tots els NIF del compte.
  • Sense OAuth. Les dotze eines de compte són només per a claus d'API. Les eines de webhooks d'empresa també són accessibles per OAuth.
  • Escriptures només amb credencial de producció. Una clau de proves llegeix l'entorn de proves i aquí no escriu mai.

retry no és replay, i no hi ha ping

  • retry rearma el mateix lliurament. Conserva el seu id i els seus comptadors: attempt es manté i manual_retry_count creix. Hi ha com a màxim un lliurament per a cada endpoint i esdeveniment, de manera que un reintent mai no en produeix una segona.
  • replay crea un lliurament nou. En un endpoint d'empresa posa en cua una fila de lliurament nova, amb attempt: 1, per al mateix esdeveniment i el mateix endpoint.
  • ping no té equivalent de compte. Envia un webhook.ping sintètic. En un endpoint de compte fas servir test, que simula un dels tipus als quals l'endpoint està subscrit, account.* inclosos.

Altres diferències als camps: un endpoint de compte té account_relationship i no té ip_allowlist, metadata, custom_headers ni timeout_seconds. El test de compte no desa l'esdeveniment sintètic enlloc, mentre que el test-event d'empresa registra un esdeveniment real. Els registres de peticions de compte no tenen paràmetre environment, perquè l'entorn és el de la credencial.

Lliuraments, reintents i reintent manual

Un lliurament és un esdeveniment enviat a un endpoint. El seu status és un d'aquests:

EstatQuè significa
pendingEn cua o esperant el seu següent intent. En un endpoint test es queda aquí per sempre, amb attempt a 0: es registra i no s'envia mai.
deliveredEl teu servidor ha respost amb un 2xx.
failedUn error recuperable. El següent intent està programat a next_retry_at.
failed_permanentlyS'han esgotat els intents o la destinació ha rebutjat el lliurament. La pots reintentar a mà.
cancelledAvortada i definitiva. cancel_reason diu per què i payload és null.

El teu servidor té 10 segons per respondre. Factuarea reintenta un 5xx, un temps esgotat i un 408, 425 o 429. No reintenta cap altre 4xx, ni una destinació que les seves comprovacions de seguretat de sortida rebutgen: acaben en failed_permanently de seguida. Els endpoints de compte fan servir el mateix calendari que els d'empresa, amb 8 intents en total:

IntentEspera després de l'anterior
1immediat
21 minut
35 minuts
430 minuts
52 hores
612 hores
71 dia
83 dies

Cada espera varia fins a un ±10 %. Després de l'últim intent el lliurament queda en failed_permanently. Els lliuraments es conserven 90 dies, i els esdeveniments que hi ha al darrere, 30 dies.

GET /v1/accounts/{account}/webhooks/{webhook}/deliveries els llista del més antic al més recent, amb limit, starting_after i un filtre opcional status. Per buscar errors recents, filtra per status=failed o failed_permanently i segueix starting_after fins que has_more sigui false. Cada lliurament mostra l'esdeveniment, el NIF (company_id), la seva relació amb el teu compte, els comptadors, el que ha respost el teu servidor (response_status i un response_body truncat) i el payload signat que es va enviar.

Reintentar un lliurament

curl -X POST https://api.factuarea.com/v1/accounts/{account}/webhooks/{webhook}/deliveries/{delivery}/retry \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Respon 202 i el mateix lliurament torna a pending, per enviar-se de nou amb el secret actual:

{
  "data": {
    "id": "01933b71-9c2d-7e5f-a674-6d8f0b3c4e06",
    "object": "account_webhook_delivery",
    "status": "queued"
  }
}

Només es poden reintentar lliuraments failed i failed_permanently. Un de delivered, pending o cancelled respon 422 amb el subcodi account_webhook_retry_not_allowed, i un lliurament d'un endpoint desactivat respon 422 amb account_webhook_endpoint_not_active. Un lliurament o un endpoint que el teu compte no veu respon 404 webhook_delivery_not_found. Necessita una clau de producció i una Idempotency-Key, i té el seu propi límit: 30 peticions per minut.

Enviar un lliurament de prova

POST /v1/accounts/{account}/webhooks/{webhook}/test posa en cua un lliurament de prova signat, marcat test: true al sobre, per comprovar que el teu endpoint és accessible i que la teva verificació de signatura funciona:

curl -X POST https://api.factuarea.com/v1/accounts/{account}/webhooks/{webhook}/test \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "type": "account.member_added" }'
{
  "data": {
    "id": "01933b71-1f0a-7d4b-8e63-5c7f9a2b3d02",
    "object": "account_webhook_delivery",
    "event_id": "01933b70-f2c3-7a15-b8d4-6e9a1b3c4e03",
    "test": true,
    "status": "queued"
  }
}
  • type és opcional. Sense ell, Factuarea fa servir el primer tipus al qual l'endpoint està subscrit. Si en dones un, l'endpoint hi ha d'estar subscrit, o la resposta és 422 amb el subcodi event_not_subscribed. Els tipus account.* són vàlids.
  • L'esdeveniment és sintètic. No es desa en cap registre d'esdeveniments i arriba només a aquest endpoint, però el lliurament que crea sí que es desa: llegeixes el resultat als lliuraments de l'endpoint.
  • Un endpoint desactivat respon 422 amb el subcodi account_webhook_endpoint_not_active.
  • En un endpoint test no surt res a la xarxa i el lliurament es queda en pending amb attempt a 0.
  • Límit: 10 peticions per minut, amb una clau de producció i una Idempotency-Key.

Els dos límits, el de la prova i el del reintent, es compten per cada credencial i la seva empresa titular, a més del límit general del teu tier. Una petició per sobre respon 429. Límits de peticions explica el límit general.

Rotar el secret

curl -X POST https://api.factuarea.com/v1/accounts/{account}/webhooks/{webhook}/secret \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

La resposta és un 200 amb l'endpoint i el secret nou, retornat una sola vegada. Durant 24 hores el secret anterior continua signant també: cada lliurament porta dos valors v1 a Factuarea-Signature, un per secret, igual que en un endpoint d'empresa. Desplega el secret nou dins d'aquesta finestra i el teu receptor mai no descarta un lliurament. La seva verificació accepta la petició si algun v1 coincideix.

Una segona rotació a menys de 5 minuts de l'última respon 422 business_rule_violation amb el subcodi webhook_secret_recently_rotated, i no canvia res. Rotar és irreversible, de manera que exigeix una Idempotency-Key. Repetir la mateixa petició amb la mateixa clau retorna secret: null, perquè el secret no es desa mai.

El topall per tier

El nombre d'endpoints de compte depèn del tier de qui paga el compte, no del tier de la credencial que crea l'endpoint. En un compte gestionat que paga el seu proveïdor, és el tier del proveïdor. Es compta per a cada compte i cada entorn, a part dels endpoints d'empresa, i inclou els desactivats.

TierEl donaEndpoints de compte per entorn
FreeEl trial0
StarterEl pla Emprendedor1
ProEl pla Empresario10
ScaleEl pla Enterprise50

Els scopes webhooks:read, webhooks:write i webhooks:delete pertanyen al mòdul de webhooks sortints (integration_webhooks), que inclouen els plans Empresario i Enterprise. Al pla Emprendedor, el que dona el tier Starter, una clau no els pot portar, així que el seu únic endpoint de compte es crea i es gestiona des de l'aplicació web, no per l'API.

Límits de peticions descriu els tiers. Crear un endpoint pot fallar de dues maneres:

{
  "error": {
    "type": "payment_required_error",
    "code": "addon_required",
    "subcode": "account_webhooks_addon_required",
    "message": "El plan de pago de tu cuenta no permite crear endpoints de webhook de cuenta. Contrata un plan que los incluya.",
    "doc_url": "https://docs.factuarea.com/guides/errors#addon_required",
    "request_id": "req_7d2f8b01e3c45a7b9f1d2e3c4b"
  }
}
{
  "error": {
    "type": "invalid_request_error",
    "code": "account_webhook_endpoint_limit_reached",
    "message": "Has alcanzado el máximo de 1 endpoint de webhook de cuenta del tier starter. Mejora tu plan para añadir más.",
    "doc_url": "https://docs.factuarea.com/guides/errors#account_webhook_endpoint_limit_reached",
    "request_id": "req_8e3a9c12f4d56b8c0a2e3f4d5c"
  }
}

Només esborrar un endpoint allibera una plaça. Un endpoint d'empresa no fa servir el topall del compte, i l'endpoint d'un altre compte tampoc.

Registres de peticions del compte

Dues operacions mostren què s'ha cridat amb les claus d'API del teu compte, perquè depuris una integració sense obrir un tiquet de suport:

Necessiten el scope developers:read i les mateixes comprovacions que els endpoints. El que les distingeix dels registres d'empresa:

  • Agreguen totes les claus del compte, i mai les d'un altre compte. Els registres d'empresa només mostren les peticions d'un NIF.
  • L'entorn és el de la credencial. Una clau live veu el trànsit de producció i una clau test el de proves. No hi ha paràmetre environment, i enviar-lo o enviar ending_before respon 400 parameter_unknown.
  • Les files es purguen als 30 dies. És una finestra per depurar, no un registre d'auditoria.

Els filtres són els del llistat d'empresa: method[], status_range[], only_errors, api_key_prefix, path_search, created_at[gte] i created_at[lte], juntament amb limit i starting_after.

curl "https://api.factuarea.com/v1/accounts/{account}/request-logs?only_errors=true&limit=25" \
  -H "Authorization: Bearer $FACTUAREA_API_KEY"
{
  "data": [
    {
      "request_id": "req_01JQZP8K4M9N2T5V7X0Y3B6D8F",
      "object": "api_request_log",
      "api_key_prefix": "01931b3e",
      "method": "POST",
      "path": "/v1/companies/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01/invoices",
      "status_code": 422,
      "duration_ms": 143,
      "ip": "203.0.113.24",
      "user_agent": "factuarea-cli/0.1.3",
      "error_type": "invalid_request_error",
      "error_code": "invalid_param_value",
      "factuarea_version": "2026-09-23",
      "environment": "live",
      "created_at": "2026-09-28T09:30:12+00:00"
    }
  ],
  "has_more": true,
  "next_cursor": "184320"
}

api_key_prefix són els 8 primers caràcters de l'identificador de la clau que va fer la crida, suficients per saber quina de les teves claus va ser. La query string no es desa mai.

Endpoints, registres i esdeveniments d'empresa sobre un NIF assolit per una relació

Les onze operacions de …/webhook-endpoints, les dues de …/request-logs i les dues de …/events (list i show) de l'eix d'empresa pertanyen al compte propietari del NIF. Quan arribes a un NIF per una relació entre comptes, perquè un altre compte te l'ha cedit o perquè és d'un compte gestionat, responen 403 forbidden_action abans de llegir o canviar res, amb qualsevol nivell d'accés. Les eines MCP d'aquestes operacions responen el mateix, entre elles list_events i get_event. Sobre els teus propis NIF conserven el seu contracte.

Per seguir els NIF dels comptes que gestiones, fes servir un endpoint de compte amb el filtre managed o all.

L'historial de correus tampoc no s'exposa per compte. No existeix GET /v1/accounts/{account}/emails, ni el seu detall ni els seus indicadors. Llegeix-lo NIF a NIF amb GET /v1/companies/{company}/emails i el scope emails:read.

Des del servidor MCP

Les dotze eines de les taules anteriors reflecteixen una a una les operacions de webhooks i de registres de peticions de compte. Les deu eines de webhooks formen el domini AccountWebhook del catàleg i les dues de registres es llisten amb les de PublicApi. Cadascuna necessita el scope de l'operació que reflecteix, funciona només amb una clau d'API i aplica les comprovacions de qui pot gestionar un endpoint. Esborrar un endpoint i rotar-ne el secret són operacions irreversibles. Tools MCP llista tot el catàleg.

En aquesta pàgina

Et donem un cop de mà?Contactar amb suport