AEAT census verification
Check your company's — and your clients' — name + NIF pair against the AEAT census before issuing VeriFactu invoices — deterministic states, sandbox magic NIFs and fail-open behavior.
Factuarea can check that your company's registered name + NIF pair is correctly identified in the AEAT census — the same identification the AEAT performs when it receives your VeriFactu invoice records. A pair that is not censused gets the submission rejected (AEAT error 4104, holder not identified), so verifying early — right after registration and whenever your fiscal data changes — saves you rejected submissions later.
POST /v1/account/census-verification- Scope:
account:read - Request body: none — the check always runs against the persisted
name and
tax_idof the authenticated account. It never accepts an arbitrary NIF or name in the payload. - Side effect: the result is stored as a snapshot on your company
(visible in the Factuarea app settings). Changing your company name or
tax_idresets the snapshot until you verify again.
This is the verification Factuarea also offers in the app during onboarding. Negative results are informational: they never block registration, invoicing or any other operation — they just warn you that VeriFactu submissions may be rejected until the census data is fixed.
Calling the endpoint
curl -X POST https://api.factuarea.com/v1/account/census-verification \
-H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
-H "Idempotency-Key: $(uuidgen)"Response (200):
{
"data": {
"object": "census_verification",
"status": "identified",
"verified_name": "ACME SOLUTIONS SL",
"checked_at": "2026-06-10T22:15:04+00:00"
}
}verified_name is the company name that was contrasted against the census
(the persisted one). checked_at is the moment of the verification, ISO
8601.
With the official SDKs:
import { Factuarea } from "@factuarea/sdk";
const factuarea = new Factuarea({ apiKey: process.env.FACTUAREA_API_KEY! });
const result = await factuarea.account.verifyCensus();
// result.data.status → "identified" | "not_identified" | …<?php
use Factuarea\Sdk\Custom\FactuareaClient;
$factuarea = FactuareaClient::create(getenv('FACTUAREA_API_KEY'));
$response = $factuarea->account->publicApiV1AccountVerifyCensus();Verify your clients too
The AEAT runs the same identification on the recipient of every VeriFactu invoice record: a client whose name + NIF pair is not censused gets the submission rejected with AEAT error 1239 (recipient not identified).
Factuarea deliberately does not validate clients against the census when you create them — and that is by design, not an oversight: foreign clients have no Spanish census entry, newly incorporated companies may take days to appear, simplified B2C invoices carry no recipient NIF at all, and the AEAT service itself can be down (the whole feature is fail-open). Blocking client creation on the census would break all those legitimate flows.
The recommended pattern instead: verify the name + NIF pair right before issuing VeriFactu invoices to that client with the dedicated endpoint:
POST /v1/clients/census-verification- Scope:
clients:read - Request body:
tax_id(NIF/CIF/NIE) andname— the pair is checked together, exactly as the AEAT will check it on submission. It doesn't need to match an existing client: the check is stateless and persists nothing on your clients. - Rate limit: 5 verifications per minute, like the account endpoint.
curl -X POST https://api.factuarea.com/v1/clients/census-verification \
-H "Authorization: Bearer fact_live_3pXnR2VbY7TcA9eFmN5z8KqW" \
-H "Content-Type: application/json" \
-d '{"tax_id": "B12345674", "name": "CONSTRUCCIONES PEREZ SL"}'Response (200):
{
"data": {
"object": "census_verification",
"status": "identified",
"verified_name": "CONSTRUCCIONES PEREZ SL",
"checked_at": "2026-06-11T09:30:00Z"
}
}The status values are the same six as the account verification (table
below). How to act on them for a client:
identified— issue normally.not_identified— a VeriFactu submission to this recipient is guaranteed to be rejected with 1239. Ask the client for their exact registered name and NIF before issuing.not_identified_similar— (individuals) use the exact name as registered with the AEAT.unavailable— the AEAT could not answer; the check is informational, so you may issue anyway and retry the verification later.
If a rejected submission slips through anyway, all is not lost: subsanación lets you fix the data and resubmit the same record. Census verification up front plus subsanación as the safety net covers the whole 1239 lifecycle.
Possible states
status is always one of these six values:
status | Meaning | What to do |
|---|---|---|
identified | The name + NIF pair matches the census. | Nothing — you are ready for VeriFactu. |
not_identified | The NIF is not identified in the census with that name. | Review your fiscal data: exact registered name and NIF. Submissions risk rejection. |
not_identified_similar | (Individuals only.) The NIF exists but the name only partially matches. | Use the exact name as registered with the AEAT. |
identified_inactive | The NIF is identified but registered as inactive (baja) in the census. | Check your census situation with the AEAT. |
identified_revoked | The NIF is identified but has been revoked. | Check your census situation with the AEAT. |
unavailable | The AEAT service could not be reached or returned an unrecognized response. | Retry later. This is not an error. |
Branch on status, the values are a frozen contract. Note that negative
states are not HTTP errors: every completed verification returns 200.
Fail-open by design
The verification never breaks your flow because the AEAT is down:
- AEAT timeout, SOAP fault or unrecognized response →
200withstatus: unavailable. Never a5xxfor this cause. - Results are cached server-side for a short period, so immediate retries of
the same pair don't hit the AEAT again (
unavailableis cached for only a few seconds so you can retry soon).
Errors
The only business error is a company without fiscal data:
{
"error": {
"type": "invalid_request_error",
"code": "census_requires_tax_id",
"message": "Configura primero los datos fiscales de tu empresa para verificar el censo.",
"param": "tax_id"
}
}| HTTP | code | When |
|---|---|---|
| 401 | missing_api_key / invalid_api_key | Missing or invalid API key. |
| 403 | insufficient_scope | The key lacks the account:read scope. |
| 422 | census_requires_tax_id | The account has no tax_id configured yet. |
| 429 | rate_limit_exceeded | More than 5 verifications per minute. |
See the error envelope guide for the full error contract.
Rate limit
The endpoint is limited to 5 verifications per minute per account,
independently of your key's global rate-limit tier. Above that you get a
429 — wait for the window to reset and retry.
Test mode: magic NIFs
With a fact_test_ key (test mode) the verification
never reaches the AEAT. The sandbox returns deterministic states based
on the sandbox company's tax_id, so you can exercise every branch of your
integration:
Sandbox tax_id | Returned status |
|---|---|
00000000T | identified |
11111111H | not_identified |
22222222J | not_identified_similar |
33333333P | identified_inactive |
44444444A | identified_revoked |
55555555K | unavailable |
| any other NIF | identified (default) |
All magic NIFs carry a valid control letter, so they pass standard NIF
validation. Set the sandbox company's tax_id to the magic value you want
to test, then call the endpoint with your fact_test_ key:
curl -X POST https://api.factuarea.com/v1/account/census-verification \
-H "Authorization: Bearer fact_test_3pXnR2VbY7TcA9eFmN5z8KqW" \
-H "Idempotency-Key: $(uuidgen)"{
"data": {
"object": "census_verification",
"status": "identified_revoked",
"verified_name": "SANDBOX COMPANY SL",
"checked_at": "2026-06-10T22:15:04+00:00"
}
}In live mode the real AEAT census is consulted with Factuarea's platform certificate. The states reflect the AEAT response verbatim — Factuarea never invents a state.
Glossary
Spanish fiscal and domain terms used across the Factuarea API — NIF, VeriFactu, AEAT, FacturaE, Modelo 303/347, series, rectificativa, huella, CSV and more.
VeriFactu record subsanación
Fix and resubmit VeriFactu billing records rejected by the AEAT — when subsanación applies, when you need an annulment or a corrective instead, and the exact API flow.