Factuarea APIDevelopers

Cuentas y NIF

Tu cuenta es el cliente: sus NIF, su equipo con roles owner, admin y member, los grants por NIF, el traspaso de NIF y cómo consultarla con GET /v1/me.

Tu cuenta es el cliente. Reúne el plan, las credenciales, el equipo y los NIF que facturan. Una credencial pertenece a una cuenta, y el segmento {account} de /v1/accounts/{account}/… la nombra. Esta guía explica qué vive en la cuenta, quién puede hacer qué dentro de ella, cómo pasa un NIF de una cuenta a otra y cómo leer tu propia credencial con GET /v1/me.

Describe la cuenta que operas tú. Las cuentas de tus clientes tienen sus propias guías: acceso cedido cuando otra cuenta te deja alcanzar algunos de sus NIF, y cuentas gestionadas cuando aprovisionas tú mismo la cuenta del cliente.

Una cuenta, varios NIF

Un NIF pertenece como máximo a una cuenta. El primer NIF de una cuenta es su NIF titular: la empresa titular de la cuenta, que no es un NIF adicional y no se puede ceder. Todos los demás son NIF adicionales: los paga la cuenta, y el plan que los admite, su precio y su tope tienen su propia guía.

Los datos de un NIF (sus facturas, contactos, series y registros de VeriFactu) se quedan con ese NIF. La cuenta guarda lo que se comparte: el equipo, las invitaciones, la titularidad, las API keys, el consumo, la cartera de NIF, los traspasos, los webhooks y los registros de peticiones. Cada cosa vive en una ruta distinta:

EjeRutaQué nombraDe dónde sale el identificador
Cuenta/v1/accounts/{account}/…Tu cuentaaccount.id de GET /v1/me
NIF/v1/companies/{company}/…Un NIF de tu ámbitoscope[].id de GET /v1/me
Aprovisionamiento/v1/accounts y /v1/accounts/imports…Las cuentas gestionadas que aprovisionas para tus clientesCuentas gestionadas

Los dos segmentos llevan el id opaco (UUID v7), nunca el tax_id. Para encontrar un NIF por su identificador fiscal, filtra GET /v1/accounts/{account}/companies con tax_id.

Consulta tu credencial con GET /v1/me

GET /v1/me te dice quién es tu credencial, a qué cuenta pertenece y qué NIF alcanza, en una sola llamada. No necesita ningún scope: cualquier credencial válida puede consultarse a sí misma. Es también la forma en que quien tiene un único NIF descubre su identificador opaco.

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
  }
}
CampoQué te dice
accountLa cuenta de la credencial. id es el valor del segmento {account}, environment es live o test, is_provider indica si la cuenta aprovisiona cuentas gestionadas y privileged_scopes lista los scopes privilegiados que Factuarea le concedió. El scope * nunca los cubre.
api_keyLa propia credencial. scopes son los scopes efectivos: un scope que el plan de los NIF del ámbito no permite no aparece. El secreto nunca se devuelve.
scopeLos NIF que alcanza la credencial, cada uno con su id, su tax_id y su name. Siempre se enumeran, también cuando solo hay uno.
client_accountsLas cuentas de tus clientes que tu cuenta alcanza por una relación. origin es granted o provisioned, access_level es none, view u operate, status es provisioned, claimed o active, y paid_by_provider indica si tu cuenta la paga.
client_accounts_visibletrue cuando la credencial tiene en vigor el scope privilegiado accounts:read y client_accounts es la lista real. false cuando la lista va vacía solo porque falta ese scope.
client_accounts_has_moretrue cuando existen más de las 100 cuentas de clientes listadas. GET /v1/accounts las lista todas.

GET /v1/me nunca devuelve ajustes de un solo NIF, como la personalización, el plan o los add-ons: son del eje de NIF.

Qué acepta {account}

Las capacidades de cuenta (equipo, claves, cartera de NIF, traspasos, webhooks) son siempre las de tu propia cuenta, así que {account} tiene que ser la cuenta de tu credencial. Una cuenta que es proveedor de cuentas gestionadas alcanza además las cuentas que gestiona, pero solo en una lista cerrada de rutas que describe cuentas gestionadas.

Cualquier otro valor responde el mismo 404 account_not_found, con el mismo body y nunca un 403: una cuenta que no es tuya, una cuenta que no existe y un valor que no es un identificador de cuenta no se distinguen. Un 403 diría que la cuenta existe, y repetirlo con identificadores distintos convertiría la ruta en un censo de las cuentas de la plataforma. Una cuenta que te cedió acceso tampoco es tuya: alcanzas sus NIF por el segmento {company}, como explica acceso cedido.

{
  "error": {
    "type": "not_found_error",
    "code": "account_not_found",
    "message": "La cuenta indicada no existe o no es la de tu credencial.",
    "param": "account",
    "doc_url": "https://docs.factuarea.com/guides/errors#account_not_found",
    "request_id": "req_01J8Y3M2Q40000000000000006"
  }
}

El eje de NIF se comporta igual. Un {company} que no existe o que queda fuera del ámbito de tu credencial responde 404 profile_not_found, y un NIF en el que tu nivel de acceso es none responde el mismo 404. Cuando tu nivel es view, el NIF es visible pero toda escritura sobre él responde 403 company_read_only.

Una credencial fact_test_ pertenece a la cuenta real, así que lee la cuenta de producción igual que una credencial de producción. Las escrituras de las capacidades de cuenta (equipo, invitaciones, titularidad, traspasos y API keys) responden 403 live_credential_required. Probar cuentas gestionadas explica qué puede escribir una clave de pruebas.

Roles y grants

Cada persona de la cuenta es un miembro con uno de tres roles. El rol decide qué NIF alcanza la persona.

RolNIF que alcanzaNotas
owner (titular)Todos los NIF, sin grantsAdministra la cuenta: equipo, NIF y facturación. Hay exactamente un titular. Solo el titular traspasa la titularidad, y nadie cambia el rol del titular ni lo retira.
admin (administrador)Todos los NIF, sin grantsAdministra la cuenta igual que el titular (equipo, NIF y facturación), sin poder traspasar la titularidad.
member (miembro)Solo los NIF en los que tiene un grantEl grant fija el nivel: view es solo lectura y operate también puede escribir.

Un grant (permiso por NIF) es el acceso de un miembro a un NIF, con el nivel view u operate. Solo un miembro lleva grants. Pasar a un miembro a admin revoca sus grants, porque un administrador ya alcanza todo. Cada miembro muestra además un bloque permissions con lo que puede hacer en ese miembro quien lee la respuesta, así que dos credenciales pueden leer permisos distintos del mismo miembro.

El asesor externo es la persona externa a la que tu cuenta puede dar acceso: siempre es member, hay uno por cuenta, en cualquier plan, con grants como cualquier otro miembro y sin ocupar plaza. Asesor externo explica cómo marcarlo.

Miembros

La pertenencia es de la cuenta, no de un NIF. Estas son las operaciones del recurso de miembros:

OperaciónScopeQué hace
GET /v1/accounts/{account}/membersmembers:readLista todos los miembros, con paginación por cursor.
POST /v1/accounts/{account}/membersmembers:writeCrea a una persona como miembro.
GET /v1/accounts/{account}/members/{member}members:readConsulta un miembro.
PATCH /v1/accounts/{account}/members/{member}members:writeCambia el role, la marca external_advisor, o ambos.
DELETE /v1/accounts/{account}/members/{member}members:writeRetira al miembro de toda la cuenta. Irreversible.
GET /v1/accounts/{account}/members/{member}/grantsmembers:readLista los grants de un miembro.
GET /v1/accounts/{account}/members/{member}/grants/{company}members:readConsulta el grant sobre un NIF.
PUT /v1/accounts/{account}/members/{member}/grants/{company}members:writeCrea o reemplaza el grant sobre un NIF.
DELETE /v1/accounts/{account}/members/{member}/grants/{company}members:writeRevoca el grant sobre un NIF.
GET /v1/accounts/{account}/members/{member}/module-accessmembers:readConsulta las restricciones de módulos de un miembro sobre un NIF.
PATCH /v1/accounts/{account}/members/{member}/module-accessmembers:writeReemplaza las restricciones de módulos de un miembro sobre un NIF.

Las reglas que importan al escribir en el equipo:

  • Quién puede. La persona que emitió la credencial tiene que ser titular o administrador de la cuenta, con la sección user_management disponible. Si no, la respuesta es 403 forbidden_action.
  • Scope de la credencial. Crear un miembro y cambiar un rol cambian el equipo de toda la cuenta, así que el scope de la credencial tiene que cubrir todos los NIF de la cuenta. Si no, la respuesta es 403 forbidden_action.
  • Crear. El body lleva name, email, la password inicial, el role (admin o member) y grants. grants es obligatorio y puede ir vacío; si falta, responde 400 parameter_missing. Los grants sobre un admin responden 422 grants_only_for_member, y un grant sobre un NIF fuera de la cuenta o fuera del scope de tu credencial responde 422 grant_company_not_in_account. La persona recibe un correo para verificar su dirección. Un correo que ya está registrado responde 422 business_rule_violation: añade a las personas que ya existen con una invitación.
  • Un grant. PUT reemplaza el grant: repetirlo con el mismo nivel deja el mismo estado y no envía nada. Bajar un grant baja también las API keys de ese miembro. DELETE responde 204 aunque no hubiera grant. Un grant sobre un owner o un admin responde 422 grants_only_for_member.
  • Retirar. DELETE retira a la persona de todos los NIF de la cuenta: pierde sus grants y sus sesiones allí y sus API keys pierden ese scope. Para retirar el acceso a un solo NIF, revoca ese grant. El titular responde 422 member_is_last_owner: traspasa antes la titularidad. Retirarte a ti mismo responde 422 business_rule_violation. Exige una Idempotency-Key.
  • Restricciones de módulos. restrictions es una lista de denegaciones de las capacidades access, delete, send y export por sección, que se aplica sobre el grant. Un objeto vacío significa ninguna restricción, nunca ningún acceso, y nunca concede más de lo que concede el grant. PATCH reemplaza el conjunto completo.
  • Qué lees. Se lista a todos los miembros, pero solo se publican los grants sobre NIF que tu credencial lee. Un miembro desconocido, de otra cuenta o con un identificador mal formado responde el mismo 404 member_not_found.

Da a un miembro operate sobre un NIF:

curl -X PUT "https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/members/$MEMBER_ID/grants/$COMPANY_ID" \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "level": "operate" }'
{
  "data": {
    "object": "account_member_grant",
    "company_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a01",
    "level": "operate"
  }
}

Invitaciones

Una invitación añade a la cuenta a una persona que ya existe en la plataforma, con un rol y los grants iniciales.

OperaciónScopeQué hace
POST /v1/accounts/{account}/invitationsinvitations:writeEnvía una invitación.
GET /v1/accounts/{account}/invitationsinvitations:readLista las invitaciones, filtradas por status.
GET /v1/accounts/{account}/invitations/{invitation}invitations:readConsulta una invitación.
POST /v1/accounts/{account}/invitations/{invitation}/resendinvitations:writeReenvía una invitación pendiente con un secreto nuevo.
DELETE /v1/accounts/{account}/invitations/{invitation}invitations:writeRevoca una invitación pendiente.
  • Body. email, role (admin o member), grants (obligatorio, puede ir vacío, solo para un member) y send_email, que vale true por defecto. Crear y reenviar exigen una Idempotency-Key.
  • El secreto se muestra una vez. Con send_email: false, la respuesta lleva el secret de aceptación y la accept_url exactamente una vez, y entregas tú el enlace. Con send_email: true, el secreto viaja solo en el correo y los dos campos van a null. Una repetición idempotente también devuelve null, y ninguna lectura los devuelve.
  • Invitaciones de administrador. Invitar a un admin exige una credencial cuyo scope cubra todos los NIF de la cuenta, y lo mismo vale para reenviarla.
  • Estados. pending, accepted, revoked y expired. Revocar nunca retira a una persona que ya se unió, y una invitación que ya estaba aceptada o revocada responde 422 business_rule_violation. Una caducada responde 422 invitation_expired al reenviarla: envía una nueva.
  • Qué puede responder una escritura. 422 business_rule_violation cuando ya existe una invitación pendiente para esa dirección, la persona ya es miembro, se repite un NIF o la cuenta alcanzó el límite de usuarios de su plan; 422 grants_only_for_member y 422 grant_company_not_in_account igual que con los miembros; y 404 invitation_not_found para una invitación que no existe o es de otra cuenta.
  • El asesor externo. Su invitación solo se envía desde la aplicación web: una invitación creada por la API nunca lleva esa marca. Cuando la persona ya se ha unido, puedes marcar al miembro con PATCH.
curl -X POST "https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/invitations" \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
        "email": "laura@acme.example",
        "role": "member",
        "grants": [
          { "company_id": "0193f1a0-5c2e-7b41-8d06-9a1e2f3c4d5e", "level": "view" }
        ],
        "send_email": false
      }'

Titularidad de la cuenta

La cuenta tiene un titular, y es la única persona que puede traspasar la titularidad. PATCH /v1/accounts/{account}/owner necesita el scope account:owner, el privilegio más alto de la cuenta, y la persona detrás de la credencial tiene que ser el titular actual. Se comprueba en cada petición, así que una credencial no conserva el poder si quien la creó deja de ser el titular.

curl -X PATCH "https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/owner" \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "owner_user_id": "0199a1f0-1c22-7a10-b111-1a1b1c1d1e1f" }'
{
  "data": {
    "account_id": "0199a1f0-1c22-7a10-b111-0a0b0c0d0e0f",
    "object": "account_owner",
    "owner_user_id": "0199a1f0-1c22-7a10-b111-1a1b1c1d1e1f",
    "previous_owner_user_id": "0199a1f0-1c22-7a10-b111-2a2b2c2d2e2f"
  }
}
  • El destino. owner_user_id es el identificador de la persona, no el id del recurso de miembro. El destino tiene que ser miembro de la cuenta y no puede ser el asesor externo.
  • Qué cambia. En una sola transacción, el titular anterior pasa a admin y el destino pasa a owner. Los dos conservan el acceso a todos los NIF, y no cambia ningún NIF, API key ni plan. Traspasar al titular actual no cambia nada.
  • Irreversible. Exige una Idempotency-Key y, sin ella, responde 422 idempotency_key_required.
  • Errores. 403 owner_transfer_forbidden cuando quien llama no es el titular actual; no revela quién lo es ni si el destino existe. 422 invalid_param_value cuando falta owner_user_id o está mal formado. 422 business_rule_violation cuando el destino no existe, no es miembro o es el asesor externo, los tres con el mismo body.

El rol del titular no se puede cambiar con PATCH sobre el miembro (cannot_change_account_owner_role): la titularidad se traspasa, nunca se reasigna.

Traspasos de NIF

Un NIF pasa de una cuenta a otra con un traspaso de NIF. Siempre lo inicia la cuenta que lo entrega: ninguna operación permite que una cuenta pida el NIF de otra.

Emite el traspaso. La cuenta que entrega el NIF llama a POST /v1/accounts/{account}/nif-transfers con el company_id del NIF que cede. El recipient_account_id, opcional, cierra el traspaso a una sola cuenta, y el expires_at, también opcional, fija la caducidad. La respuesta es 201 y lleva el secret exactamente una vez.

curl -X POST "https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/nif-transfers" \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
        "company_id": "0199a1f0-1c22-7a10-b111-4a4b4c4d4e4f",
        "recipient_account_id": "0199a1f0-1c22-7a10-b111-5a5b5c5d5e5f"
      }'
{
  "data": {
    "id": "0199a1f0-1c22-7a10-b111-3a3b3c3d3e3f",
    "object": "nif_transfer",
    "company_id": "0199a1f0-1c22-7a10-b111-4a4b4c4d4e4f",
    "expires_at": "2026-10-04T09:00:00+00:00",
    "status": "active",
    "recipient_account_id": "0199a1f0-1c22-7a10-b111-5a5b5c5d5e5f",
    "secret": "<secreto en claro, 48 caracteres>"
  }
}

Entrega el secreto. Envíalo a la cuenta receptora por un canal de confianza. Quien tenga el secreto puede aceptar el traspaso, o solo la cuenta destinataria cuando fijaste una. El secreto no se guarda nunca en claro y ninguna lectura posterior lo devuelve. Si lo pierdes, revoca el traspaso y emite otro.

Acepta el traspaso. La cuenta receptora llama a POST /v1/accounts/{account}/nif-transfers/accept, donde {account} es su propia cuenta. El body lleva el secret y nada más: el traspaso nombra el NIF, así que un company_id se rechaza.

curl -X POST "https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/nif-transfers/accept" \
  -H "Authorization: Bearer $FACTUAREA_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "secret": "EJEMPLOdeTRASPASOnoVALIDOnoSIRVEparaACEPTARnada0" }'
{
  "data": {
    "id": "0199a1f0-1c22-7a10-b111-3a3b3c3d3e3f",
    "object": "nif_transfer",
    "company_id": "0199a1f0-1c22-7a10-b111-4a4b4c4d4e4f",
    "expires_at": "2026-10-04T09:00:00+00:00",
    "status": "consumed",
    "recipient_account_id": null
  }
}

Revócalo si el secreto se filtra. Mientras nadie lo haya aceptado, la cuenta que entrega el NIF puede llamar a POST /v1/accounts/{account}/nif-transfers/{nif_transfer}/revoke, con un reason opcional de hasta 500 caracteres que queda en el registro de auditoría. Revocar un traspaso ya revocado responde el mismo 200, y un traspaso revocado no vuelve.

OperaciónScopeQué hace
POST /v1/accounts/{account}/nif-transfersnif_transfers:writeEmite un traspaso.
POST /v1/accounts/{account}/nif-transfers/acceptnif_transfers:writeAcepta un traspaso con su secreto.
POST /v1/accounts/{account}/nif-transfers/{nif_transfer}/revokenif_transfers:writeRevoca un traspaso que nadie aceptó.
GET /v1/accounts/{account}/nif-transfersnif_transfers:readLista los traspasos que emitió tu cuenta.
  • Caducidad. Sin expires_at, un traspaso dura 24 horas. Pasa expires_at para elegir otro instante futuro, hasta 7 días: un valor pasado, demasiado lejano o que no se puede interpretar responde 422 business_rule_violation.
  • Quién puede. La empresa titular de la cuenta no se puede ceder. Emitir exige un rol administrativo en ese NIF, y una credencial cuyo acceso a él es view responde 403 company_read_only. Un NIF que no existe, es de otra cuenta o queda fuera de tu ámbito responde 404 profile_not_found.
  • Irreversible. Emitir, aceptar y revocar exigen una Idempotency-Key y, sin ella, responden 422 idempotency_key_required.
  • Listado. Muestra solo los traspasos que emitiste tú y solo sobre los NIF que tu credencial alcanza, nunca los que recibiste. status es active, expired, revoked o consumed: se deriva del reloj en cada lectura, y puedes filtrar por él.
  • Qué hace la aceptación. En una sola transacción, y como mucho una vez incluso con peticiones concurrentes, el NIF pasa a la cuenta receptora junto con la empresa sandbox de ese NIF cuando la cuenta que lo entrega la tiene. Las credenciales de la cuenta que entrega lo pierden de su ámbito, y las personas de esa cuenta que no pertenecen también a la cuenta receptora pierden el acceso, y se cierran sus sesiones web y los tokens OAuth ligados a él.
  • El precio de recibir. El NIF que llega es un NIF adicional de la cuenta receptora, salvo que esa cuenta se registrara sin NIF: entonces pasa a ser su NIF titular y no se cobra. El control se ejecuta antes de mover nada, así que un rechazo deja el traspaso vigente y el NIF donde estaba: 403 billing_managed_by_provider, 402 additional_nif_plan_required, 403 additional_nif_not_in_plan, 422 business_rule_violation con el subcódigo additional_nif_limit_reached, 402 payment_method_required y 402 additional_nif_charge_failed. En producción y con suscripción de pago, el cargo se hace al aceptar, y se compensa si el traslado falla después.
  • Qué puede responder la aceptación. 422 nif_transfer_invalid cuando el secreto no coincide con ningún traspaso, ya se consumió o se revocó, va dirigido a otra cuenta o su NIF ya cambió de cuenta. Todos esos casos comparten body a propósito: distinguirlos revelaría si ese secreto existió alguna vez. 422 nif_transfer_expired es un código distinto, para que quien lo tiene sepa que debe pedir otro secreto. 422 business_rule_violation con el subcódigo account_must_keep_one_nif cuando la cuenta que entrega se quedaría sin ningún NIF activo, y 409 resource_conflict cuando una cuenta registrada sin NIF ya guarda datos de negocio en su empresa vacía.

La palabra reclamación pertenece solo a las cuentas gestionadas: el cliente de una cuenta gestionada la reclama con un vale. Un NIF que cambia de cuenta es siempre un traspaso.

El estado de un NIF

Cada NIF de la cuenta tiene un status.

EstadoQué significa
activeEl NIF está operativo.
inactiveEl NIF está desactivado: no es operable, pero conserva sus datos y puedes reactivarlo.
archivedEl NIF ya no acepta operaciones. Es terminal, aunque la empresa y su historial se conservan.

Un NIF active puede pasar a inactive o a archived, y uno inactive puede pasar a active o a archived. La cuenta tiene que conservar siempre al menos un NIF active: desactivar o archivar el último active responde 422 business_rule_violation con el subcódigo account_must_keep_one_nif. Archivar también puede quedar bloqueado por documentos fiscales abiertos.

OperaciónScopeQué hace
GET /v1/accounts/{account}/companiescompanies:readLista los NIF. Por defecto solo active e inactive; status=archived trae los archivados.
GET /v1/accounts/{account}/companies/{company}companies:readConsulta un NIF.
POST /v1/accounts/{account}/companies/{company}/deactivatecompanies:writePasa un NIF active a inactive.
POST /v1/accounts/{account}/companies/{company}/activatecompanies:writeReactiva un NIF inactive.
DELETE /v1/accounts/{account}/companies/{company}companies:deleteArchiva un NIF. Nunca cobra.

Cartera de NIF explica cómo dar de alta y editar NIF.

  • paid_until. Es el final de la cobertura pagada de un NIF adicional, en ISO 8601. Reactivar el NIF antes de esa fecha es gratis, y desactivarlo conserva la cobertura. Vale null cuando el NIF nunca se cobró o la cobertura caducó. Solo un periodo nuevo justifica un cargo nuevo, así que reactivar tras caducar la cobertura se cobra como un nuevo NIF adicional.
  • suspension_reason. Dice por qué el sistema suspendió un NIF inactive: payer_blocked cuando la cuenta que paga una cuenta gestionada tiene su cobro bloqueado, y management_ended cuando la gestión terminó antes de que nadie asumiera el pago. Vale null cuando el sistema no suspende el NIF, por ejemplo cuando lo desactivó la propia cuenta.
  • Quién puede. Dar de alta, editar, activar, desactivar y archivar exigen un titular o administrador de la cuenta con la sección user_management disponible: si no, 403 forbidden_action, antes de cobrar o cambiar nada. Una credencial cuyo acceso a ese NIF es view responde 403 company_read_only, y una sin acceso responde el mismo 404 que un NIF fuera de la cuenta.

Estadísticas por NIF

GET /v1/accounts/{account}/companies/stats devuelve una fila company_stats por cada NIF que lee tu credencial, sin los archivados: invoices_count (facturas emitidas del periodo, es decir, enviadas, pagadas y vencidas), total_invoiced (una cadena con dos decimales) y last_invoice, que es la última factura emitida del NIF sea cual sea el periodo, o null cuando aún no ha emitido ninguna.

El periodo es date_from y date_to (YYYY-MM-DD, ambas opcionales e inclusivas). Sin ellas es el año natural en curso, y con solo una de las dos el otro extremo se queda en el mismo año. La lista no se pagina: has_more es siempre false y next_cursor es siempre null. Una fecha mal formada, o un final anterior al inicio, responde 422 invalid_param_value.

curl "https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/companies/stats?date_from=2026-01-01&date_to=2026-09-30" \
  -H "Authorization: Bearer $FACTUAREA_KEY"
{
  "data": [
    {
      "object": "company_stats",
      "company_id": "01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c",
      "tax_id": "B12345674",
      "name": "Talleres García SL",
      "invoices_count": 3,
      "total_invoiced": "363.00",
      "last_invoice": {
        "number": "F-2026-003",
        "issued_on": "2026-09-20",
        "total": "121.00"
      }
    },
    {
      "object": "company_stats",
      "company_id": "01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0d",
      "tax_id": "B87654323",
      "name": "Distribuciones Norte SL",
      "invoices_count": 0,
      "total_invoiced": "0.00",
      "last_invoice": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}

¿Puede emitir este NIF?

GET /v1/accounts/{account}/companies/{company}/issuing-readiness responde si un NIF está listo para emitir facturas. Es una lectura fiscal y neutra: can_issue es el veredicto, blockers es la lista de motivos legibles por máquina cuando vale false, y los demás campos son las señales con las que se compuso el veredicto (census_status, has_default_series, fiscal_profile_complete, operable, missing_modules y checked_at). Nunca consulta la suscripción, el plan, la cuota ni el precio, y nunca responde con un estado de pago requerido.

{
  "data": {
    "can_issue": false,
    "blockers": [
      "census_not_identified",
      "no_default_series"
    ],
    "census_status": "not_identified",
    "has_default_series": false,
    "fiscal_profile_complete": true,
    "operable": true,
    "missing_modules": [],
    "checked_at": "2026-05-25T18:00:00+00:00"
  }
}
  • Ramifica por el código. Cada bloqueo es un código estable, como verifactu_certificate_missing cuando VeriFactu está activo para el NIF y este no tiene un certificado válido. Con el tiempo pueden añadirse motivos nuevos: trata uno desconocido como un bloqueo que no puedes resolver por la API.
  • En el listado. Añade include=readiness a GET /v1/accounts/{account}/companies y cada NIF lleva un objeto readiness con este mismo contrato. Cualquier otro valor de include responde 422 invalid_param_value.
  • Una sola respuesta para cada fallo. Un NIF que no existe, es de otra cuenta, queda fuera de lo que lee tu credencial o tiene un identificador mal formado responde el mismo 404 resource_not_found, nunca un 403, para que la respuesta no sirva para hacer un censo de NIF por diferencia.

Qué comparten los NIF de una cuenta

  • Credenciales y consumo. La mayoría de los límites no se comparten. El tope de claves (max_api_keys) se cuenta por NIF, y la cuota mensual por clave y NIF efectivo. Solo portfolio_max_api_keys, el tope de claves de una cuenta que opera una cartera, se cuenta sobre toda la cuenta. GET /v1/accounts/{account}/usage informa del consumo de la cuenta y lo desglosa por NIF sobre el mismo total. Una clave lista y gestiona solo las claves cuyo ámbito de NIF queda entero dentro del suyo, así que una credencial acotada a unos pocos NIF no ve una clave que alcanza también a otro (quién ve y gestiona una clave). API keys y claves acotadas explican cómo acotar una clave a una parte de los NIF.
  • Límites de cartera. Una credencial opera una cartera cuando su cuenta tiene al menos dos NIF reales. La sandbox de la cuenta no cuenta: un NIF titular y su sandbox no son una cartera. Emitir una credencial por encima del tope de claves de la cartera responde 422 portfolio_max_api_keys_exceeded. Los límites de peticiones de una cartera (429 portfolio_rate_limit_exceeded y 429 portfolio_monthly_quota_exceeded) funcionan por ahora en modo observación (shadow) y todavía no rechazan. Los explican los límites de peticiones.
  • Identidad de correo. Un NIF que no es el titular, porque la cuenta lo compró o lo recibió por traspaso, toma el régimen de una cuenta nueva (account_probation_limit_exceeded) y la comprobación de identidad del remitente para enviar correo del NIF titular de su cuenta. El titular no hereda de nadie. Los NIF de una cuenta gestionada heredan del NIF titular de la cuenta del proveedor mientras dure la gestión, y de su propio NIF titular cuando termina. Un NIF que alcanzas por acceso cedido no hereda nada de la cuenta que recibe el acceso: su confianza sigue siendo la del NIF titular de su propia cuenta. Envío de documentos describe la comprobación.

Scopes

ScopeOperacionesPlan
members:read, members:writeMiembros, grants y restricciones de módulosNecesita el módulo user_management
invitations:read, invitations:writeInvitacionesNecesita el módulo user_management
account:ownerTraspaso de la titularidadCualquier plan
nif_transfers:read, nif_transfers:writeTraspasos de NIFNecesita el módulo user_management
companies:read, companies:write, companies:deleteEstado, estadísticas y aptitud de emisión de los NIFCualquier plan

Ninguno de estos scopes se obtiene por OAuth: el canal OAuth del servidor MCP no alcanza las capacidades de cuenta, así que usa una API key. En un plan sin el módulo user_management, los scopes members:*, invitations:* y nif_transfers:* no se pueden asignar a una clave, y GET /v1/me lista solo los efectivos. Los scopes privilegiados accounts:* que aprovisionan cuentas gestionadas son otra familia: los describe cuentas gestionadas.

En esta página

¿Te echamos una mano?Contactar con soporte