Factuarea APIDevelopers

Arribar a un NIF pel segment d'empresa

Treballa amb qualsevol NIF al qual arriba la teva credencial anomenant-lo al segment d'empresa de la ruta — els propis, els d'un accés cedit i els de comptes gestionats — amb com resoldre el seu id, les respostes que obtens i la capçalera X-Active-Profile retirada.

Tot recurs d'empresa de l'API v1 penja de /v1/companies/{company}/…, on {company} és l'id públic (UUID v7) del NIF sobre el qual opera la petició. Funciona igual a tots els recursos d'empresa, factures, contactes, sèries i la resta:

curl https://api.factuarea.com/v1/companies/$COMPANY_ID/invoices \
  -H "Authorization: Bearer $FACTUAREA_KEY"

Una credencial arriba a tots els NIF del seu àmbit, i tries el destí a cada petició, a la ruta, sense reautenticar-te ni gestionar una clau per NIF. Aquesta pàgina explica aquest segment de la ruta. Per donar a una integració només una part del compte, acota la clau en comptes d'això.

Quan el segment anomena un NIF al qual arriba la teva credencial, la petició sencera s'executa contra les seves dades: tota lectura es filtra a ell i tota escriptura hi cau. El NIF es resol abans del límit de peticions, de la idempotència i del registre de consum, així que els tres s'atribueixen al NIF que anomenes i no a l'empresa titular de la credencial.

El segment no és opcional. No hi ha cap ruta a un recurs d'empresa sense ell, així que cap petició no pot acabar en un NIF que no vas anomenar, que és justament la garantia que la capçalera retirada no podia donar.

El segment mai no amplia la teva credencial. Els seus scopes, el seu tier i el seu environment passen intactes: una clau que només té invoices:read i anomena un NIF continua sense poder fer POST /v1/companies/{company}/invoices a ell (403 insufficient_scope), i una clau fact_test_ es queda al sandbox sigui quin sigui el NIF que anomeni. Triar un NIF canvia sobre quin actues, mai què tens permès fer.

Què pot contenir l'àmbit d'una credencial

L'àmbit d'una clau és la llista de NIF als quals arriba, fixada quan s'emet la clau i canviada amb PATCH …/nif-scope. Pot contenir tres classes de NIF, i cadascun porta un nivell, view o operate:

NIFCom entra a l'àmbitNivell que porta
Els teusEl nomenes a scoped_company_ids en emetre la clau, o la clau hereta l'àmbit de la clau que la va emetre.El nivell que té en aquest NIF la persona que va emetre la clau.
Cedit per un altre compteL'accés cedit és vigent, i nomenes el NIF en emetre la clau o en canviar-ne l'àmbit.El menor entre el nivell de l'accés i el de la persona que va emetre la clau, que per a un member queda a més limitat pel seu grant.
D'un compte gestionat que has aprovisionatLa gestió és vigent amb un nivell diferent de none, i nomenes el NIF de la mateixa manera. Consulta els comptes gestionats.El menor entre el teu nivell al compte gestionat i el de la persona que va emetre la clau.

Un nivell es fixa quan el NIF entra a la clau i només baixa: les claus acotades expliquen com. Quan un accés es redueix o acaba, el NIF surt de l'àmbit de les teves claus a la petició següent. Les claus continuen funcionant sobre la resta, i una que es queda amb l'àmbit buit es revoca.

El servidor MCP arriba als mateixos NIF: anomena el NIF amb la capçalera X-Company-Id en lloc d'un segment de la ruta.

Resol l'identificador del NIF

El segment porta l'id opac, mai el tax_id. Tres llocs te'l donen, i cap no exigeix que el construeixis a mà:

  • GET /v1/me introspecciona la credencial que crida i enumera, a scope, cada NIF al qual arriba amb el seu id, tax_id i name. Ho fa sempre, també quan n'hi ha exactament un. El seu account.id és l'identificador que espera el segment /v1/accounts/{account}/….
  • GET /v1/accounts/{account}/companies?tax_id=B12345674 busca un NIF del teu propi compte pel seu identificador fiscal. Un número fiscal fora del teu àmbit retorna una llista buida, mai un rebuig. No llista els NIF als quals arribes per una relació.
  • Els NIF d'un compte gestionat vénen a companies[] de GET /v1/accounts/{account}, com descriuen els comptes gestionats.
curl https://api.factuarea.com/v1/me \
  -H "Authorization: Bearer $FACTUAREA_KEY"
{
  "data": {
    "object": "me",
    "account": {
      "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a00",
      "name": "Asesoría Martínez",
      "environment": "live",
      "is_provider": true,
      "privileged_scopes": [
        "accounts:read",
        "accounts:write"
      ]
    },
    "api_key": {
      "id": "019e81ef-e1d4-7208-a51d-94c2c2a54a84",
      "name": "Producción",
      "prefix": "fact_live_1OSf9KdP",
      "scopes": [
        "account:read",
        "series:read",
        "series:write"
      ],
      "tier": "scale",
      "environment": "live",
      "created_at": "2026-01-15T09:30:00Z",
      "last_used_at": "2026-05-25T18:00:00Z",
      "expires_at": null
    },
    "scope": [
      {
        "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
        "tax_id": "B12345674",
        "name": "Acme Corporation"
      },
      {
        "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a02",
        "tax_id": "B87654323",
        "name": "Acme Logística S.L."
      }
    ],
    "client_accounts": [
      {
        "id": "0199a1f0-1c22-7a10-b111-5a5b5c5d5e5f",
        "name": "Construcciones Ruiz",
        "origin": "granted",
        "access_level": "view",
        "status": "active",
        "paid_by_provider": false,
        "environment": "live"
      },
      {
        "id": "0199a1f0-1c22-7a10-b111-6a6b6c6d6e6f",
        "name": "Talleres García",
        "origin": "provisioned",
        "access_level": "operate",
        "status": "provisioned",
        "paid_by_provider": true,
        "environment": "live"
      }
    ],
    "client_accounts_visible": true,
    "client_accounts_has_more": false
  }
}

L'id de cada entrada de scope és el que va a {company}. client_accounts llista els comptes dels teus clients als quals arriba el teu compte, i només quan la clau porta el scope privilegiat accounts:read en vigor: comptes i NIF descriu cada camp.

Desa a la teva integració la correspondència tax_id → id i refresca-la quan donis d'alta un NIF: l'id és estable mentre visqui el NIF, i el tax_id és immutable després de l'alta. Un NIF arxivat que es torna a donar d'alta és un de nou, amb un id nou.

Resolució i errors

El segment d'empresa resol el NIF efectiu abans que s'executi cap handler:

Segment d'empresaResultat
Un NIF de l'àmbit de la teva credencial, active, en el qual el teu nivell permet la peticióLa petició opera sobre aquest NIF.
Dins de l'àmbit, però desactivat (inactive) o arxivat403 company_inactive. Un NIF desactivat es pot reactivar abans; un d'arxivat no, perquè archived és terminal.
Fora del teu àmbit, inexistent, que no és un identificador, o de l'altre entorn (live ↔ test)404 profile_not_found.
Dins de l'àmbit, però la teva clau té view a ell i la petició escriu403 company_read_only, sense crear ni canviar res.
Dins de l'àmbit, però la persona que va emetre la clau ja no hi arriba i la petició escriu404 profile_not_found, igual que fora de l'àmbit.
Assolit per una relació entre comptes, en una operació que és del compte amo del NIF403 forbidden_action, amb qualsevol nivell i també en lectures.
Una operació que els teus scopes no cobreixen403 insufficient_scope.

El 404 és indistingible en tots els seus casos: l'API mai no revela que existeix un NIF fora del teu àmbit, i un NIF de producció i el seu bessó sandbox comparteixen identificador fiscal. L'entorn es comprova abans que l'estat, així que un NIF desactivat de l'altre entorn també respon 404.

{
  "error": {
    "type": "not_found_error",
    "code": "profile_not_found",
    "message": "La empresa indicada no existe o no está en el ámbito de tu credencial.",
    "param": "company"
  }
}

El 403 company_inactive és diferent: el NIF sí és dins del teu àmbit, així que revelar que està desactivat és legítim, i, en un NIF desactivat, és el senyal per reactivar-lo abans d'operar:

{
  "error": {
    "type": "authorization_error",
    "code": "company_inactive",
    "message": "Esta empresa está desactivada. Actívala para operar.",
    "param": "company"
  }
}

Un NIF arxivat respon el mateix 403 en aquest eix i no es pot reactivar. Pel compte, les operacions que el canvien responen 404.

Un 403 company_read_only diu que el teu accés al NIF és de només lectura, i les seves lectures continuen funcionant. Depèn del menor entre el nivell desat a la clau i el que té avui la persona que la va emetre.

Un 403 forbidden_action sobre un NIF al qual s'arriba per una relació diu que l'operació és del compte que el posseeix. Aquestes operacions són els registres de peticions, els esdeveniments, els endpoints de webhook d'empresa, la facturació, el consum d'automatitzacions i les escriptures de les credencials de pagament. L'accés cedit les llista. El missatge no anomena el compte amo:

{
  "error": {
    "type": "authorization_error",
    "code": "forbidden_action",
    "message": "Esta operación solo la puede hacer la cuenta dueña del NIF: con un acceso por relación entre cuentas no está disponible.",
    "doc_url": "https://docs.factuarea.com/guides/errors#forbidden_action",
    "request_id": "req_01J8Y3M2Q40000000000000008"
  }
}

L'eix de compte és una altra ruta

/v1/accounts/{account}/… anomena un compte, no un NIF. {account} ha de ser el compte de la teva credencial: un compte que no és teu, un que no existeix, un valor que no és un identificador i un que et va donar accés responen tots el mateix 404 account_not_found. Un compte gestionat s'admet només en una llista tancada de rutes que descriuen els comptes gestionats. Les rutes de la cartera de NIF porten també {company}, però allà anomena el NIF sobre el qual actua l'operació, no el que posseeix les dades.

La capçalera X-Active-Profile retirada

Fins a aquesta versió, el NIF de destí viatjava en una capçalera de petició X-Active-Profile. Aquesta capçalera està retirada. Una petició que la porti es rebutja amb 400, sigui quin sigui el seu valor:

{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_unknown",
    "subcode": "retired_active_profile_header",
    "message": "La cabecera 'X-Active-Profile' fue retirada de la API v1: la empresa efectiva se indica en el segmento de empresa de la ruta.",
    "param": "X-Active-Profile"
  }
}

El rebuig es dispara per presència, mai per contingut: un identificador ben format, un NIF fora del teu àmbit, un valor mal format, una cadena buida i una cadena només amb espais reben exactament el mateix error amb el mateix missatge. No s'interpreta res del valor, així que el rebuig no serveix per sondejar quins NIF existeixen.

Enviar la capçalera i que s'ignorés hauria estat pitjor que rebutjar-la: una escriptura pensada per a un altre NIF hauria retornat 201 amb el document emès sota el NIF del titular de la credencial. El 400 es llança abans del handler, així que una escriptura rebutjada no deixa res enrere. Migrar és mecànic: esborra la capçalera i mou-ne el valor al segment {company} de la ruta.

Quina faig servir?

El segment de la ruta i les maneres d'ampliar o acotar el que arriba a tocar una credencial resolen necessitats diferents, i conviuen:

  • Els teus propis NIF. Fes servir una clau del teu compte i anomena el NIF a cada petició. Per donar a una integració només una part del compte, acota la clau: la seva credencial arriba només a aquests NIF, i el segment no en pot anomenar cap altre.
  • Els NIF d'un negoci que manté el seu propi compte. L'accés cedit permet que aquest negoci doni al teu compte view o operate sobre tots o alguns dels seus NIF. Els afegeixes a una clau i els anomenes al segment com els teus.
  • Clients que dones d'alta tu. Els comptes gestionats et permeten aprovisionar per API el compte d'un client, i arribes als seus NIF amb el teu nivell mentre duri la gestió.

Anomenar un NIF a la ruta només canvia sobre quin actues. Mai no canvia els scopes de la credencial, i l'aïllament funciona com en gestionar la cartera: un NIF fora del teu àmbit mai no és observable, i la resposta és un 404 i no un 403.

En aquesta pàgina

Et donem un cop de mà?Contactar amb suport