Factuarea APIDevelopers

Additional tax IDs

Buy more tax IDs for your account: plan, charge, trial, cap and the preview before you commit.

Your account is opened with one tax ID, its titular company. Every other tax ID the account operates is an additional tax ID, whether you register it, reactivate it or receive it by a tax ID transfer. Additional tax IDs are billed as a monthly add-on, so adding one can charge your account on the spot. This guide covers what you pay, which plans allow them, the cap, the trial rule, the preview and the four codes that reject an addition.

The writes and the preview live on the account axis: {account} is the account.id you read from GET /v1/me, and {company} is a company's id, an opaque UUID v7, not its tax_id. The billing read at the end lives on the company axis.

What counts as an additional tax ID

  • The first tax ID never counts. The titular company is the one the account was opened with and the one that contracts the plan. The first tax ID that enters an account with no active tax ID is not an additional tax ID.
  • Only active tax IDs count. The billed quantity is the number of active tax IDs minus the titular company. A tax ID that is inactive or archived, and the sandbox company of a tax ID, do not count.
  • The way in does not matter. A tax ID you register through the API or from the app, one you reactivate and one you receive by transfer cost the same once they are active.

The quantity follows your portfolio on its own, and an hourly reconciliation keeps it aligned with the number of active additional tax IDs. The reconciliation corrects the quantity without charging or crediting anything.

Price and plans

An additional tax ID costs 15.00 EUR per month before VAT. It is always billed monthly, even when the account's plan is annual, and it lives in its own subscription of the account (additional-nifs), separate from the one that pays the plan.

The API does not hold the amount: it is the price of the add-on. To know what your account pays, read unit_amount in gestoria_seats or ask the preview instead of hard-coding 15.00.

Only some plans allow additional tax IDs:

PlanAdditional tax IDs
emprendedorNot allowed: 403 additional_nif_not_in_plan.
empresarioAllowed, billed monthly.
integralAllowed, billed monthly.
enterpriseAllowed. If the account is billed by contract, with no paid subscription, nothing is charged.

The plan of an additional tax ID does not follow the plan of the account. On a Profesional (empresario) or Avanzado (integral) account, every additional tax ID has the Profesional plan (empresario); only the titular tax ID has the plan of the account.

The account also needs a current plan. With none (cancelled or expired) the answer is 402 additional_nif_plan_required. A trial counts as a current plan, see the trial rule. The plan is checked inside each operation and not through the scopes: the companies:* scopes do not depend on the plan.

The cap

Your contract can set a maximum number of active additional tax IDs for the account. It is kept on the account as max_additional_nifs. By default it is empty, which means no cap, and only we set it, by contract. The API does not return it.

When adding one more tax ID, or several at once, would leave the account above the cap, the answer is 422 business_rule_violation with subcode additional_nif_limit_reached, before anything is charged or changed. A batch is rejected as a whole: it never lets some of its tax IDs through and stops others.

{
  "error": {
    "type": "invalid_request_error",
    "code": "business_rule_violation",
    "subcode": "additional_nif_limit_reached",
    "message": "Has alcanzado el máximo de NIF adicionales de tu contrato (5).",
    "doc_url": "https://docs.factuarea.com/guides/errors#business_rule_violation",
    "request_id": "req_c15e7a1c0d9b3f46a28c060000"
  }
}

The four writes

Four operations can add an active additional tax ID. They go through the same gate, with the same codes and in the same order.

WriteEndpointScope
Register a new tax IDPOST /v1/accounts/{account}/companiescompanies:write
Reactivate one tax IDPOST /v1/accounts/{account}/companies/{company}/activatecompanies:write
Reactivate several at oncePOST /v1/accounts/{account}/companies/activatecompanies:write
Accept a tax ID transferPOST /v1/accounts/{account}/nif-transfers/acceptnif_transfers:write

What the four share:

  • Idempotency-Key is required. A request without it is rejected with 422 idempotency_key_required before any business logic runs.
  • Who can ask. The credential must reach the titular company of the account, which is the company that pays. To register or reactivate, the person who issued the key must also be an owner or admin of the account with the user_management section available; to accept a transfer, they need an administrative role in at least one tax ID of the receiving account. Otherwise the answer is 403 forbidden_action, before anything is charged or changed.
  • A read-only credential. If the credential only has view access to the tax ID, reactivating or accepting a transfer returns 403 company_read_only.
  • The batch is all or nothing. company_ids takes between 1 and 1000 ids. Every tax ID is validated before any charge: it must belong to the account and be inactive (422 business_rule_violation otherwise), and one that is not of the account returns 404 for the whole batch. The combined additional tax IDs are charged in a single invoice.
curl -X POST https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/companies \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Talleres García SL",
    "tax_id": "B12345674"
  }'

The 201 is the new company, with status: "active". Its paid_until is the end of the period it is paid for, or null when it was not charged (a trial, for example). A tax_id already registered in your account returns 409 resource_already_exists; one that belongs to another account returns 422 business_rule_violation and is moved with a tax ID transfer instead.

The gate and its four codes

Before anything is created, reactivated, moved or charged, each write runs the additional tax ID gate. It checks in this order and stops at the first failure:

  1. Who pays. The account must pay for itself.
  2. The plan. The account needs a current plan that allows additional tax IDs.
  3. The cap. The account must stay within max_additional_nifs.
  4. The charge. In live mode with a paid subscription, the charge must go through.

Every rejection arrives before any charge and writes nothing: no tax ID is created, reactivated or moved, and nothing is charged. The four codes of the gate:

CodeStatusWhat it meansWhat to do
billing_managed_by_provider403Another account pays this account's billing, so it cannot add a tax ID on its own.Ask the account that pays to add, reactivate or accept the tax ID. See accounts paid by their provider.
additional_nif_plan_required402The account has no current plan, so there is no subscription to bill the additional tax ID to.Subscribe to empresario, integral or enterprise, or resume the cancelled plan, and repeat the same call.
additional_nif_not_in_plan403The plan is current but does not allow additional tax IDs (emprendedor).Move the account to empresario, integral or enterprise and repeat the same call. It is a plan limit, not a missing payment.
additional_nif_charge_failed402The immediate charge was declined: the card was refused, it needs authentication or the payment provider was unreachable.Fix the payment method in the billing portal and repeat the same call.

Other rejections you can meet on the same writes:

CodeStatusWhat it means
business_rule_violation with subcode additional_nif_limit_reached422The addition would leave the account above its cap.
payment_method_required402Live mode, paid subscription and no payment method on file. error.details.payment_setup_url links to where to set one up.
forbidden_action403The credential does not reach the titular company, or the person who issued the key does not have the role the write requires.
company_read_only403The credential only has view access to the tax ID.
idempotency_key_required422The request carries no Idempotency-Key.

When you are charged

In live mode with a paid subscription the additional tax ID is charged at once on the account's additional-nifs subscription: prorated for the rest of the current period or, when it is the first one and the subscription is created, the full first month. With no payment method on file the write is rejected with 402 payment_method_required:

{
  "error": {
    "type": "payment_required_error",
    "code": "payment_method_required",
    "message": "La cuenta no tiene un método de pago configurado para cobrar el NIF adicional: configúralo y vuelve a intentarlo.",
    "details": {
      "payment_setup_url": "https://billing.stripe.com/p/session/live_YWNjdF8xS2ZHM0RLb0h4RXBGV3lY"
    },
    "doc_url": "https://docs.factuarea.com/guides/errors#payment_method_required",
    "request_id": "req_c15e7a1c0d9b3f46a28c010000"
  }
}

A declined charge is 402 additional_nif_charge_failed. If the operation itself fails after the charge, the charge is compensated: you are never left paying for a tax ID that was not added.

Nothing is charged when the account is in its trial, when it is an enterprise account billed by contract with no paid subscription, when it is a test account (the gate makes no call to the payment provider, see test managed accounts) or when the tax ID is still covered.

Coverage. paid_until on the company is the end of the period the tax ID is paid for. Each paid renewal extends it, for every active additional tax ID, to the end of the new period. Deactivating a tax ID (POST /v1/accounts/{account}/companies/{company}/deactivate) releases it without a credit but keeps its coverage, so reactivating it before paid_until is free. After the coverage expires, paid_until is null and reactivating is charged again. Deactivating is never billed and never returns 402, and the account must keep at least one active tax ID (422 business_rule_violation with subcode account_must_keep_one_nif).

The trial rule

While the account is in its trial, additional tax IDs are free, however they are added. That covers the trial window without a subscription and a plan subscription that is in its trial period (a card on file, status trialing). The preview answers included_in_trial: true with no charge.

When the account starts paying, because the trial ends and the first charge goes through or because it subscribes straight to a paid plan, the additional tax IDs it held for free become inactive, with no charge and no credit. We do it so that nothing is charged that you did not choose. Two details:

  • A tax ID whose paid_until is still in the future stays active, because it was already paid.
  • The rule only acts in live mode on an account that really charges: a test account keeps its tax IDs.

You then reactivate the ones you want to keep, one by one or in a batch, and each reactivation is charged like any other.

When your plan changes

The life of the plan carries the additional tax IDs along:

  • A plan that does not allow them. Moving down to a plan without additional tax IDs, or a plan that expires (an expired trial, a payment that could not be recovered, a deleted subscription), deactivates the active additional tax IDs, never the titular company, and releases them without a credit. On expiry the additional-nifs subscription is also cancelled at once. Moving between plans that do allow them, such as enterprise to empresario, changes nothing.
  • Cancelling the plan schedules the cancellation of the additional tax IDs subscription for the same date, at period end or at once, like the plan. Resuming the plan removes that scheduled cancellation as long as the account still has active additional tax IDs.
  • They do not come back on their own. A tax ID deactivated this way is reactivated with a plan that allows it, and the reactivation is charged.

Preview the charge

GET /v1/accounts/{account}/companies/seat-charge-preview returns what the next addition would cost, computed from the upcoming invoice of the titular company, without charging. It needs companies:read.

ParameterNotes
countPreview a batch of N tax IDs, between 1 and 1000 (1 by default).
company_ids[]Coverage-aware preview by UUID v7: tax IDs still covered for the period cost 0 with already_covered: true. When you send it, it overrides count.
curl -G https://api.factuarea.com/v1/accounts/$ACCOUNT_ID/companies/seat-charge-preview \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  --data-urlencode "count=3"
{
  "data": {
    "object": "seat_charge_preview",
    "amount": "7.50",
    "tax_amount": "1.58",
    "total": "9.08",
    "tax_rate": 21,
    "currency": "EUR",
    "next_invoice_date": "2026-04-01T00:00:00Z",
    "requires_payment_method": false,
    "requires_active_plan": false,
    "included_in_trial": false,
    "already_covered": false,
    "is_first_seat": false,
    "recurring_quantity": 3,
    "recurring_base_cents": 4500,
    "recurring_total_cents": 5445
  }
}
FieldMeaning
amount, tax_amount, totalThe proration charged now: taxable base, VAT and their sum, in euros as strings with two decimals.
tax_rate, currency, next_invoice_dateThe VAT rate in percent (null when it could not be resolved), EUR and the date of the next invoice of the add-on.
already_covered, requires_active_plan, included_in_trial, requires_payment_methodWhy the amount is 0, or what is missing. At most one is true. requires_active_plan covers both no current plan and a plan that does not allow additional tax IDs.
is_first_seattrue when the operation creates the first additional tax ID subscription of the account: the charge is then the full month, and today becomes the monthly billing day.
recurring_quantity, recurring_base_cents, recurring_total_centsThe monthly fee after the operation: how many additional tax IDs will be billed, their base and the same with VAT. The two _cents fields stay in cents, as their names say, and recurring_total_cents is null when VAT is unknown.

The preview is a read: it never returns 402 and it does not evaluate the plan or the cap of the writes. A tax ID that is not additional, a test account, an account with no current plan and one whose plan does not allow additional tax IDs all preview 0. It returns 403 billing_managed_by_provider when the provider pays the billing of the account, and 404 when a company_ids value is not a tax ID of the account.

A preview that looks fine does not promise the write will go through: the cap is only checked when you add the tax ID. If the payment provider cannot simulate the invoice, the preview falls back to the price of the add-on before VAT, so tax_rate and recurring_total_cents can be null.

Receive a tax ID by transfer

Accepting a tax ID transfer with POST /v1/accounts/{account}/nif-transfers/accept adds the incoming tax ID to the receiving account as an additional tax ID. The gate of the receiving account runs before anything moves. A rejection leaves the transfer valid and the tax ID in the issuing account, so you can fix the cause, such as a plan or a payment method, and accept again with the same secret.

In live mode with a paid subscription the tax ID is charged on acceptance, and if the move fails after the charge, the charge is compensated. The receiving side needs an administrative role in at least one tax ID of its account, and a credential that reaches the titular company of the receiving account with write access (403 forbidden_action, or 403 company_read_only when it is read-only).

There is one exception: an account registered without a tax ID receives the tax ID as its titular company, and pays nothing.

Accounts paid by their provider

A managed account whose management is in force and whose billing is paid by its provider does not buy anything on its own. Its account holder receives 403 billing_managed_by_provider on the four writes and on the preview.

The provider adds the tax IDs instead. People of the provider account with operate access to the managed account register and reactivate them through the same endpoints, using the managed account's {account}, and the charge goes to the provider's managed-accounts subscription, prorated at once. The gate still judges the managed account itself: its own plan (emprendedor gets 403 additional_nif_not_in_plan), its own cap and the provider's payment method (402 payment_method_required when it has none, 402 additional_nif_charge_failed when the charge is declined). Test accounts and enterprise managed accounts, billed by contract, are not charged.

When the client takes over the payment, or the management ends after the claim, the account pays for itself again and everything above applies to its own account holder. What the provider pays is in managed account pricing and payer change.

Read what you pay

GET /v1/companies/{company}/billing (scope account:read) returns the subscription snapshot of the account. Its gestoria_seats block describes the additional tax ID subscription. The field keeps its original public name so that existing integrations do not break, and there is no alias: despite the name, it counts additional tax IDs and nothing else.

{
  "gestoria_seats": {
    "status": "active",
    "quantity": 4,
    "active_companies": 4,
    "unit_amount": "15.00",
    "tax_rate": 21,
    "tax_amount": "3.15",
    "total_per_seat": "18.15",
    "recurring_total": "72.60",
    "currency": "EUR",
    "billing_interval": "month",
    "next_invoice_at": "2026-07-15T10:00:00+00:00",
    "ends_at": null
  }
}
FieldMeaning
statusStatus of the additional tax ID subscription (active, past_due…), or none when there is no subscription yet, as in a trial.
quantity, active_companiesBilled units, one per active additional tax ID, and the number of active additional tax IDs.
unit_amount, tax_amount, total_per_seat, recurring_totalThe taxable base of one unit, its VAT, the unit with VAT and the projected monthly total (total_per_seat × quantity).
billing_intervalAlways month, whatever the plan interval.

Amounts are euros as strings with two decimals, not integer cents. They are null when the cost cannot be resolved (an enterprise account outside the payment provider, a sandbox, no current plan): never a misleading 0. The whole block is null when the account has no additional tax ID subscription and no active additional tax IDs, and in a trial with active additional tax IDs it shows status: "none" and quantity: 0. A company whose billing is paid by another company answers managed: true with gestoria_seats: null, so the billing of whoever pays is never leaked.

Next steps

On this page

Need a hand?Contact support