TF Fiscal
Documentation

Identity lookup

Official Brazilian registry lookups by taxpayer number: CNPJ lookup and CPF lookup with date of birth, error model, data protection and integration checklist.

Overview

Look up official Brazilian registry data by taxpayer identification number:

CapabilityEndpointWhat it returns
CNPJ lookupGET /openapi/v3/consultas/cnpj/{cnpj}Company registry data for a 14-digit corporate tax number: legal name, trade name, registration status, legal nature, CNAE activity code, registered address, contacts, share capital
CPF lookupGET /openapi/v3/consultas/cpf/{cpf}/{nascimento}Individual registry data for an 11-digit personal tax number plus date of birth: name, registration status, date of birth

Both endpoints are GET: the signed body is the empty string and all path variables (CNPJ / CPF / date of birth) are part of the signed path, see Authentication. Responses are bare objects (no platform envelope); business errors are a bare {code, message} object.

Why CPF requires a date of birth

The upstream source validates CPF and date of birth as a pair (Receita Federal semantics); a CPF alone returns nothing. A mismatched pair and a non-existent CPF return the same error code: they are deliberately not distinguished, otherwise the endpoint would become a tool for probing other people's birth dates.

Onboarding

  1. Application credential: apply for an application and receive an app_secret. It is displayed only once; store it securely.
  2. API subscription: the platform grants your application access to the endpoints you need (the scope key is the endpoint path).

Endpoints

EndpointPurpose
GET /openapi/v3/consultas/cnpj/{cnpj}Company registry data by CNPJ
GET /openapi/v3/consultas/cpf/{cpf}/{nascimento}Individual registry data by CPF and date of birth, with the LGPD age tiers

Error model

Two error shapes

Business, request-level and upstream errors (HTTP 400 / 422 / 428 / 451 / 503) are returned as a bare object:

json
{ "code": 10016003, "message": "CPF not found" }
FieldTypeDescription
codeintegerPlatform error code
messagestringHuman-readable explanation, localized to the request language

Authentication-layer errors (HTTP 401 / 403 / 429) are produced by the platform gateway before the request reaches the API, and use the platform envelope:

json
{ "success": false, "errorType": 1, "code": 10009005, "message": "API not subscribed, please subscribe before calling" }
FieldTypeDescription
successbooleanfalse for every error
errorTypeinteger1 API error, 2 SEFAZ rejection, 3 system fault, 4 field validation failure
codeintegerPlatform error code
messagestringHuman-readable explanation, localized

Note: your error handler must accept both shapes. A robust rule: parse the body as JSON, read code from either shape, and treat success=false or HTTP >= 400 as failure.

Business error codes

codeHTTPResponsible partyMeaningAction
10016000400CallerInvalid CPF format (11 digits required)Check for stray formatting characters or wrong length
10016001400CallerInvalid CPF check digitsValidate locally with the mod-11 algorithm first to avoid wasted calls
10016002400CallerInvalid date of birth (valid DDMMYYYY required)Note the day-month-year order, and that the date must actually exist
10016003400CallerCPF not foundThe CPF does not exist, or the CPF and date of birth do not match (deliberately indistinguishable)
10016004451Third party (lawful upstream block)LGPD: menor de 16 anos (Lei Felca), holder is under 16Data lawfully withheld; do not retry
10016005422Third party (lawful upstream block)LGPD: menor de idade, holder is 16 to 17Data lawfully withheld; do not retry
10016006428Third party (lawful upstream block)LGPD: idade nao verificavel - informe a data de nascimento para completar a verificacao, age cannot be verifiedThe platform already re-verified once with the date of birth; do not retry
10016010400CallerInvalid CNPJ format (14 digits required)Check for stray formatting characters
10016011400CallerInvalid CNPJ check digitsValidate locally with the mod-11 algorithm first
10016012400CallerCNPJ not foundNo such CNPJ in the official registry
10016020503Third party (upstream unavailable)Upstream data source is temporarily unavailableRetry with exponential backoff (start at 1 s, double up to 30 s, add jitter); contact the platform if it persists

Format and check-digit errors are rejected locally by the platform and never reach the upstream source: they consume no quota and are not billed.

Responsibility convention: 10016000 to 10016003 and 10016010 to 10016012 are caller-side problems; 10016004 to 10016006 are lawful third-party blocks; 10016020 is a third-party outage; HTTP 500 + 10001000 is a platform fault.

Billing: 10016003 (not found / birth date mismatch), 10016004 (under 16) and 10016005 (age 16 to 17) are billed per call; 10016006 (age unverifiable), 10016020 (upstream outage) and locally rejected format / check-digit errors are not billed. The age tiers are described in detail on the CPF lookup page.

Authentication and authorization errors

HTTPcodeMeaningAction
40110009000Missing signature headers (token / sign / timestamp)All three headers are mandatory
40110009001Timestamp invalid or clock skew beyond ±300 sSync your clock (NTP); regenerate the timestamp per request
40110009002Invalid tokenCheck the app_secret
40110009003Signature mismatchSee the checklist under Troubleshooting
40310009004Application disabledContact the platform
40310009015Application not effective (pending approval or rejected)Wait for approval
40310009014Integrator account disabledContact the platform
40310009005API not subscribedRequest a subscription for the endpoint
42910009006Rate limit exceededRetry with exponential backoff (start at 1 s, double up to 30 s, add jitter)

Retry guidance: 401 and 403 are configuration errors; retrying without a fix is pointless and may trip rate limits. 429 and 503 (10016020) are retryable with backoff. 422 / 428 / 451 are statutory blocks; retrying is pointless. For 500, contact the platform with the failing request's timestamp and path.

HTTP status quick reference

HTTPScenarioBody shape
200Lookup succeededBare data
400Invalid parameter / record not foundBare {code, message}
401Authentication failedPlatform envelope
403Application disabled / not effective / not subscribedPlatform envelope
422CPF holder is 16 to 17 (lawful upstream block, 10016005)Bare {code, message}, no personal fields
428CPF age cannot be verified (lawful upstream block, 10016006)Bare {code, message}, no personal fields
429Rate limit exceededPlatform envelope
451CPF holder is under 16 (lawful upstream block, 10016004)Bare {code, message}, no personal fields
500Platform-side fault (10001000)Bare {code, message}, contact the platform
503Upstream data source unavailable (10016020)Bare {code, message}, retry with backoff

Data protection

CPF is personal data of a natural person and is governed by Brazil's LGPD (Law 13.709/2018):

  • The platform does not persist CPF lookup results; every query hits the source in real time.
  • Full CPF values never enter application logs; they are masked.
  • Path variables in the call log are HMAC-processed before storage; no plaintext is retained.
  • The upstream source lawfully withholds data for minors; the platform passes the 451 / 422 / 428 status through unchanged and stores nothing. 451 / 422 are billed per call, 428 is not; see Minors and age verification on the CPF lookup page.

Callers are expected to observe the same minimum-necessity principle: query only where there is a lawful business basis (such as invoice issuance), and do not retain personal data beyond what the business requires.

Response localization

The message field follows the request language: the Language header (en / pt / es / zh) takes precedence, then Accept-Language (supports pt-BR and q-values). Without a language header, responses default to Portuguese (pt).

For programmatic decisions always use the numeric code and enum values such as situacao.codigo; never match on description text. The message of the LGPD blocking tiers is the statutory Portuguese wording and is not translated.

Integration checklist

  1. Obtain the app_secret and confirm both endpoints are subscribed.
  2. Call with a real CNPJ: HTTP 200, ni echoes the input, situacaoCadastral.codigo is 2.
  3. Call with a real CPF + date of birth: HTTP 200, nascimento echoes the input.
  4. Negative case: correct CPF with a wrong date of birth returns 400 + 10016003 (same code as not-found).
  5. Negative case: CNPJ / CPF with bad check digits returns 400 + 10016011 / 10016001 (rejected locally, not billed).
  6. Negative case: date of birth as 1997-01-09 or 31021997 returns 400 + 10016002.
  7. Failure paths: call with a wrong sign (401 + 10009003); call an unsubscribed endpoint (403 + 10009005).
  8. Parser compatibility: make sure your client treats 422 / 428 / 451 / 503 as failures and reads the bare {code, message} body (these cannot be triggered with test data; they only appear in production for real minors' CPFs).

Troubleshooting

Signature never matches (401, 10009003)?

Check, in order of frequency:

  1. A GET request did not concatenate the body as the empty string "" (an empty object or placeholder text was used instead);
  2. path missing the /openapi prefix, or including the query string;
  3. The date-of-birth segment left out of the CPF signature; both path variables must be signed;
  4. sign sent in uppercase (must be lowercase hex);
  5. The timestamp used in concatenation differs from the header (regenerated between the two);
  6. A formatted CNPJ whose / split the path.

Recompute the fixed values of the signing example in Authentication first; once your local implementation matches, move on to inspecting the live request parameters.

CNPJ returns 404 or fails to route?

The CNPJ parameter accepts 14 digits only. The / inside 40.673.061/0001-34 is treated as a path separator, so the request never reaches the endpoint.

CPF found but the business flow looks wrong?

Check situacao.codigo first: anything other than 0 means the CPF is not in regular standing (deceased, suspended, pending regularisation, ...). The data is valid; the business decision is yours.

Clock skew (401, 10009001)?

Your server clock differs from ours by more than 300 seconds. Use NTP, and never cache or reuse timestamps across requests.