Factuarea APIDevelopers

Comptes gestionats

Aprovisiona comptes per als teus clients per API: alta, val de reclamació, nivell d'accés, fi de la gestió i les rutes que obre un compte gestionat.

Un compte gestionat és el compte que crees per a un dels teus clients. És un compte normal, separat del teu: té el seu propi NIF, el seu propi perfil fiscal, el seu propi pla i, quan el client el reclama, el seu propi titular. L'aprovisiones per API, el paga el teu compte i hi conserves un nivell d'accés (none, view o operate) fins que el client pren el relleu. Aquesta guia està escrita per al compte que aprovisiona, el proveïdor de comptes gestionats. Explica el privilegi que necessites, com crear i llegir comptes gestionats, com els reclama el client, com funcionen el teu nivell i la fi de la gestió, quines rutes obre un compte gestionat i com pujar el certificat VeriFactu del client perquè el seu NIF pugui emetre.

El que pagues per cada compte gestionat és a preu dels comptes gestionats i canvi de pagador. El flux complet amb una clau fact_test_, sense cobraments, és a provar comptes gestionats. Per crear-ne molts d'una vegada, fes servir la importació massiva. El compte que operes tu mateix, i el segment {account}, són a comptes i NIF.

La vida d'un compte gestionat

Dos camps diuen en quin punt és un compte gestionat. status és l'estat del compte mateix, i el bloc management diu si el teu compte encara el gestiona.

statusQuè vol dir
provisionedEl vas crear i ningú no l'ha reclamat encara, així que no té titular. El paga el teu compte.
claimedEl client el va reclamar amb el val i ara n'és l'owner. Conserves el teu nivell i, fins que el client assumeixi el pagament, continues pagant tu.
activeEl client el porta i el paga: va assumir el pagament, o la gestió va acabar després de la reclamació.
management.statusQuè vol dir
activeEl teu compte el gestiona.
endedLa gestió va acabar i el teu compte va perdre l'accés. Es llegeix a management, mai a status.

Un compte la gestió del qual acaba abans que ningú el reclami continua en provisioned.

Scopes privilegiats

Les operacions d'aprovisionament d'aquesta guia necessiten accounts:read o accounts:write. Són scopes privilegiats, i es distingeixen de qualsevol altre scope en quatre coses:

  • * no els cobreix. Una clau que només té * rep 403 insufficient_scope en aquestes operacions. Indica accounts:read i accounts:write de manera explícita, al costat de * si també vols la resta.
  • Els concedim nosaltres, compte per compte. Factuarea concedeix el privilegi de proveïdor de comptes a un compte, i només Factuarea ho pot fer. Demana'ns aquest privilegi: l'API no té cap operació que el concedeixi. GET /v1/me et diu si el tens, amb account.is_provider i account.privileged_scopes. Una clau només pot portar accounts:* mentre aquesta llista els nomeni, així que crear una clau així sense el privilegi respon 403 privileged_scope_required.
  • No arriben per OAuth. Fes servir una API key, també amb el servidor MCP.
  • Cap pla els condiciona. La porta és el privilegi, no el pla.

La comprovació corre a cada petició i res no surt d'una memòria cau. La clau ha de llistar l'scope, el teu compte ha de tenir avui el privilegi i la persona que va emetre la clau ha de continuar sent titular o administrador del teu compte. Si falla qualsevol de les tres coses, la resposta és 403 privileged_scope_required, i les dues causes responen igual. Si revoquem el privilegi, o aquella persona deixa de ser titular o administrador, la mateixa clau deixa de funcionar en la seva petició següent.

Les operacions del pla i de la importació tenen les seves pròpies guies: preu dels comptes gestionats i canvi de pagador i importació massiva.

L'entorn de la clau és l'entorn de tot el que aprovisiona i llegeix. Una clau fact_live_ treballa amb comptes gestionats de producció i una clau fact_test_ amb els de proves, i cadascuna només veu els seus.

{
  "data": {
    "account": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a00",
      "name": "Asesoría Martínez",
      "environment": "live",
      "is_provider": true,
      "privileged_scopes": [
        "accounts:read",
        "accounts:write"
      ]
    }
  }
}

El bloc account de GET /v1/me, abreujat. La mateixa resposta llista a client_accounts els comptes gestionats que arriba a tocar el teu compte, amb origin: "provisioned", fins a 100; GET /v1/accounts els llista tots.

Aprovisiona un compte

POST /v1/accounts crea el compte, el seu NIF i la relació amb el teu compte en una sola crida. No porta segment {account}, perquè el compte encara no existeix. El proveïdor és sempre el compte de la clau i l'entorn és el de la clau: cap dels dos va al cos.

CampObligatoriNotes
external_refSíLa teva pròpia referència del compte, fins a 128 caràcters, única per al teu compte. Fa la crida idempotent.
planSíemprendedor, empresario o integral. enterprise només l'assignem nosaltres, per contracte: 422 managed_account_plan_not_self_serve.
tax_idSíEl NIF, CIF o NIE del client, fins a 20 caràcters, validat amb el seu caràcter de control.
legal_nameSíRaó social, de 2 a 100 caràcters. Sense display_name, és també el nom del compte.
access_levelNoEl nivell que conserva el teu compte sobre aquest compte: none (per defecte), view o operate.
display_nameNoNom visible del compte i del seu NIF, de 2 a 120 caràcters.
address, city, postal_code, province, countryNoEl domicili fiscal del client. El codi postal deriva la zona AEAT.
languageNoes (per defecte), en o ca. L'idioma del compte i del seu val.
owner_emailDepènL'email de la persona que serà titular del compte. Obligatori amb una clau de producció, i sempre que send_email sigui true. Amb una clau de proves és opcional si no s'envia cap correu.
send_emailNofalse per defecte. Decideix qui entrega el val.
curl -X POST https://api.factuarea.com/v1/accounts \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "external_ref": "cliente-0042",
    "plan": "empresario",
    "access_level": "operate",
    "tax_id": "B12345674",
    "legal_name": "Talleres García SL",
    "display_name": "Talleres García",
    "language": "es",
    "owner_email": "laura@talleresgarcia.example",
    "send_email": false
  }'
{
  "data": {
    "id": "0199a1f0-1c22-7a10-b111-6a6b6c6d6e6f",
    "object": "managed_account",
    "external_ref": "cliente-0042",
    "status": "provisioned",
    "environment": "live",
    "plan": "empresario",
    "pending_plan": null,
    "billing_interval": "monthly",
    "access_level": "operate",
    "display_name": "Talleres García",
    "language": "es",
    "companies": [
      {
        "id": "0199a1f0-1c22-7a10-b111-7a7b7c7d7e7f",
        "tax_id": "B12345674",
        "name": "Talleres García SL"
      }
    ],
    "claimed": false,
    "claimed_at": null,
    "management": {
      "status": "active",
      "ended_at": null
    },
    "paid_by_provider": true,
    "created_at": "2026-09-27T09:00:00+00:00",
    "claim_token": "c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1",
    "claim_url": "https://app.factuarea.com/account-claims/accept?token=c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1c1a1",
    "claim_expires_at": "2026-10-11T09:00:00+00:00"
  }
}

Un compte nou respon 201 Created amb Location: /v1/accounts/{id}. El cos és el compte gestionat més el seu val de reclamació. companies[].id és el {company} que fas servir a l'eix de NIF, i id és el {account} de les rutes que nomenen un compte gestionat.

El paga el teu compte. En producció li ho cobrem al teu compte a la subscripció managed-accounts, i preu dels comptes gestionats i canvi de pagador explica quant i quan. Una clau fact_test_ crea en canvi un compte de proves: no es cobra res, no hi ha val (claim_token i claim_url són null) i no compta per al teu topall.

Idempotency-Key és obligatòria, perquè l'aprovisionament no es pot desfer. Una petició sense ella es rebutja amb 422 idempotency_key_required abans d'executar cap lògica de negoci. Un rebuig no crea res.

CodiStatusQuan
insufficient_scope403La clau no llista accounts:write. * no compta.
privileged_scope_required403El teu compte no té el privilegi, o la persona que va emetre la clau ja no n'és titular ni administrador.
invalid_param_value422Un camp no passa la validació. error.param el nomena.
managed_account_plan_not_self_serve422plan és enterprise.
managed_account_provider_in_trial422El teu compte és al seu trial i va demanar un compte de producció, que es cobra. Durant el trial, només comptes de proves.
managed_accounts_limit_reached422El teu compte és al seu topall de comptes gestionats de producció.
business_rule_violation amb subcode nif_already_claimed_by_another_account422El tax_id d'un compte de producció ja pertany a un altre compte. Un NIF no pot ser en dos comptes alhora. error.param és tax_id.
payment_method_required402Un compte de producció necessita un mètode de pagament al teu compte, i no n'hi ha cap. Afegeix-ne un i repeteix la crida.
provisioning_account_claimed409L'external_ref nomena un compte que el seu titular ja va reclamar.
managed_account_external_ref_in_other_environment409L'external_ref l'usa un compte de l'altre entorn.
idempotency_key_required422La petició no porta Idempotency-Key.
idempotency_key_reused422Aquesta clau ja es va usar amb un cos diferent.

Idempotència: Idempotency-Key i external_ref

Dues proteccions treballen juntes, i fan feines diferents.

Idempotency-Key protegeix una petició. Si es talla la connexió i repeteixes la mateixa petició amb la mateixa clau, reproduïm la primera resposta, amb la capçalera Idempotent-Replayed: true, i no aprovisionem dues vegades. El val és l'única excepció: mai no el desem en clar, ni tan sols a la memòria cau d'idempotència, així que una repetició respon claim_token i claim_url com a null. Si mai no vas rebre la primera resposta, reemet el val. La mateixa clau amb un altre cos és 422 idempotency_key_reused.

external_ref protegeix el compte. És única per al teu compte als dos entorns, així que és la clau natural del teu CRM. Aprovisionar un external_ref que el teu compte ja va aprovisionar, encara que sigui amb una Idempotency-Key nova, no crea mai un segon compte:

L'external_ref ja és…Què fa la crida
Un compte sota la teva gestió, al mateix entorn200 OK amb aquest mateix compte. No es crea, canvia ni cobra res, i no s'emet cap val. El pla, el nivell i el NIF que enviïs s'ignoren.
Un compte de l'altre entorn409 managed_account_external_ref_in_other_environment, sense escriure res. Fes servir una altra referència.
Un compte la gestió del qual vas acabar abans que ningú el reclamés200 OK. La gestió es reactiva amb el nivell que enviïs i els seus NIF es reprenen. En un compte de producció, el teu compte torna a pagar-lo i corren les mateixes comprovacions que per a un de nou: trial, topall i mètode de pagament.
Un compte que el seu titular ja va reclamar409 provisioning_account_claimed, sense reactivar res.

El val de reclamació

El val és el que necessita el client per reclamar el compte. Arriba en tres camps de la resposta de l'aprovisionament:

CampQuè és
claim_tokenEl secret d'un sol ús. Només en desem l'empremta, mai el val en si.
claim_urlL'enllaç a la pàgina de reclamació de l'app. Porta el token.
claim_expires_atQuan caduca el val: 14 dies després d'emetre'l.

El val es retorna una sola vegada. claim_token i claim_url apareixen a la resposta que emet el val i mai més: ni en una repetició, ni en un llistat, ni en un detall. Tracta'ls com una credencial i entrega'ls o desa'ls tot seguit. Si en perds un, reemet-lo: l'anterior deixa de valer.

El que reps depèn de la crida:

Cridaclaim_token i claim_url
Compte de producció nou, send_email: false (per defecte)Es retornen, una vegada, al 201.
Compte de producció nou, send_email: truenull. L'enllaç viatja només al correu a owner_email.
Compte de proves nounull. Un compte de proves no té val.
external_ref ja aprovisionat (200)null. No s'emet cap val.
Repetició idempotentnull.
Llistat i detallNo apareixen mai.

El val s'emet a nom d'owner_email: una persona que iniciï sessió amb una altra adreça no el pot fer servir.

Qui entrega el val: send_email

Tries una de dues vies, i el val no viatja mai per les dues.

  • send_email: false (per defecte). La resposta porta claim_url una sola vegada i l'entregues tu pel teu propi canal, per exemple el teu CRM o el teu propi correu. owner_email continua sent obligatori amb una clau de producció, perquè el val s'emet al seu nom.
  • send_email: true. Enviem l'enllaç per correu a owner_email, en l'idioma (language) del compte, i la resposta porta null a claim_token i claim_url. owner_email és obligatori.

Reemet el val

POST /v1/accounts/{account}/claim-tokens emet un val nou per a un compte gestionat que el seu titular encara no ha reclamat. {account} és l'id del compte gestionat. Els vals pendents deixen de funcionar i el nou va al mateix email i en el mateix idioma. El cos és opcional i admet send_email, amb el mateix significat que a dalt. Necessita una Idempotency-Key.

curl -X POST https://api.factuarea.com/v1/accounts/$MANAGED_ACCOUNT_ID/claim-tokens \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "send_email": false }'
{
  "data": {
    "object": "managed_account_claim",
    "account_id": "0199a1f0-1c22-7a10-b111-6a6b6c6d6e6f",
    "claim_token": "d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2",
    "claim_url": "https://app.factuarea.com/account-claims/accept?token=d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2d2b2",
    "expires_at": "2026-10-11T09:00:00+00:00"
  }
}

Amb send_email: true, claim_token i claim_url són null, però expires_at continua portant la data: la caducitat no és un secret i una reemissió sempre emet un val nou. Una repetició idempotent retorna també claim_token i claim_url com a null, i conserva expires_at. El val nou dura 14 dies, com el primer.

CodiStatusQuan
provisioning_account_claimed409El titular ja va reclamar el compte. No queda res per reemetre.
managed_account_not_claimable422És un compte de proves, i un compte de proves no es reclama mai.
idempotency_key_required422La petició no porta Idempotency-Key.
account_not_found404{account} no és un compte que gestiones. Consulta quines rutes accepten un compte gestionat.

Llista i llegeix els teus comptes gestionats

GET /v1/accounts llista els comptes que va aprovisionar el teu compte, només a l'entorn de la clau: una clau fact_test_ llista els teus comptes de proves i una de producció els de producció. Cap element porta val.

ParàmetreNotes
statusprovisioned, claimed o active filtren per l'estat del compte. ended retorna els comptes la gestió dels quals va acabar. Sense status, la llista conté només les gestions vigents.
external_refLa teva referència, coincidència exacta: zero o un resultat. Fins a 128 caràcters.
limitEntre 1 i 100, 25 per defecte.
starting_afterL'id de l'últim compte de la pàgina anterior, que és també el seu next_cursor.
curl -G https://api.factuarea.com/v1/accounts \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  --data-urlencode "status=provisioned" \
  --data-urlencode "limit=25"
{
  "data": [
    {
      "id": "0199a1f0-1c22-7a10-b111-6a6b6c6d6e6f",
      "object": "managed_account",
      "external_ref": "cliente-0042",
      "status": "provisioned",
      "environment": "live",
      "plan": "empresario",
      "pending_plan": null,
      "billing_interval": "monthly",
      "access_level": "operate",
      "display_name": "Talleres García",
      "language": "es",
      "companies": [
        {
          "id": "0199a1f0-1c22-7a10-b111-7a7b7c7d7e7f",
          "tax_id": "B12345674",
          "name": "Talleres García SL"
        }
      ],
      "claimed": false,
      "claimed_at": null,
      "management": {
        "status": "active",
        "ended_at": null
      },
      "paid_by_provider": true,
      "created_at": "2026-09-27T09:00:00+00:00"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Un valor de status desconegut o un external_ref de més de 128 caràcters respon 422, i un paràmetre de consulta desconegut o un limit o starting_after mal format respon 400.

GET /v1/accounts/{account} retorna un compte gestionat pel seu id, amb la mateixa forma. Funciona amb qualsevol nivell d'accés, none inclòs: les operacions d'aprovisionament només demanen que la gestió sigui vigent.

CampSignificat
idEl {account} de les rutes que nomenen un compte gestionat.
external_refLa teva pròpia referència.
statusprovisioned, claimed o active, com a dalt.
environmentlive o test: l'entorn de la clau que el va aprovisionar. Un compte de proves no es cobra mai i no es pot reclamar.
plan, pending_planEl pla actual. pending_plan és una baixada que té efecte al final del període, o null.
billing_intervalmonthly: els comptes gestionats es facturen cada mes.
access_levelEl nivell que conserva el teu compte sobre aquest compte.
display_name, languageEl seu nom visible, i l'idioma del compte i del seu val.
companiesEls seus NIF, cadascun amb id (el {company} de l'eix de NIF), tax_id i name.
claimed, claimed_atSi el titular el va reclamar, i quan.
managementstatus (active o ended) i ended_at.
paid_by_providertrue mentre el paga el teu compte, false quan el titular va assumir el pagament.
created_atQuan es va aprovisionar.

Amb status=ended, el teu compte ha perdut l'accés al compte, així que cada element es redueix al que ja sabies:

{
  "id": "0199a1f0-1c22-7a10-b111-6a6b6c6d6e6f",
  "object": "managed_account",
  "external_ref": "cliente-0042",
  "management": {
    "status": "ended",
    "ended_at": "2026-10-05T10:00:00+00:00"
  }
}

Consum de l'aprovisionament

GET /v1/accounts/{account}/provisioning-usage et diu quants comptes gestionats portes i quants més en pots aprovisionar. A diferència de les rutes anteriors, {account} és el teu propi compte, l'account.id de GET /v1/me: qualsevol altre valor respon 404 account_not_found.

{
  "data": {
    "object": "provisioning_usage",
    "managed_accounts": {
      "live": 12,
      "test": 3
    },
    "limit": 50,
    "remaining": 38,
    "managed_accounts_by_plan": {
      "emprendedor": 7,
      "empresario": 5,
      "integral": 0,
      "enterprise": 0
    },
    "provider_paid_additional_nifs": 2,
    "provider_paid_employee_seats": 9
  }
}
CampSignificat
managed_accounts.live, managed_accounts.testEls comptes gestionats la gestió dels quals és vigent, per entorn. Els dos comptadors surten sempre, sigui quin sigui l'entorn de la clau. Els comptes de proves no compten mai per al límit.
limit, remainingEl teu topall i els comptes de producció que encara pots aprovisionar. remaining no és mai negatiu.
managed_accounts_by_planEls comptes de producció per pla. Sempre llista tots els plans del catàleg, també els que són a 0.
provider_paid_additional_nifs, provider_paid_employee_seatsEl que paga el teu compte pels teus comptes gestionats a més de la seva quota pròpia: NIF addicionals i places d'empleat.

La reclamació

El client reclama el compte a l'app, no per l'API. L'enllaç de reclamació obre una pàgina on el client veu el compte que l'espera, amb el seu pla i el seu preu. Una persona nova tria una contrasenya, i qui ja té un compte de Factuarea inicia sessió. En els dos casos ha de fer servir l'adreça a la qual es va emetre el val (owner_email): una altra adreça es rebutja, igual que un val ja usat, revocat o caducat.

La reclamació té aquests efectes:

  • El client passa a ser l'owner del compte. claimed és true, claimed_at queda fixat i status passa de provisioned a claimed. Si ja havies acabat la gestió, el compte passa directament a active.
  • Conserves el teu nivell. La reclamació no canvia mai access_level. Després pots baixar el nivell, però ja no pujar-lo: consulta les regles del nivell.
  • Continues pagant fins que el client assumeixi el pagament. Mentre paid_by_provider sigui true, el compte el pagues tu. Preu dels comptes gestionats i canvi de pagador explica com passa el pagament al client.
  • T'avisem. Els titulars i administradors del teu compte reben un correu que diu que el compte s'ha reclamat.
  • El val es consumeix. Reemetre'l respon 409 provisioning_account_claimed.

Un compte de proves no es pot reclamar: 422 managed_account_not_claimable quan intentes reemetre'n el val.

El teu nivell d'accés

PATCH /v1/accounts/{account}/access-level canvia el nivell que conserva el teu compte sobre un compte gestionat. El cos porta level, que és obligatori.

curl -X PATCH https://api.factuarea.com/v1/accounts/$MANAGED_ACCOUNT_ID/access-level \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "level": "view" }'

La resposta és 200 amb el compte gestionat i el seu nou access_level.

NivellQuè arriben a tocar les teves credencials
noneRes de les dades del client. Aprovisiones el compte, el pagues i encara el pots llegir i fer servir les operacions d'aprovisionament, però cap dels seus NIF és accessible.
viewEls NIF del compte, només lectura. Una escriptura sobre un d'ells respon 403 company_read_only.
operateEls NIF del compte, per llegir i escriure. No et dona mai el que només pot fer el compte del propi client: els seus webhooks d'empresa i els seus registres de peticions, per exemple, responen 403 forbidden_action.

Abans de la reclamació, pots pujar i baixar el nivell tantes vegades com necessitis. Després de la reclamació, el pots baixar en qualsevol moment, però pujar-lo respon 422 access_level_raise_forbidden i no canvia res: només el titular el pot pujar, des del seu panell. Baixar-lo té efecte a l'instant i retalla el que les teves credencials arriben a tocar als seus NIF des de la seva petició següent.

Acaba la gestió

DELETE /v1/accounts/{account}/management acaba la gestió d'un compte gestionat. Des de la petició següent el teu compte perd l'accés al compte i als seus NIF, i totes les rutes responen 404. Necessita una Idempotency-Key, i la resposta és 200 amb el compte i management.status: "ended".

curl -X DELETE https://api.factuarea.com/v1/accounts/$MANAGED_ACCOUNT_ID/management \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "id": "0199a1f0-1c22-7a10-b111-6a6b6c6d6e6f",
    "object": "managed_account",
    "external_ref": "cliente-0042",
    "status": "provisioned",
    "environment": "live",
    "plan": "empresario",
    "pending_plan": null,
    "billing_interval": "monthly",
    "access_level": "operate",
    "display_name": "Talleres García",
    "language": "es",
    "companies": [
      {
        "id": "0199a1f0-1c22-7a10-b111-7a7b7c7d7e7f",
        "tax_id": "B12345674",
        "name": "Talleres García SL"
      }
    ],
    "claimed": false,
    "claimed_at": null,
    "management": {
      "status": "ended",
      "ended_at": "2026-09-28T10:00:00+00:00"
    },
    "paid_by_provider": true,
    "created_at": "2026-09-27T09:00:00+00:00"
  }
}

El que passa després depèn de si el client havia reclamat el compte:

  • Abans de la reclamació. El compte continua en provisioned i no és operable: tots els seus NIF passen a inactive, amb suspension_reason: "management_ended". El val continua funcionant. El compte queda així fins que el client el reclami, o fins que aprovisionis de nou el mateix external_ref, cosa que reactiva la gestió.
  • Després de la reclamació. El compte passa a active i el pagament passa al titular. Si el titular no té mètode de pagament, la gestió acaba igualment: deixes de pagar i els NIF del compte queden suspesos fins que el titular assumeixi el pagament.
  • Un compte enterprise per contracte que pagues de debò necessita un pla on continuar. Sense ell, la resposta és 422 enterprise_contract_transition_required i la gestió continua vigent. Escriu-nos perquè fixem el pla i repeteix la crida.

Després, GET /v1/accounts?status=ended continua llistant el compte amb el seu id, el teu external_ref i el bloc management, perquè el teu CRM pugui tancar el cicle. El client també pot acabar la gestió des del seu panell.

Quines rutes de {account} accepten un compte gestionat

{account} nomena normalment el teu propi compte. Un compte gestionat s'accepta en una llista tancada de rutes, i només quan el teu compte el va aprovisionar, la seva gestió és vigent i és al mateix entorn que la clau.

RutesCompte gestionat
Les rutes d'aprovisionament: GET /v1/accounts/{account}, PATCH …/access-level, DELETE …/management, POST …/claim-tokens, PATCH …/plan i GET …/plan/previewS'accepta, amb qualsevol nivell, none inclòs. Les operacions del pla demanen a més operate, com explica preu dels comptes gestionats i canvi de pagador. Aquestes rutes accepten només un compte gestionat: el teu propi compte respon aquí 404 account_not_found.
Les dades de NIF del compte: GET /v1/accounts/{account}/companies, POST …/companies, GET …/companies/stats, GET …/companies/seat-charge-preview, POST …/companies/activate, GET …/companies/{company}, PATCH …/companies/{company}, DELETE …/companies/{company}, POST …/companies/{company}/activate, POST …/companies/{company}/deactivate, POST …/companies/{company}/verify-creation, GET …/companies/{company}/creation-status i GET …/companies/{company}/issuing-readinessS'accepten amb un nivell diferent de none. Les escriptures necessiten operate: amb view, una escriptura sobre un NIF respon 403 company_read_only, i registrar o reactivar un NIF, que es factura, respon 403 billing_managed_by_provider.
Tota la resta de l'eix de compte: membres, invitacions, traspassos de NIF, titularitat, API keys, consum, places d'empleat, el resum de plantilla, el consum de l'aprovisionament, webhooks de compte i registres de peticions404 account_not_found. Són capacitats del compte mateix.

Tot allò on no s'accepta un compte gestionat respon el mateix 404 account_not_found, amb el mateix cos, en tots els casos: un compte que no és teu, un que no existeix, un de l'altre entorn, un la gestió del qual va acabar, un que et va donar accés cedit en lloc d'aprovisionar-lo tu, i un valor que no és un identificador. Res de la resposta els distingeix, així que no serveix per esbrinar quins comptes existeixen.

Els NIF del compte gestionat també s'arriben a tocar a l'eix de NIF, a /v1/companies/{company}/…, amb el companies[].id que has llegit a dalt. Les teves claus hi arriben com arriben als teus propis NIF, limitades pel teu nivell i per l'àmbit de NIF de cada clau. Per afegir els NIF del client a una clau que ja tens desplegada, envia la llista completa resultant a PATCH /v1/accounts/{account}/api-keys/{api_key}/nif-scope com a scoped_company_ids. Un àmbit nou no pot excedir mai el de la credencial que el canvia.

Quan el client assumeix el pagament, el compte paga els seus propis NIF: la teva relació passa a ser accés cedit amb el mateix nivell, i registrar, activar, desactivar o arxivar NIF correspon al compte que paga. NIF addicionals explica què pots afegir mentre pagues tu.

El costat del client és de l'app

El que el client fa amb un compte gestionat passa a l'app, i res d'això té una operació /v1 ni una tool MCP. Una credencial teva no pot decidir pel titular. El client fa servir l'app per:

  • reclamar el compte amb el val;
  • veure quin compte gestiona el seu i amb quin nivell;
  • pujar o baixar el nivell que conserves, que és l'única manera de pujar-lo després de la reclamació;
  • acabar la gestió;
  • assumir el pagament.

Tota la resta d'aquesta guia és el teu costat, el del proveïdor.

El topall: max_managed_accounts

Cada compte que aprovisiona té un topall de comptes gestionats de producció. Per defecte és 25, viu al teu compte com a max_managed_accounts i només el canviem nosaltres. provisioning-usage el retorna com a limit.

  • Què es compta. Només els comptes gestionats de producció amb la gestió vigent. Els comptes de proves no el consumeixen mai, ni tampoc els comptes la gestió dels quals va acabar.
  • En assolir-lo. Aprovisionar un compte de producció més, o reactivar-ne un, respon 422 managed_accounts_limit_reached i no crea res. Dues peticions alhora no poden superar juntes el topall, perquè el teu compte queda bloquejat mentre es comprova cadascuna.
  • Com fer-hi lloc. Acaba la gestió d'un compte que ja no portes, o demana'ns que pugem el topall del teu compte.

El certificat VeriFactu del client

Cada NIF presenta a VeriFactu amb el seu propi certificat. Un proveïdor no signa en nom dels seus clients, i no existeix un mode de representació ni d'apoderament: el que pots fer amb operate és pujar el certificat del client, perquè el seu NIF pugui emetre.

El certificat ha de ser el certificat FNMT del propi client, en format PKCS#12, i ha de coincidir amb el NIF al qual es puja. Necessites una clau el nivell efectiu de la qual sobre aquest NIF sigui operate, amb l'scope verifactu:write, i l'id del NIF, que surt de companies[].id del compte gestionat. Amb view la pujada respon 403 company_read_only, i amb none respon el mateix 404 que qualsevol NIF que no pots tocar.

POST /v1/companies/{company}/verifactu/certificates accepta multipart/form-data amb certificate_file (.p12 o .pfx, fins a 100 KB) i certificate_password. Necessita una Idempotency-Key. El certificat pujat s'activa a l'instant i els anteriors es desactiven.

curl -X POST https://api.factuarea.com/v1/companies/$CLIENT_COMPANY_ID/verifactu/certificates \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "certificate_file=@talleres-garcia.p12" \
  -F "certificate_password=$CERTIFICATE_PASSWORD"
{
  "data": {
    "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a13",
    "object": "verifactu_certificate",
    "subject_nif": "B12345674",
    "subject_name": "Talleres García SL",
    "subject_kind": "juridica",
    "valid_from": "2026-01-01T00:00:00+01:00",
    "valid_to": "2029-01-01T00:00:00+01:00",
    "is_active": true,
    "revoked_at": null,
    "created_at": "2026-01-10T09:00:00+01:00"
  }
}

La pujada es rebutja amb 422 en aquests casos, i error.param nomena el camp:

Codi i subcodeparamQuan
verifactu_not_eligible amb certificate_nif_mismatchcertificate_fileEl NIF del certificat no és el de l'empresa.
verifactu_not_eligible amb certificate_expiredcertificate_fileEl certificat ha caducat o encara no és vàlid.
business_rule_violation amb invalid_certificate_passwordcertificate_passwordLa contrasenya no obre el certificat.

Què impedeix emetre a un NIF

GET /v1/accounts/{account}/companies/{company}/issuing-readiness respon si un NIF pot emetre ara mateix, i per què no quan no pot. Funciona amb el {account} d'un compte gestionat i necessita companies:read. can_issue és el veredicte, i blockers és una llista tancada de motius, sense un ordre concret.

{
  "data": {
    "can_issue": false,
    "blockers": [
      "verifactu_certificate_missing"
    ],
    "census_status": "verified",
    "has_default_series": true,
    "fiscal_profile_complete": true,
    "operable": true,
    "missing_modules": [],
    "checked_at": "2026-09-30T10:15:00+00:00"
  }
}
BloqueigQuè ho impedeix
tax_id_missingEl perfil de l'empresa no té NIF.
tax_id_invalid_formatEl NIF hi és, però no és un NIF, CIF o NIE vàlid.
census_not_identifiedLa verificació censal de l'AEAT no identifica el titular del NIF.
census_revokedLa verificació censal de l'AEAT dona el NIF per revocat.
census_unavailableLa verificació censal no està disponible, així que no podem afirmar que el NIF pugui emetre.
fiscal_profile_incompleteFalten dades fiscals que l'emissió exigeix: domicili, raó social o règim.
no_default_seriesEl NIF no té sèrie per defecte per a factures.
company_not_operableEl NIF és al teu àmbit, però no és operable, per exemple perquè està inactive.
module_unavailableNo s'ha concedit un mòdul que l'emissió necessita. missing_modules el nomena.
verifactu_certificate_missingVeriFactu és actiu per al NIF i no té un certificat vigent: cap, revocat o caducat.

verifactu_certificate_missing és un valor de blockers, no un codi d'error: l'operació respon 200 i el catàleg de codis d'error no té pàgina per a ell. Se suma al que ja bloquegi el NIF, així que un NIF en pot portar diversos alhora. Només s'aplica mentre VeriFactu sigui actiu per al NIF. Puja el certificat i torna a llegir issuing-readiness: el bloqueig desapareix quan el certificat és vigent.

La llista pot créixer amb el temps. Tracta un motiu que no coneguis com un bloqueig que no pots resoldre per l'API. La lectura és neutra: mira l'estat fiscal i els mòduls, i mai la subscripció, el pla ni els pagaments.

Un compte de proves no té VeriFactu: el mòdul no està disponible amb una clau de proves. Provar comptes gestionats explica què deixa fora el camí de proves.

Segueix un compte gestionat amb esdeveniments

Un endpoint de webhooks de compte del teu compte rep els esdeveniments dels comptes gestionats que aprovisiones quan compleixen les regles de lliurament d'aquesta guia: account.managed_account_provisioned, account.managed_account_claimed, account.management_ended i account.access_level_changed. Són la manera de saber, sense consultar de manera periòdica, que un client ha reclamat el seu compte o que la gestió ha acabat.

Des del servidor MCP

Deu tools MCP reflecteixen les operacions del proveïdor. Cadascuna necessita l'scope de l'operació que reflecteix, que és sempre privilegiat: fes servir una API key, perquè OAuth no porta accounts:*.

ToolScopeOperació
provision_managed_accountaccounts:writePOST /v1/accounts
list_managed_accountsaccounts:readGET /v1/accounts
get_managed_accountaccounts:readGET /v1/accounts/{account}
get_provisioning_usageaccounts:readGET /v1/accounts/{account}/provisioning-usage
reissue_managed_account_claimaccounts:writePOST /v1/accounts/{account}/claim-tokens
change_managed_account_access_levelaccounts:writePATCH /v1/accounts/{account}/access-level
end_account_managementaccounts:writeDELETE /v1/accounts/{account}/management
change_managed_account_planaccounts:writePATCH /v1/accounts/{account}/plan
preview_managed_account_plan_changeaccounts:readGET /v1/accounts/{account}/plan/preview
preview_managed_account_provisioningaccounts:readGET /v1/accounts/provisioning-preview

La importació massiva no té tool MCP: llegeix fitxers pujats, que el servidor MCP no transporta. Tools MCP llista la resta del catàleg.

Propers passos

En aquesta pàgina

Et donem un cop de mà?Contactar amb suport