Skip to content

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:

http://localhost:2112/l1/greeks?root=SPY&format=html

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

GET /l1/greeks

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

  • underlying and root accept comma-separated lists (e.g., underlying=SPX,NDX or root=SPX,SPXW).
  • underlying expands to all roots for each underlying — underlying=SPX returns both SPX and SPXW options.
  • root returns only the exact root(s) specified.
  • center must be atm or atf — 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:

  1. Underlying — in the order specified by the caller
  2. Expiration — ascending
  3. Settlement — AM before PM
  4. Root — alphabetical
  5. Strike — ascending
  6. 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&center=atf&right=call&format=html
http://localhost:2112/l1/greeks?root=AAPL&center=atm&right=call&format=html
http://localhost:2112/l1/greeks?root=AAPL&center=atf&strike_count=5&format=html
  • atm anchors to the nearest strike to the current underlying price
  • atf anchors 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:

http://localhost:2112/l1/greeks?root=AAPL&center=atm&strike_count=1&right=call&format=csv

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&center=atf&right=call : Term structure — one row per expiry at the forward

http://localhost:2112/l1/greeks?root=AAPL&center=25&right=call : 25-delta call skew across the term

http://localhost:2112/l1/greeks?root=AAPL&center=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

import pandas as pd

url = "http://localhost:2112/l1/greeks"
df = pd.read_csv(f"{url}?root=SPY&format=csv")

# Near-term ATM calls
near = df[(df["right"] == "call") & (df["delta"].abs() > 0.4) & (df["delta"].abs() < 0.6)]
print(near[["expiry", "strike", "delta", "vega", "theta", "decay", "lav_vol"]])
df <- read.csv(paste0(
  "http://localhost:2112/l1/greeks",
  "?root=SPY&format=csv"))

# Filter to near-term calls
calls <- df[df$right == "call" & abs(df$delta) > 0.4, ]
head(calls[, c("expiry", "strike", "delta", "vega", "theta", "decay", "lav_vol")])
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"));
}
const resp = await fetch(
  "http://localhost:2112/l1/greeks?root=SPY&format=json"
);
const greeks = await resp.json();
greeks.slice(0, 5).forEach(c =>
  console.log(`${c.expiry} ${c.strike} ${c.right}: delta=${c.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:

  1. Data → From Web → paste http://localhost:2112/l1/greeks?root=AAPL&format=csv
  2. Power Query imports all Greeks as a table
  3. Use VLOOKUP or INDEX/MATCH against the table to pull individual values into your spreadsheet
  4. 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.