Identity API
Look up official Brazilian registry data by taxpayer identification number:
| Capability | Endpoint | What it returns |
|---|---|---|
| CNPJ lookup | GET /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 lookup | GET /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 & Signing. Responses are bare objects (no
platform envelope); business errors are a bare {code, message} object — see
General Conventions.
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.
CNPJ lookup
Request
GET /openapi/v3/consultas/cnpj/{cnpj}| Parameter | In | Description |
|---|---|---|
cnpj | path | 14 digits, digits only. Formatted CNPJs are rejected — the / in 40.673.061/0001-34 would be parsed as a path separator |
Complete example:
GET /openapi/v3/consultas/cnpj/40673061000134 HTTP/1.1
Host: api.v2.tffiscal.com
token: sk_live_9f8e7d6c5b4a
timestamp: 1786843552
sign: aa201527a7d8288c8d79dcdb6a776566
Language: enEquivalent curl:
APP_SECRET="sk_live_9f8e7d6c5b4a"
CNPJ="40673061000134"
P="/openapi/v3/consultas/cnpj/${CNPJ}"
TS=$(date +%s)
SIGN=$(printf '%s' "${APP_SECRET}${P}${TS}" | md5sum | cut -d' ' -f1)
curl -X GET "https://api.v2.tffiscal.com${P}" \
-H "token: ${APP_SECRET}" -H "timestamp: ${TS}" -H "sign: ${SIGN}" -H "Language: en"Success response (HTTP 200)
The response is a bare object. The tables below list every possible field; when the source holds no data for a field it comes back empty, and such fields are left out of the example.
{
"ni": "40673061000134",
"tipoEstabelecimento": "1",
"nomeEmpresarial": "TF SOFTWARE LTDA",
"nomeFantasia": "TF SOFTWARE",
"situacaoCadastral": {
"codigo": "2",
"data": "2021-02-02",
"motivo": "SEM MOTIVO"
},
"naturezaJuridica": {
"codigo": "2062",
"descricao": "Sociedade Empresária Limitada"
},
"dataAbertura": "2021-02-02",
"cnaePrincipal": {
"codigo": "6201501",
"descricao": "Desenvolvimento de programas de computador sob encomenda"
},
"endereco": {
"tipoLogradouro": "PRACA",
"logradouro": "JOAO DURAN ALONSO",
"numero": "34",
"complemento": "CONJ 32",
"cep": "04571070",
"bairro": "CIDADE MONCOES",
"municipio": { "codigo": "7107", "descricao": "SAO PAULO" },
"uf": "SP",
"pais": { "codigo": "1058", "descricao": "BRASIL" }
},
"municipioJurisdicao": { "codigo": "7107", "descricao": "SAO PAULO" },
"telefones": [ { "ddd": "11", "numero": "80783080" } ],
"correioEletronico": "contato@example.com.br",
"capitalSocial": 100000,
"porte": "03"
}Field reference (top level):
| Field | Type | Description |
|---|---|---|
ni | string | CNPJ, 14 digits |
tipoEstabelecimento | string | Establishment type: 1 headquarters, 2 branch |
nomeEmpresarial | string | Registered legal name |
nomeFantasia | string | Trade name (doing-business-as) |
situacaoCadastral | object | Registration status — see below |
naturezaJuridica | object | Legal nature (code + description) |
dataAbertura | string | Incorporation date, yyyy-MM-dd |
cnaePrincipal | object | Primary economic activity (code + description) |
endereco | object | Registered address — see below |
municipioJurisdicao | object | Tax jurisdiction municipality (code + description) |
telefones[] | array | Phone numbers — see below |
correioEletronico | string | E-mail address |
capitalSocial | number | Share capital |
porte | string | Company size code |
situacaoEspecial | string | Special status (e.g. judicial recovery); usually absent |
dataSituacaoEspecial | string | Effective date of the special status |
situacaoCadastral (registration status):
| Field | Type | Description |
|---|---|---|
codigo | string | Status code; 2 means active (Ativa) |
data | string | Status effective date, yyyy-MM-dd |
motivo | string | Reason; SEM MOTIVO when active |
endereco (address):
| Field | Type | Description |
|---|---|---|
tipoLogradouro | string | Street type (RUA, AVENIDA, PRACA, …) |
logradouro | string | Street name (without the type prefix) |
numero | string | Street number |
complemento | string | Additional info (suite, floor, …) |
cep | string | Postal code, 8 digits, no hyphen |
bairro | string | District |
municipio | object | Municipality (code + description) |
uf | string | State code, 2 letters (e.g. SP) |
pais | object | Country (code + description); Brazil is 1058 |
To render a full street line, concatenate
tipoLogradouro + logradouroyourself — the source returns them separately.
telefones[] element:
| Field | Type | Description |
|---|---|---|
ddd | string | Area code, 2 digits |
numero | string | Subscriber number (without area code) |
Code-value objects (naturezaJuridica / cnaePrincipal / municipioJurisdicao /
municipio / pais):
| Field | Type | Description |
|---|---|---|
codigo | string | Official code |
descricao | string | Description, verbatim from the source (Portuguese) |
CPF lookup
Request
GET /openapi/v3/consultas/cpf/{cpf}/{nascimento}| Parameter | In | Description |
|---|---|---|
cpf | path | 11 digits, digits only |
nascimento | path | Date of birth, DDMMYYYY, 8 digits (e.g. 09011997 = 9 January 1997) |
Complete example (the signature is reproducible with the values shown — see Signing examples):
GET /openapi/v3/consultas/cpf/40710536828/09011997 HTTP/1.1
Host: api.v2.tffiscal.com
token: sk_live_9f8e7d6c5b4a
timestamp: 1786843552
sign: 84a877ec34052db54cf41bb736f7c585
Language: enEquivalent curl:
APP_SECRET="sk_live_9f8e7d6c5b4a"
CPF="40710536828"; NASC="09011997"
P="/openapi/v3/consultas/cpf/${CPF}/${NASC}"
TS=$(date +%s)
SIGN=$(printf '%s' "${APP_SECRET}${P}${TS}" | md5sum | cut -d' ' -f1)
curl -X GET "https://api.v2.tffiscal.com${P}" \
-H "token: ${APP_SECRET}" -H "timestamp: ${TS}" -H "sign: ${SIGN}" -H "Language: en"Success response (HTTP 200)
{
"ni": "40710536828",
"nome": "DANILO HIDEO CORREA",
"situacao": {
"codigo": "0",
"descricao": "REGULAR"
},
"nascimento": "09011997"
}| Field | Type | Description |
|---|---|---|
ni | string | CPF, 11 digits |
nome | string | Individual’s full name |
situacao | object | Registration status — see below |
nascimento | string | Date of birth, echoed back in the original DDMMYYYY format |
situacao (registration status):
| Field | Type | Description |
|---|---|---|
codigo | string | Status code — see table below |
descricao | string | Status description, verbatim from the source (Portuguese) |
Common situacao.codigo values:
| Code | Description | Meaning |
|---|---|---|
0 | REGULAR | Regular |
2 | SUSPENSA | Suspended |
3 | TITULAR FALECIDO | Holder deceased |
4 | PENDENTE DE REGULARIZACAO | Pending regularisation |
5 | CANCELADA POR MULTIPLICIDADE | Cancelled (duplicate registration) |
8 | NULA | Void |
9 | CANCELADA DE OFICIO | Cancelled ex officio |
Business note: when
codigois not0, it is up to the caller to decide whether the business flow may continue. Issuing an invoice to a deceased holder (3), for instance, usually warrants a block — this endpoint reports the status faithfully and does not make that judgment for you.
Error reference
Business and request-level errors (HTTP 400) are a bare object:
{ "code": 10016003, "message": "CPF not found" }| code | HTTP | Meaning | Action |
|---|---|---|---|
| 10016000 | 400 | Invalid CPF format (11 digits required) | Check for stray formatting characters or wrong length |
| 10016001 | 400 | Invalid CPF check digits | Validate locally with the mod-11 algorithm first to avoid wasted calls |
| 10016002 | 400 | Invalid date of birth (valid DDMMYYYY required) | Note the day-month-year order, and that the date must actually exist |
| 10016003 | 400 | CPF not found | The CPF does not exist, or the CPF and date of birth do not match (deliberately indistinguishable) |
| 10016010 | 400 | Invalid CNPJ format (14 digits required) | Check for stray formatting characters |
| 10016011 | 400 | Invalid CNPJ check digits | Validate locally with the mod-11 algorithm first |
| 10016012 | 400 | CNPJ not found | No such CNPJ in the official registry |
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.
Authentication-layer errors (401 / 403 / 429) use the platform envelope — see Authentication & Signing.
| HTTP | Scenario | Body shape |
|---|---|---|
| 200 | Lookup succeeded | Bare data |
| 400 | Invalid parameter / record not found | Bare {code, message} |
| 401 | Authentication failed | Platform envelope |
| 403 | Application disabled / not effective / not subscribed | Platform envelope |
| 429 | Rate limit exceeded | Platform envelope |
| 5xx | Platform-side fault | 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 protected subjects (such as minors); those requests surface as “not found” (10016003).
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.
Integration checklist
- Obtain the
app_secretand confirm both endpoints are subscribed. - Call with a real CNPJ → HTTP 200,
niechoes the input,situacaoCadastral.codigois2. - Call with a real CPF + date of birth → HTTP 200,
nascimentoechoes the input. - Negative case: correct CPF with a wrong date of birth → 400 + 10016003 (same code as not-found).
- Negative case: CNPJ / CPF with bad check digits → 400 + 10016011 / 10016001 (rejected locally, not billed).
- Negative case: date of birth as
1997-01-09or31021997→ 400 + 10016002. - Failure paths: call with a wrong
sign→ 401 + 10009003; call an unsubscribed endpoint → 403 + 10009005.
Troubleshooting
Signature never matches (401, code 10009003)? On these endpoints the usual causes are
a GET that did not concatenate the body as the empty string, the date-of-birth segment
left out of the CPF signature (both path variables must be signed), or a formatted
CNPJ whose / split the path. Recompute the fixed values in
Signing examples first.
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.