.jpg)
Someone hands you a spreadsheet with 400 company names in it. A few are legal names, most are how a salesperson types them at 4pm on a Friday, and at least one says "Alphabet (Google)". You need prices, financials, and filings attached to every row by Monday.
This is the least glamorous problem in market data and it eats an enormous amount of engineering time. Nobody puts "we built a symbol mapping layer" on a roadmap, but almost every team that works with financial data ends up building one anyway, usually twice, because the first version matched on company name and started returning Apple Hospitality REIT when someone typed Apple.
A stock symbol lookup API is the shortcut. It takes whatever identifier you happen to have and gives you back the full set of identifiers for that company or security, along with enough metadata to tell whether you got the right one.
The core function is translation. You send in a ticker, a CIK, an LEI, or a chunk of a company name, and you get back a record that carries all the other identifiers plus the reference data attached to them.
The part that trips people up is that there are really two objects here, and they are not the same thing.
A company is the legal entity. Alphabet Inc. is one company. It has one CIK, one LEI, one legal name, one SIC code, one headquarters.
A security is something that trades. Alphabet has two of them in common use, GOOGL for the Class A shares and GOOG for the Class C, and if you widen the lens to include every exchange where Alphabet shares change hands, the count goes up considerably. One company, many securities.
Get those layers confused and you end up double counting a position, or pulling financials for a share class that has none of its own, or writing a screener that returns the same business three times. Intrinio splits them deliberately: the Lookup Company endpoint takes a ticker, CIK, LEI, or Intrinio company ID and returns entity-level data, while Lookup Security returns the tradeable instrument. All Securities by Company walks you from one to the other.
What comes back from a company lookup is more than a name and a symbol. You get lei, cik, legal_name, sic, sector and industry group, the primary exchange, employee count, CEO, incorporation state and country, and the date of the most recent SEC filing. There are also four fields most people miss on the first read: first_fundamental_date, last_fundamental_date, first_stock_price_date, and last_stock_price_date. Those tell you what data actually exists for the company before you write a loop that requests ten years of history and gets back nothing for a third of your universe.
Name to ticker is the request everyone starts with, and it is also the least reliable one.
Company names are not unique, not stable, and not standardized. "Apple" could be Apple Inc. or Apple Hospitality REIT. "Google" is not a registrant at all anymore, it is a subsidiary of Alphabet. Legal suffixes vary by jurisdiction and get dropped inconsistently, so Inc., Incorporated, Corp., Corporation, plc, S.A., N.V., and Holdings all show up or don't depending on who typed the row. Then there are the rebrands, where the ticker changed, the name changed, and the entity behind both stayed exactly the same.
Fuzzy search still has a place. You need it for the initial pass over that spreadsheet, and for any UI where a person types a name into a box. Search Companies handles that side, returning ranked candidates you can score and review.
The important part is what you do after the match. Resolve the name once, store the stable identifier, and stop matching on names forever. Intrinio assigns each company an internal ID that looks like com_gebVJX and each security one like sec_gxVl78. Those never change. If you keep the company name as a display field and the Intrinio ID as your join key, a rebrand becomes a metadata update instead of a broken pipeline.
For the ambiguous rows, it helps to score against something besides the name string. Matching on headquarters state, SIC code, or approximate employee count clears up most of the collisions in a US universe fast.
Every identifier here was built for a particular job. Most mapping bugs come from using one outside that job.
Ticker. Short, readable, and the only identifier anyone says out loud. It is also scoped to an exchange, gets reused after a delisting, and changes whenever a company rebrands or reincorporates. Fine for display. Bad as a primary key.
CIK. The Central Index Key the SEC assigns to registrants. It survives name changes, ticker changes, and mergers, and it is the natural join key for anything filing-related. The limitation is scope: no CIK for companies that do not file with the SEC, which rules out most of the world.
LEI. A 20-character global code for a legal entity, issued under an international standard and required in a lot of regulatory reporting. If your workflow touches counterparty risk, derivatives reporting, or anything cross-border, the LEI is the one your compliance team cares about. Intrinio returns it on the company record and maps it from the CIK.
FIGI. Bloomberg's open identifier, and the backbone of Intrinio's global security master. A FIGI identifies a specific security on a specific exchange. A composite FIGI rolls those up to the primary security within a country. A share class FIGI groups the listings that represent the same share class. This is the layer that lets you tell Deutsche Bank on Frankfurt apart from Deutsche Bank on Stuttgart without guessing from the currency field.
ISIN and CUSIP. Widely used and heavily licensed, which affects what a vendor is allowed to hand back. Intrinio accepts an ISIN as a lookup input but does not return ISINs in the response, and that distinction matters if you were planning to use one as your storage key.
The practical rule: pick one internal key, make it the thing your tables join on, and treat every other identifier as an attribute hanging off it. Intrinio's com_ and sec_ IDs are built for exactly that, though a CIK works fine if your universe is US-only and always will be.
Two things break symbol mapping in production, and both are time-related.
The first is that tickers move. Facebook became Meta and FB became META in June 2022. Block kept trading as SQ for three years after it stopped calling itself Square, then switched to XYZ in January 2025. Symbols also get recycled, so a ticker that pointed at one company in 2015 may point at an entirely different one now. Any backtest that stores a ticker as its key and looks it up today is asking about the wrong company for part of its history, and nothing in the output will tell you.
Intrinio's security records carry previous_tickers and alternate_tickers for this, along with a delisted flag, and there are dedicated endpoints for the history: Security History By Ticker and Security History By Identifier will tell you what a symbol referred to as of a given date. If you are running research over a long window, that lookup belongs in your pipeline and not in a comment explaining why 2019 looks weird.
The second problem is multiple listings. A single company can have several share classes, list on several exchanges, and appear again as an ADR. Requesting a ticker with no exchange context gets you the primary listing, which is usually what you want and occasionally very much not. Composite tickers solve this by pinning the symbol to a venue, so a bare DBK resolves to Deutsche Bank's primary listing while a composite ticker like DBK:GR tells the API exactly which one you mean. The primary_security and primary_listing booleans on each security record let you filter down to one row per company when you are building a screener and want the business, not every place its shares happen to trade.
A few habits separate mapping layers that hold up from the ones that get rewritten.
Resolve at ingest, not at query time. Every row that enters your system should get an internal ID attached immediately, while you still have context about where it came from and someone available to fix the ones that fail.
Keep the mapping in its own table, with the source, the date, the method, and a confidence score. Add a manual override column. You will need it, because some percentage of any real universe cannot be matched programmatically and an analyst has to look at it.
Refresh on a schedule. The security master is not static. Companies list, delist, rename, split their shares, and get acquired continuously, so a mapping table built in March and never touched again will be visibly wrong by autumn.
Expect nulls and design for them. LEIs are missing for plenty of smaller and non-US entities. CIKs do not exist outside SEC registrants. Code that assumes every field is populated will fail on the long tail, which is exactly where the interesting names tend to be.
Track your unmatched rate as a metric. If it jumps, something upstream changed, and you would rather find out from a dashboard than from a client asking why a holding disappeared.
Intrinio's reference layer covers both halves of this problem. On the entity side, the Company Reference and Metadata endpoints give you lookup, search, and full company listings with tickers, CIKs, LEIs, legal names, sector and industry classification, and data availability dates. On the instrument side, the Security Reference Data endpoints cover securities, exchanges, composite tickers, FIGI and composite FIGI, and the symbol history you need to keep long time series honest. Company reference data is sourced from the SEC, and the security master is built on OpenFIGI symbology. There is a longer technical write-up on how we structure it in our post on modern security master architecture.
Reference data comes bundled with fundamentals coverage rather than sold as a separate line item, since it is the thing that makes every other dataset joinable. Access runs over REST, bulk download, and the Intrinio MCP server, so an AI agent resolving a company name hits the same source your nightly batch does. Endpoint details are in the API documentation.
If you want to see how your universe maps before you commit to anything, that is a reasonable first conversation to have.
See plans and pricing or talk to our team about coverage for your list.