People search
This guide covers the person-centred read: find a holder or representative and see how much of the register is theirs. It complements field-scoped search, where people are a filter over marks; here they are the subject of the query.
The complete, always-current per-field schema lives in the interactive OpenAPI reference at
/docs(Scalar). This guide explains the contract and links to that reference — it does not restate the schema. When a field is not documented here,/docsis authoritative.
Throughout, the base URL is written as $TARNO_BASE_URL and the key as $TARNO_API_KEY, and every
call carries the X-API-Key header.
GET /v1/personas · scope brands:read · MCP equivalent: search_personas
Until now people could only be used as a filter over marks (?titular=, ?rut=) or as an
aggregate (/v1/insights/by-holder). This endpoint inverts the question: it starts from the
person and tells you how much of the register is theirs.
curl -sS "$TARNO_BASE_URL/v1/personas?q=carey" -H "X-API-Key: $TARNO_API_KEY"
[
{
"id": "1261017",
"nombre": "ESTUDIO CAREY LIMITADA",
"identificador": "76111111-6",
"pais": "CL",
"region": "13",
"comuna": "13101",
"marcasTitular": 12,
"marcasRepresentante": 3480,
"marcasTotal": 3492,
"marcasHistoricas": 0,
"tipo": "juridica",
"tipoOrigen": "rut",
"observacion": null,
"nombrePublicado": "Estudio Carey Limitada",
"revision": false
},
{
"id": "884213",
"nombre": "JUAN CAREY SOTO",
"identificador": null,
"pais": "CL",
"region": null,
"comuna": null,
"marcasTitular": 1,
"marcasRepresentante": 0,
"marcasTotal": 1,
"marcasHistoricas": 0,
"tipo": "desconocido",
"observacion": null,
"nombrePublicado": "Juan Carey Soto",
"revision": false
}
]
How to search
| Parameter | What it does |
|---|---|
q |
Partial, accent-insensitive match over name and surname. Minimum 2 characters — argandona finds Argandoña. |
rut |
Exact match. Accepts any format (17.271.415-3, 17271415-3) and normalises it. |
limit / offset |
Paging. limit defaults to 25, caps at 100. |
envelope |
true adds the { data, dataAsOf } envelope. |
You must supply q or rut; with neither, the response is 400 — so nobody lists the whole table
by accident.
Results are ordered by mark volume, heaviest first. When you search a common surname, the firm with thousands of marks comes before its one-mark namesake.
The counts are CURRENT, and marcasHistoricas tells you what is missing
marcasTitular, marcasRepresentante and marcasTotal count only what the person holds today.
Transfer a mark away and it stops counting.
marcasHistoricas counts what they used to hold and no longer do. It exists so that subtraction
is never silent: without it you would see a smaller number and nothing to say history exists. It is
0 for almost everyone; a non-zero value is the cue to ask for the history:
# the marks this person USED to hold
curl -sS "$TARNO_BASE_URL/v1/brands?titular=Carey&vigencia=historica" -H "X-API-Key: $TARNO_API_KEY"
What KIND of party each person is
Since 2026-09-08 every person carries five more fields, the same five in all three places where
the contract publishes a person: the brand detail (GET /v1/brands/:nroSolicitud), the
registrability report and this search. They are additive: no earlier
field was removed, renamed or re-typed, and no scope changed — they are read under the same
brands:read — so an integration written before that date keeps parsing every response unchanged.
| Field | Type | What it says |
|---|---|---|
tipo |
natural | juridica | desconocido |
What kind of party this is. |
tipoOrigen |
rut | sufijo | manual |
Which signal produced tipo. Omitted — never null — when there was none. |
observacion |
string | null | The jurisdiction clause INAPI writes glued to the name. |
nombrePublicado |
string | null | The spelling exactly as INAPI published it, against the canonical nombre. |
revision |
boolean | A known ambiguity is attached to this row. |
All five are declared optional in the schema — that is what makes the change additive — and
tipoOrigen additionally disappears from the object when there is no signal.
desconocido is a value, not a hole. Measured in production on 2026-09-07 over 396,287 people:
127,263 carry a RUT (79,385 natural, 47,878 jurídica), another 167,568 carry a company suffix in the
name, and roughly a third of the corpus carries neither signal. That third is desconocido, and
saying so is more honest than deducing. Reading it as "probably a natural person" would sweep some
130,000 unclassified parties into a tipo = 'natural' filter. When you need certainty, require
tipoOrigen: 'rut' — the cut the state itself applies when it issues the number — instead of
accepting a deduction from a word at the end of a name.
tipoOrigen is omitted; it never arrives as null. With no signal the key disappears from
the object, which is exactly when tipo reads desconocido (the second element of the example above
has no tipoOrigen). An if (p.tipoOrigen === null) never fires: the correct check is
p.tipoOrigen === undefined or !("tipoOrigen" in p).
nombre is the field to SEARCH with; nombrePublicado is the field to SHOW, or to CHECK against a
source document. nombre is the canonical form — UPPERCASE with accents — and it is what the
engine indexes; nombrePublicado keeps the source's own spelling so any value can be traced back to
INAPI. Matching on nombrePublicado re-introduces exactly the case-and-accent noise the canonical
form exists to remove.
observacion is INAPI's prose, not a note of ours. It is the jurisdiction clause lifted out of
the name: «X, SOCIEDAD ORGANIZADA BAJO LAS LEYES DEL ESTADO DE DELAWARE» is stored as
nombre: 'X' plus this observation. It is published verbatim, misspellings included: 1,472
people carry it in 681 distinct spellings of the same clause (SOCIEDD ORGANIZADA…, SOC. ORG.
BAJO LAS LEYES…). Do not parse it as a controlled vocabulary; it is prose.
revision warns, it does not disqualify. It means the corpus itself flagged the row for a human
to look at — a RUT that contradicts the company suffix in the name, a clause that ate the whole name
— not that the data is bad. Whoever shows the party to a lawyer may want to say so; whoever counts
marks can ignore it. The reason is not published: it is operator vocabulary that grows with every
pass, so the contract answers only the question a consumer actually has — "can I trust this row
blindly?".
The people corpus was rewritten on 2026-09-08
Names are canonical from that date: 396,444 people were rewritten to the canonical form and some 240,000 changed spelling. If you compare values cached before then against what the API returns today, you will see case and accent differences that are not data changes. Also:
- Jurisdiction clauses are no longer inside
nombre: they live inobservacion, and the name they were glued to is now just the name. - Grouping or de-duplicating people on your side by
nombreover-counted: the same party that readEstudio Carey Limitadaon one mark andESTUDIO CAREY LIMITADAon another now reads the same on both. - 179 duplicate groups were fused. No mark changed hands, so a party's total can only go up by absorbing its twin, never down.
Two things worth understanding
It returns counts, not marks. A large firm holds thousands: embedding them would make the
response unbounded and duplicate the search engine /v1/brands already is. To get a person's marks,
use the values returned here:
# every mark this party is on, by RUT (any role)
curl -sS "$TARNO_BASE_URL/v1/brands?rut=76111111-6" -H "X-API-Key: $TARNO_API_KEY"
# only where they are the holder, by name
curl -sS "$TARNO_BASE_URL/v1/brands?titular=Carey" -H "X-API-Key: $TARNO_API_KEY"
# what they used to hold and no longer do (`vigencia=todas` spans both)
curl -sS "$TARNO_BASE_URL/v1/brands?titular=Carey&vigencia=historica" -H "X-API-Key: $TARNO_API_KEY"
Those calls return current holding by default: a party that transferred a mark away drops out of
it. vigencia changes the question — see field-scoped search.
identificador is often null, and that is not a data defect. The RUT is a Chilean
identifier, so:
- a foreign holder will never have one — it does not exist;
- for filings before 2023 INAPI did not publish it (17-26% coverage across 2017-2022, against ~75% from 2024 onwards).
If your integration joins on RUT, treat null as "not available", never as "no match".
From an AI agent
search_personas(q: "carey", limit: 5)
search_personas(rut: "17.271.415-3")
The MCP tool always returns the { data, dataAsOf } envelope and is byte-identical to
GET /v1/personas?envelope=true.