Lavender API¶
The Lavender native API is the primary way to access option Greeks from the gateway. It provides the richest output — extended Greeks through third order, quality metadata, per-expiry chain data, and term structure support — in a clean, flat response format.
If you're starting fresh (not migrating from an existing vendor), start here. If you're migrating, the vendor compatibility layers let you switch with a one-line host change, and you can adopt the Lavender API at your own pace.
Try It in Your Browser¶
Once the gateway is running, paste this into any browser:
A full Greeks chain for SPY, rendered as an HTML table. Change the symbol and refresh. No API key, no code, no setup.
Sample Response¶
GET /l1/greeks?root=SPY&right=call&min_strike=570&max_strike=570&min_exp=2026-12-18&max_exp=2026-12-18&format=json
[
{
"underlying": "SPY",
"root": "SPY",
"expiry": "2026-12-18",
"strike": 570,
"right": "call",
"osym": "SPY 261218C00570000",
"greeks": "core",
"und_price": 632.16,
"delta": 0.7335,
"gamma": 0.0022,
"vega": 1.7270,
"theta": -0.1147,
"decay": -0.1495,
"rho": 2.6532,
"lav_theo": 95.94,
"lav_vol": 0.2659
}
]
The core field group (default) includes delta, gamma, vega, theta, rho, plus Lavender-specific fields: decay (next-trading-day P&L), lav_theo (model price), and lav_vol (calibrated implied volatility). Add greeks=all for extended Greeks through third order.
Endpoint¶
Single endpoint. No authentication required. Runs on localhost:2112.
Returns per-contract Greeks for all options on an underlying, with optional filtering, field selection, and term structure modes.
Output Formats¶
Every request accepts a format parameter:
| Format | Value | Content-Type | Notes |
|---|---|---|---|
| JSON | format=json |
application/json |
Array of objects. Default. |
| CSV | format=csv |
text/csv |
Header row + data rows. Ideal for pandas / R. |
| NDJSON | format=ndjson |
application/x-ndjson |
One JSON object per line. Good for streaming. |
| HTML | format=html |
text/html |
Rendered table. Paste the URL in a browser. |
Browser-first onboarding
Append ?format=html (or &format=html) to any request to see the output as a rendered table — no code needed. Great for quick inspection, spot-checking Greeks, or sharing a link with a colleague.
Identity Fields¶
Every response row includes identity fields that describe which contract the row belongs to.
Every response row includes both structural fields and the OSI symbol:
| Field | Example | Description |
|---|---|---|
underlying |
SPY |
Underlying symbol |
root |
SPY |
Option root |
expiry |
2026-06-19 |
Expiration date |
strike |
550 |
Strike price |
right |
call |
call or put |
osym |
SPY 260619C00550000 |
Standard OSI contract symbol (21 chars, space-padded root) |
Field Groups¶
Control which fields appear in the response with the greeks parameter. Default is core. Use greeks=all for everything, or combine groups with commas (e.g., greeks=core,chain).
Every response row includes a greeks metadata field showing which groups are active.
Which group do I need?
Most traders need core — delta, gamma, vega, theta, rho, and the model price. This is the default.
Add extra if you trade vol (vanna, volga, charm, veta) or want bid/ask IV.
Add exotic for third-order Greeks (speed, zomma, color, ultima) — rarely needed outside market-making.
Add chain for per-expiry data (forward price, rates, dividends, settlement type).
core — Essential per-strike Greeks¶
| Field | Description |
|---|---|
und_price |
Current underlying price |
delta |
\(\partial V / \partial S\) — per $1 spot move |
gamma |
\(\partial^2 V / \partial S^2\) — per $1 spot move |
vega |
\(\partial V / \partial \sigma\) — per 1% vol move |
theta |
\(\partial V / \partial t\) — per calendar day |
decay |
Expected price change to same time on next trading day |
rho |
\(\partial V / \partial r\) — per 1% rate move |
lav_theo |
Model theoretical value |
lav_vol |
Surface-fitted implied volatility (decimal: 0.25 = 25%) |
extra — Cross-Greeks and vol data¶
| Field | Description |
|---|---|
vanna |
\(\partial^2 V / \partial S\,\partial \sigma\) — delta sensitivity to vol |
volga |
\(\partial^2 V / \partial \sigma^2\) — vega sensitivity to vol (also known as vomma) |
charm |
\(\partial^2 V / \partial S\,\partial t\) — delta decay over time (annualized) |
veta |
\(\partial^2 V / \partial \sigma\,\partial t\) — vega decay over time (annualized) |
bid_vol |
Implied volatility at bid price |
ask_vol |
Implied volatility at ask price |
prev_vol |
Prior session's implied volatility |
conf_vol |
Vol surface quality metric |
exotic — Niche and third-order Greeks¶
| Field | Description |
|---|---|
speed |
\(\partial^3 V / \partial S^3\) — gamma sensitivity to spot |
zomma |
\(\partial^3 V / \partial S^2\,\partial \sigma\) — gamma sensitivity to vol |
color |
\(\partial^3 V / \partial S^2\,\partial t\) — gamma decay over time (annualized) |
ultima |
\(\partial^3 V / \partial \sigma^3\) — volga sensitivity to vol |
vera |
\(\partial^2 V / \partial \sigma\,\partial r\) — cross-sensitivity of vol and rates |
lambda |
\(\Delta \times S \,/\, V\) — leverage ratio (% option move per % spot move). Also known as omega (\(\Omega\)). |
epsilon |
\(\partial V / \partial q\) — per 1% dividend yield move |
chain — Per-expiry constants¶
| Field | Description |
|---|---|
fwd_price |
Calibrated forward price for this expiry |
ex_style |
american or european |
settle |
am or pm settlement |
days |
Fractional calendar days to settlement (e.g., 31.83 means 31 days and ~20 hours). Accounts for AM vs PM settlement. |
disc_rate |
Discount (risk-free) rate |
borr_rate |
Implied borrow rate |
divs |
Cumulative dividends to expiry |
Query Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
underlying |
string | — | All roots for an underlying (e.g., SPX returns both SPX and SPXW) |
root |
string | — | Single option root. One of underlying or root is required. |
format |
string | json |
json, csv, ndjson, or html |
exp |
date or * |
* |
Exact expiration, comma-separated list, or * for all |
right |
string | both |
call, put, or both |
min_strike |
decimal | — | Strike floor |
max_strike |
decimal | — | Strike ceiling |
min_exp |
date | — | Expiration floor |
max_exp |
date | — | Expiration ceiling |
min_days |
int | — | Minimum days to settlement |
max_days |
int | — | Maximum days to settlement |
min_delta |
decimal | — | Minimum absolute delta |
max_delta |
decimal | — | Maximum absolute delta |
greeks |
string | core |
Comma-separated field groups: core, extra, exotic, chain, or all |
center |
string | — | atm (at-the-money) or atf (at-the-forward) — anchors per expiry |
strike_count |
int | 1 |
Number of closest strikes to center, per expiry |
osym |
string | — | Request specific contracts by OSI symbol (comma-separated). Accepts padded (AAPL 260321C00400000) or compact (AAPL260321C00400000) forms. When set, root/underlying are optional. |
Parameter details
underlyingandrootaccept comma-separated lists (e.g.,underlying=SPX,NDXorroot=SPX,SPXW).underlyingexpands to all roots for each underlying —underlying=SPXreturns both SPX and SPXW options.rootreturns only the exact root(s) specified.centermust beatmoratf— unrecognized values return 400.- Unknown parameters return a 400 error with a descriptive message. This catches typos like
?righ=call. - All numeric values are rounded to 6 decimal places.
Sort Order¶
Results are sorted deterministically:
- Underlying — in the order specified by the caller
- Expiration — ascending
- Settlement — AM before PM
- Root — alphabetical
- Strike — ascending
- Right — call before put
Term Structure¶
Use center=atm or center=atf to select the N closest strikes to an anchor per expiry. Combined with strike_count=1 (the default) and right=call, this produces one row per expiration — a term structure view.
http://localhost:2112/l1/greeks?root=AAPL¢er=atf&right=call&format=html
http://localhost:2112/l1/greeks?root=AAPL¢er=atm&right=call&format=html
http://localhost:2112/l1/greeks?root=AAPL¢er=atf&strike_count=5&format=html
atmanchors to the nearest strike to the current underlying priceatfanchors to the nearest strike to the calibrated forward price for each expiry- Numeric values (e.g.,
center=25) anchor to the nearest strike by call delta — see Example Requests
All Greeks are per-share
Multiply by 100 (or the contract multiplier) to get per-contract values. This applies to all endpoints — native and vendor compatibility.
List available expirations
Use center=atm&strike_count=1&right=call to get one row per expiration — a lightweight expiry discovery query:
Example Requests¶
Every example is a complete URL — paste it in a browser or curl it.
http://localhost:2112/l1/greeks?root=AAPL : All AAPL Greeks — core fields, all expirations
http://localhost:2112/l1/greeks?root=AAPL&right=call&max_days=30 : Just calls, near-term
http://localhost:2112/l1/greeks?root=AAPL¢er=atf&right=call : Term structure — one row per expiry at the forward
http://localhost:2112/l1/greeks?root=AAPL¢er=25&right=call : 25-delta call skew across the term
http://localhost:2112/l1/greeks?root=AAPL¢er=atf&right=call&greeks=chain : Term structure with carry data (forward, rates, divs)
http://localhost:2112/l1/greeks?underlying=SPX : SPX + SPXW options together
http://localhost:2112/l1/greeks?root=AAPL&greeks=all : Every field — core, extra, exotic, chain
http://localhost:2112/l1/greeks?root=AAPL&format=html : Paste in browser — instant Greeks table
Code Examples¶
using var client = new HttpClient();
var json = await client.GetStringAsync(
"http://localhost:2112/l1/greeks?root=SPY&format=json");
using var doc = JsonDocument.Parse(json);
foreach (var row in doc.RootElement.EnumerateArray().Take(5))
{
Console.WriteLine($"{row.GetProperty("expiry")} " +
$"{row.GetProperty("strike")} {row.GetProperty("right")}: " +
$"delta={row.GetProperty("delta")}");
}
#include <cpr/cpr.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
auto r = cpr::Get(cpr::Url{
"http://localhost:2112/l1/greeks?root=SPY&format=json"});
auto data = json::parse(r.text);
for (auto& row : data | std::views::take(5))
std::cout << row["expiry"] << " " << row["strike"]
<< " delta=" << row["delta"] << "\n";
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create(
"http://localhost:2112/l1/greeks?root=SPY&format=json"))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
var array = new JSONArray(response.body());
for (int i = 0; i < Math.min(5, array.length()); i++) {
var row = array.getJSONObject(i);
System.out.printf("%s %.0f %s: delta=%.3f%n",
row.getString("expiry"), row.getDouble("strike"),
row.getString("right"), row.getDouble("delta"));
}
using CSV, DataFrames, HTTP
resp = HTTP.get(
"http://localhost:2112/l1/greeks?root=SPY&format=csv")
df = CSV.read(IOBuffer(resp.body), DataFrame)
# Near-term ATM calls
filter(r -> r.right == "call" && abs(r.delta) > 0.4, df) |>
x -> select(x, :expiry, :strike, :delta, :vega, :theta, :decay, :lav_vol) |>
x -> first(x, 10)
How It Differs from Vendor Compatibility Layers¶
| Lavender API | Vendor Compatibility | |
|---|---|---|
| Field names | Lavender native (lav_vol, und_price, decay, …) |
Vendor-specific (implied_vol, underlying_price, …) |
| Field selection | greeks= groups (core, extra, exotic, chain) |
Fixed per vendor |
| Filters | 12 filter params + term structure | Vendor-specific subset |
| Term structure | center=atm/atf + strike_count |
Not available |
| Market data fields | Not included — model outputs only | Zeroed for wire compatibility |
| Response shape | Flat array of objects | Vendor-specific envelope |
| Greek units | Per-1% vega/rho/epsilon, per-calendar-day theta | Converted to each vendor's convention |
The compatibility layers are for migrating existing code with zero changes. The Lavender API is for new integrations and for accessing the full feature set.
Error Handling¶
| Status | Condition | Example |
|---|---|---|
200 |
Success. Empty array [] means no contracts matched your filters — the root exists but no options match. |
?root=AAPL&exp=2026-07-04 (holiday, no expiry) |
400 |
Invalid or missing parameters. The response body describes the error. | Missing root or underlying, Invalid right, Unknown parameter 'righ' |
502 |
Upstream data unavailable. The gateway could not fetch Greeks from the data engine. | Transient — retry after a few seconds. |
Unknown parameters return 400 with the parameter name — this catches typos like ?righ=call before they silently produce wrong results.
Rate Limits¶
There are no rate limits. The gateway runs on localhost and serves requests as fast as your machine can handle them. Typical latency is 5–50ms for a single root, 100–200ms for large chains (SPY, SPX).
Coverage¶
Lavender covers all OPRA-listed US options — equities, ETFs, and index options including SPX, NDX, RUT, VIX, and their weekly variants. Approximately 6,000 underlying names with all listed expirations and strikes.
Data Freshness¶
Greeks are recomputed continuously during market hours (9:30 AM – 4:00 PM ET). Outside market hours, Greeks reflect the last computed values from the prior session. The gateway caches responses for up to 5 seconds — successive requests within that window return the same snapshot.
Excel Integration¶
Bulk fetch + VLOOKUP
Don't make one HTTP call per cell — Excel will freeze. Instead, use Power Query to import the full chain as a table, then VLOOKUP into it:
- Data → From Web → paste
http://localhost:2112/l1/greeks?root=AAPL&format=csv - Power Query imports all Greeks as a table
- Use
VLOOKUPorINDEX/MATCHagainst the table to pull individual values into your spreadsheet - Data → Refresh All to update Greeks
For multiple underlyings, make one query per underlying (not per contract). Each query returns the full chain in ~50ms.
Montage¶
The Lavender Montage ships with every Gateway installation. It is a real-time option chain viewer for navigating the full OPRA universe — no URLs, no code, no setup.
Calls on the left, puts on the right, strikes centered — the classic options montage layout, stacked vertically by expiration.
Chain headers — each expiration displays:
- Forward price, risk-free rate, borrow rate, cumulative dividends
- Time-to-expiration (calendar and business days)
- Expiration type label (weekly, monthly, quarterly)
Borrow rates are color-coded so hard-to-borrow names stand out immediately.
Strike-level data — per contract, ticking in real time:
- Theo price
- Bid IV, mid IV, ask IV, IV change from prior day
- Delta, gamma, theta, vega, rho
- Vanna, volga, charm, veta, epsilon
- Scaled vega
Navigation — search any of ~6,000 OPRA names via the built-in ticker picker, expand/collapse chains, scroll to ATM, and adjust visible strike depth.
Diagnostics — built-in console with color-coded event logging, latency indicator, and data freshness tracking.
The Montage reads from the same Greeks engine that powers the REST API — it is a display-only tool, not a separate data source.