Search
Find entities by name, ticker, GICS sector, entity type, SIC or NAICS code, and page through the matches.
GET /v1/search returns entities that match a text query and filters: one row per share class, with its latest ticker, name, entity type, GICS sector and sub-industry, SIC and NAICS codes, and the last date it carried that ticker. Use it to discover tickers and entity_id values you do not know, including delisted companies and companies known by an earlier name.
The response contains no money, share or percentage values. Dates are YYYY-MM-DD strings; SIC and NAICS codes are strings.
Rows are at share-class grain: entity_id names a share class where one exists, and the company where the company has no share class on record. Tickers and entities explains the two.
An API key is optional. The response is the same with or without one. A key sent in X-API-Key or api_key that is not valid returns 401, as does a revoked or unrecognised key sent as Authorization: Bearer.
Parameters
All parameters are optional and combine with AND. With no parameters, the endpoint lists every entity alphabetically.
qstrDefault: noneCase-insensitive substring match on every ticker and every name the entity has carried, current or past. % and _ match those characters. 100 characters or fewer. A match on a company returns each of its share classes.
gics_sectorstrDefault: noneExact, case-sensitive GICS sector name: Communication Services, Consumer Discretionary, Consumer Staples, Energy, Financials, Health Care, Industrials, Information Technology, Materials, Real Estate or Utilities. Any other value returns no rows.
entity_typestrDefault: nonecorporation, etf or closed_end_fund, in lower case. corporation covers every row that is not an ETF or closed-end fund, including preferreds, ADRs, exchange-traded notes and units. Any other value returns no rows.
sicstrDefault: noneExact SIC code, for example 3711. Any value that matches no code returns no rows.
naicsstrDefault: noneExact NAICS code, for example 336110. The whole code must match: 3361 does not match 336110.
countrystrDefault: "US"Only US returns rows. Any other value, including us, returns no rows.
limitintDefault: 50Rows per page, 1 to 500, on every plan.
offsetintDefault: 0Rows to skip before the page starts. 0 or more.
With q, rows are ordered by match strength: an exact ticker match first, then a ticker prefix, then a name prefix, then any other substring. Within each group, rows whose current name matches come before rows that matched only a past name, then listings with a trading day in the last 30 days, then shorter names, then names alphabetically. Without q, rows are ordered by name, then entity_id.
Response
The body is {"data": [...], "meta": {...}}.
Row fields
| field | type | unit | nullable | description |
|---|---|---|---|---|
entity_id | int | — | no | Share-class id, or company id where the company has no share class on record. Pass it as entity_id to the data endpoints. |
ticker | str | — | yes | The most recent ticker this row itself carried. For a delisted entity, its last ticker. |
entity_name | str | — | no | Current recorded name. |
entity_type | str | — | no | corporation, etf or closed_end_fund. |
gics_sector | str | — | yes | GICS sector name of the company. |
gics_sub_industry | str | — | yes | GICS sub-industry name of the company. |
sic | str | — | yes | SIC code of the company. |
naics | str | — | yes | NAICS code of the company. |
country | str | — | no | Always US. |
ticker_valid_to | str | date | yes | Last day the row carried ticker. Null while it still carries it. |
Meta
Response metadata explains knowledge_time and freshness.
| field | type | unit | nullable | description |
|---|---|---|---|---|
count | int | rows | no | Rows in this page. |
limit | int | rows | no | Page size used. |
offset | int | rows | no | Offset used. |
total | int | rows | no | Rows that match across all pages. |
has_more | bool | — | no | true while offset + count is less than total. |
entity_id_grain | str | — | no | Reminder that entity_id is a share-class id where a share class matched and a company id where only the company exists. |
knowledge_time | str | UTC timestamp | yes | Newest knowledge time across the datasets used. |
freshness | array | — | no | One {dataset, through, promoted_at} entry each for identifiers, entities and classifications. |
Pagination
Search pages by offset, not by cursor. Pass limit (up to 500) and offset; meta.total is the number of matching rows, and meta.has_more is true while offset + count is less than total. Pagination compares the two styles.
Page two of the general motors query from the request examples below:
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=general%20motors&limit=3&offset=3"{
"data": [
{
"entity_id": 10018237,
"ticker": "GMH",
"entity_name": "GENERAL MOTORS CORP",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Internet & Direct Marketing Retail",
"sic": "4841",
"naics": "515210",
"country": "US",
"ticker_valid_to": "2003-12-22"
},
{
"entity_id": 10033728,
"ticker": "XGM",
"entity_name": "General Motors Company — SR NT 7/15/41",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": "2009-06-02"
},
{
"entity_id": 10033729,
"ticker": "HGM",
"entity_name": "General Motors Company — SR NT7.375% 51",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": "2009-06-02"
}
],
"meta": {
"count": 3,
"limit": 3,
"offset": 3,
"total": 8,
"has_more": true,
...
}
}An offset past the last row returns an empty page with the same total:
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=general%20motors&limit=3&offset=999"{
"data": [],
"meta": {
"count": 0,
"limit": 3,
"offset": 999,
"total": 8,
"has_more": false,
...
}
}Errors
A query that matches nothing is not an error: it returns 200 with an empty data array (see Edge cases).
| status | error code | when it happens | how to fix |
|---|---|---|---|
400 | bad_request | limit is not a whole number of 1 or more. | Pass a limit from 1 to 500. |
400 | bad_request | limit is more than 500. | Pass 500 or less and page with offset. |
400 | bad_request | offset is negative or not a whole number. | Pass 0 or a positive whole number. |
400 | bad_request | q is longer than 100 characters. | Shorten q. |
401 | unauthorized | A key sent in X-API-Key or api_key is not valid, or a key sent as Authorization: Bearer is revoked or unrecognised. | Send a valid key, or send the request without one. |
429 | see Rate limits | A request allowance is used up: the plan's, or without a key, the allowance for your IP address. With a key, the plan's row allowance also applies. | Wait for the reset. A request-limit body gives the wait in retry_after_seconds; daily allowances reset at 00:00 UTC and hourly ones at the top of the UTC hour. |
limit=0:
{"error": "bad_request", "code": "bad_request", "status": 400, "detail": "limit must be a positive integer"}limit=501:
{"error": "bad_request", "code": "bad_request", "status": 400, "detail": "limit max is 500"}offset=-1:
{"error": "bad_request", "code": "bad_request", "status": 400, "detail": "offset must be a non-negative integer"}q of 101 characters:
{"error": "bad_request", "code": "bad_request", "status": 400, "detail": "q must be 100 characters or fewer"}Plan differences
Search returns the same rows on every plan and without a key, and limit goes up to 500 on every plan.
- Free: full rows,
limitup to 500. - Pro: identical to Free.
- Max: identical to Free,
limitup to 500. - Redistribution: identical to Free.
- No key: identical rows. Requests are limited per IP address to 40 per UTC clock hour and 100 per UTC day; the response headers report
X-RateLimit-Limit-Day: 100andX-RateLimit-Limit-Hour: 40.
Each search counts as one request against your plan's daily allowance, whatever limit is. The general motors query with a Free key returns the same rows as the Pro response in the request examples; the Free response adds the hourly headers:
x-ratelimit-limit-day: 100
x-ratelimit-limit-hour: 40The same query without a key:
curl -s "https://api.xfinlink.com/v1/search?q=general%20motors&limit=3"{
"data": [
{
"entity_id": 10001879,
"ticker": "GM",
"entity_name": "GENERAL MOTORS CO",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": null
},
...
],
"meta": {
"count": 3,
"limit": 3,
"offset": 0,
"total": 8,
...
}
}Edge cases
Past names
q matches names an entity no longer uses. Meta Platforms is found by its former name:
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=facebook&limit=3"{
"data": [
{
"entity_id": 10002684,
"ticker": "META",
"entity_name": "META PLATFORMS INC",
"entity_type": "corporation",
"gics_sector": "Communication Services",
"gics_sub_industry": "Interactive Media & Services",
"sic": "7370",
"naics": "519290",
"country": "US",
"ticker_valid_to": null
}
],
"meta": {
"count": 1,
"limit": 3,
"offset": 0,
"total": 1,
...
}
}Recycled and delisted tickers
A query can return several entities that carried the same ticker. In the request examples, GM appears twice: General Motors Company (ticker_valid_to null) and General Motors Corporation (ticker_valid_to 2009-06-01). Delisted entities stay searchable under their last ticker.
Instruments beyond common stock
entity_type=corporation also returns a company's preferreds and exchange-traded notes, each as its own row:
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=JPM&entity_type=corporation&limit=6"{
"data": [
{
"entity_id": 10015682,
"ticker": "JPM",
"entity_name": "JPMORGAN CHASE & CO",
"entity_type": "corporation",
"gics_sector": "Financials",
"gics_sub_industry": "Diversified Banks",
"sic": "6020",
"naics": "522110",
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10035372,
"ticker": "AMJB",
"entity_name": "JPMORGAN CHASE & CO — ETN",
"entity_type": "corporation",
"gics_sector": "Financials",
"gics_sub_industry": "Diversified Banks",
"sic": "6020",
"naics": "522110",
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10035478,
"ticker": "VYLD",
"entity_name": "JPMORGAN CHASE & CO — ETN",
"entity_type": "corporation",
"gics_sector": "Financials",
"gics_sub_industry": "Diversified Banks",
"sic": "6020",
"naics": "522110",
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10033608,
"ticker": "JPM-PC",
"entity_name": "JPMORGAN CHASE & CO — PFD EE",
"entity_type": "corporation",
"gics_sector": "Financials",
"gics_sub_industry": "Diversified Banks",
"sic": "6020",
"naics": "522110",
"country": "US",
"ticker_valid_to": null
},
...
],
"meta": {
"count": 6,
"limit": 6,
"offset": 0,
"total": 31,
...
}
}Use entity_type=etf or entity_type=closed_end_fund for funds. Filters combine, so q=vanguard&entity_type=etf returns Vanguard's exchange-traded funds and no companies named Vanguard:
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=vanguard&entity_type=etf&limit=2"{
"data": [
{
"entity_id": 10001980,
"ticker": "VXUS",
"entity_name": "VANGUARD STAR FUNDS",
"entity_type": "etf",
"gics_sector": null,
"gics_sub_industry": null,
"sic": "6722",
"naics": null,
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10006405,
"ticker": "VSGX",
"entity_name": "VANGUARD WORLD FUND",
"entity_type": "etf",
"gics_sector": null,
"gics_sub_industry": null,
"sic": "6722",
"naics": "525910",
"country": "US",
"ticker_valid_to": null
}
],
"meta": {
"count": 2,
"limit": 2,
"offset": 0,
"total": 104,
...
}
}Rows without classifications
Some rows have no GICS, SIC or NAICS values; those fields are null, as on the GME row in the request examples. Such rows never match a gics_sector, sic or naics filter.
Companies with no share class on record
Without q, the listing includes companies that have no share class on record. Their entity_id is the company id:
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?limit=3"{
"data": [
...,
{
"entity_id": 57289,
"ticker": "REPCF",
"entity_name": "0913693 B.C. LTD",
"entity_type": "corporation",
"gics_sector": "Health Care",
"gics_sub_industry": "Life Sciences Tools & Services",
"sic": "2836",
"naics": "325414",
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10025317,
"ticker": "ATTY",
"entity_name": "1 800 ATTORNEY INC",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": null,
"sic": "2741",
"naics": "511140",
"country": "US",
"ticker_valid_to": "2003-02-12"
}
],
"meta": {
"count": 3,
"limit": 3,
"offset": 0,
"total": 58338,
...
}
}Exact-match filters
gics_sector, entity_type, sic, naics and country match exactly. entity_type=ETF, gics_sector=energy and country=us all return no rows, and so does a code that does not exist, such as sic=abc:
{
"data": [],
"meta": {
"count": 0,
"limit": 3,
"offset": 0,
"total": 0,
...
}
}naics compares the whole code, so a prefix such as 3361 does not match 336110. Filters combine with q: companies whose name contains motor and whose NAICS code is 336110:
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=motor&naics=336110&limit=2"{
"data": [
{
"entity_id": 10012940,
"ticker": "F",
"entity_name": "FORD MOTOR CO DEL",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10001879,
"ticker": "GM",
"entity_name": "GENERAL MOTORS CO",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": null
}
],
"meta": {
"count": 2,
"limit": 2,
"offset": 0,
"total": 16,
...
}
}No matches
curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=zzzzqqqx"{
"data": [],
"meta": {
"count": 0,
"limit": 50,
"offset": 0,
"total": 0,
"has_more": false,
"entity_id_grain": "security id where a share class matched; issuer id where only the issuer exists",
"knowledge_time": "2026-09-18T01:59:25Z",
"freshness": [
{
"dataset": "identifiers",
"through": "2026-07-30",
"promoted_at": "2026-09-18T05:17:40Z"
},
{
"dataset": "entities",
"through": "2026-09-13",
"promoted_at": "2026-09-18T05:14:35Z"
},
{
"dataset": "classifications",
"through": "2026-09-18",
"promoted_at": "2026-09-18T05:22:46Z"
}
]
}
}Request examples
Search for general motors, three rows per page. The Python client returns a pandas.DataFrame of the rows and does not return meta.
import xfinlink as xfl
xfl.set_api_key("YOUR_API_KEY")
cols = ["entity_id", "ticker", "entity_name", "gics_sector", "ticker_valid_to"]
page1 = xfl.search(q="general motors", limit=3)
page2 = xfl.search(q="general motors", limit=3, offset=3)
print(page1[cols].to_string(index=False))
print(page2[cols].to_string(index=False))curl -s -H "X-API-Key: YOUR_API_KEY" \
"https://api.xfinlink.com/v1/search?q=general%20motors&limit=3"Search xfinlink for companies named General Motors and show me their tickers. entity_id ticker entity_name gics_sector ticker_valid_to
10001879 GM GENERAL MOTORS CO Consumer Discretionary NaN
10001629 GM GENERAL MOTORS CORP Consumer Discretionary 2009-06-01
10018045 GME GENERAL MOTORS CORP NaN 1996-06-07
entity_id ticker entity_name gics_sector ticker_valid_to
10018237 GMH GENERAL MOTORS CORP Consumer Discretionary 2003-12-22
10033728 XGM General Motors Company — SR NT 7/15/41 Consumer Discretionary 2009-06-02
10033729 HGM General Motors Company — SR NT7.375% 51 Consumer Discretionary 2009-06-02{
"data": [
{
"entity_id": 10001879,
"ticker": "GM",
"entity_name": "GENERAL MOTORS CO",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10001629,
"ticker": "GM",
"entity_name": "GENERAL MOTORS CORP",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": "2009-06-01"
},
{
"entity_id": 10018045,
"ticker": "GME",
"entity_name": "GENERAL MOTORS CORP",
"entity_type": "corporation",
"gics_sector": null,
"gics_sub_industry": null,
"sic": null,
"naics": null,
"country": "US",
"ticker_valid_to": "1996-06-07"
}
],
"meta": {
"count": 3,
"limit": 3,
"offset": 0,
"total": 8,
"has_more": true,
"entity_id_grain": "security id where a share class matched; issuer id where only the issuer exists",
"knowledge_time": "2026-09-18T01:59:25Z",
"freshness": [
{
"dataset": "identifiers",
"through": "2026-07-30",
"promoted_at": "2026-09-18T05:17:40Z"
},
{
"dataset": "entities",
"through": "2026-09-13",
"promoted_at": "2026-09-18T05:14:35Z"
},
{
"dataset": "classifications",
"through": "2026-09-18",
"promoted_at": "2026-09-18T05:22:46Z"
}
]
}
}{"tool": "search", "arguments": {"q": "general motors", "limit": 3}}
{
"data": [
{
"entity_id": 10001879,
"ticker": "GM",
"entity_name": "GENERAL MOTORS CO",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": null
},
{
"entity_id": 10001629,
"ticker": "GM",
"entity_name": "GENERAL MOTORS CORP",
"entity_type": "corporation",
"gics_sector": "Consumer Discretionary",
"gics_sub_industry": "Automobile Manufacturers",
"sic": "3711",
"naics": "336110",
"country": "US",
"ticker_valid_to": "2009-06-01"
},
{
"entity_id": 10018045,
"ticker": "GME",
"entity_name": "GENERAL MOTORS CORP",
"entity_type": "corporation",
"gics_sector": null,
"gics_sub_industry": null,
"sic": null,
"naics": null,
"country": "US",
"ticker_valid_to": "1996-06-07"
}
],
"meta": {
"count": 3,
"limit": 3,
"offset": 0,
"total": 8,
"has_more": true,
"entity_id_grain": "security id where a share class matched; issuer id where only the issuer exists",
"knowledge_time": "2026-09-18T01:59:25Z",
"freshness": [
{
"dataset": "identifiers",
"through": "2026-07-30",
"promoted_at": "2026-09-18T05:17:40Z"
},
{
"dataset": "entities",
"through": "2026-09-13",
"promoted_at": "2026-09-18T05:14:35Z"
},
{
"dataset": "classifications",
"through": "2026-09-18",
"promoted_at": "2026-09-18T05:22:46Z"
}
]
}
}Was this page helpful?
Thank you for helping improve xfinlink documentation.
- Need help? Get in touch.
- Building with an LLM? Read llms.txt.
- Using Claude or ChatGPT? Connect the MCP server.