What does AAPL271217C00420000 tell you before you fetch anything?
Option contract names look like line noise. They are not. The string is a composite key that encodes all four coordinates of the contract, and once you can read it you can construct a contract name without asking the API what exists.
Decoding it, left to right
Take the example that appears in the specification: AAPL271217C00420000.
AAPL— the underlying symbol, variable length.271217— the expiration as YYMMDD: 17 December 2027.C— the right.Cfor call,Pfor put.00420000— the strike, in thousandths of a currency unit, zero-padded to eight digits: 420000 thousandths = a strike of 420.
Run the second example through the same reader: AAPL270115P00450000 is a put on AAPL expiring 15 January 2027 struck at 450 (00450000 ÷ 1000). Nothing about the format is EODHD's invention — it is the OCC convention used across the US listed options market, which is why filter[contract] can be an exact-match lookup rather than a search.
The key of a price observation is longer still
A contract name identifies the instrument. It does not identify a price. Look at the id on a row from /mp/unicornbay/options/eod:
AAPL270115P00450000-2025-08-12
Contract, then observation date. That is the real primary key of an options time series, and it is the reason a single underlying's full history is enormous: 14,000 contracts times every day each of them existed.
Checking the fields against the name
A composite key gives you a free integrity test. The row carries exp_date and dte (days to expiration) as separate fields, so you can confirm they agree with the name.
From the 2025-08-12 snapshot, the put expiring 2027-01-15 reports dte: 521. Count it: 2025-08-12 to 2026-08-12 is 365 days, and 2026-08-12 to 2027-01-15 is 19 + 30 + 31 + 30 + 31 + 15 = 156 days. Total 521. Exact.
The call expiring 2027-12-17 reports dte: 857. From 2025-08-12 to 2027-08-12 is 730 days, plus 19 + 30 + 31 + 30 + 17 = 127 to reach 17 December. Total 857. Also exact.
Notice what that confirms: dte is measured from the snapshot date the row belongs to — not from today, and not from tradetime. The same row's tradetime is 2025-06-08, and counting from there would give 586, not 521. If you store these rows and read them back in six months, dte will still say 521 while the real gap has shrunk. It is a fact about the observation, not about the present moment — a distinction that quietly ruins any screen written on stale data.
The row also carries expiration_type, a nullable string that reads monthly in the example. Weekly and quarterly expirations exist alongside monthlies on the big names, and they behave differently in volume and open interest, so it is worth carrying that column rather than assuming a uniform grid.
Which symbols even have options
There is no "optionable" flag on the ordinary exchange symbol list. The answer lives in its own endpoint: /mp/unicornbay/options/underlying-symbols, which returns a compact array of bare strings — ["A", "AA", "AAAU", ...] — with the count in meta.total. The specification's own example reports 5,972 underlyings; a live call returned 6,932 on 2026-07-28 and 6,960 on 2026-09-15, which is the difference between an example and a response and the reason to read the count rather than quote it. meta.fields: ["underlying_symbol"] and meta.compact: true in both.
Two honest limits. The coverage is US listed names only, so a European or Asian symbol will not appear regardless of whether options trade on it somewhere. And the endpoint is paginated like the others (page[offset] max 10000, page[limit] max 1000), so a full universe pull is several requests, not one.
Try it now
- Decode these three live Apple contract names by hand, taken from the contracts endpoint on 28 September 2026:
AAPL290119C00670000,AAPL261016P00312500andAAPL261009C00125000. Then check your decode against the fields the same rows carried:
| Row | exp_date |
type |
strike |
expiration_type |
|---|---|---|---|---|
| 1 | 2029-01-19 | call | 670 | monthly |
| 2 | 2026-10-16 | put | 312.5 | monthly |
| 3 | 2026-10-09 | call | 125 | weekly |
If your decode and the fields ever disagree, trust the fields and re-read the format. Which of the three could the name alone not tell you was a weekly?
2. Build a contract name yourself for an Apple strike and expiry you choose, then open the chain in the Terminal and see whether that expiry and strike exist. The API gives the same answer without ceremony: on 28 September 2026, filter[contract]=AAPL261016C00999000 returned a 200 with an empty data array. An empty result is a real answer: that contract does not exist.
Open AAPL.US — options in the EODHD Terminal
- The underlyings list held 6,976 symbols on 28 September 2026. Here is the options view for a fund; change the symbol there to one you care about, and if no chain appears, it is not in that list. Check before you write anything that assumes an option chain exists.