Structured Note Reference Data

Explorer Contact Us
More ▾

Pricing Data: API

The price feed is also available as an HTTP API. You give us an ISIN — or a CUSIP, or a list of either — and we hand back the latest price we have, the raw bid/mid/ask sides behind it, and enough reference and lifecycle context to know what you're looking at. It spans everything in our security master: structured notes, municipal and corporate bonds, treasuries, CDs, ETFs/ETNs, UITs, and more. We route the lookup to the right product's price table for you; you don't have to know which one a given ISIN lives in.

The fixed seven-field price is the start. The same API also serves the product's whole price row, every price in a date range, a product's entire universe on a date, and reference fields by name — each described in its own section below the bulk lookup.

The API lives at https://api.sqxnotes.com/v1/. Authentication is by API key in the x-api-key header. We'll get you a key.

Requests of ordinary size are synchronous: the answer comes back on the connection. A request for 1,000 or more ISINs, or one whose result reaches 1,000 rows, is too large for a single HTTP response, so it becomes a job — you get a 202 with a URL to poll and, when it finishes, a CSV to download. The section on large requests below has the flow. Everything under 1,000 needs no polling.


The five-second version

If you have an ISIN, ask for it:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/byIsin?isin=US06370EDU91"

You get back 200 with the price right away, or 404 if we've never heard of the ISIN. That's the whole flow.


What you get back on success

Every response — success or error — comes in the same envelope: a data object, an errors array (empty on success), and a meta block with a request id and the server's as_of timestamp. On a 200, data carries three things: the pricing record, a reference block identifying the security, and a lifecycle_status.

{
    "data": {
        "reference": {
            "isin": "US06370EDU91",
            "cusip": "06370EDU9",
            "description": "Bank of Montreal Senior Medium-Term Notes",
            "type": "structured_note",
            "issuer": "Bank of Montreal",
            "currency": "USD",
            "ticker": null,
            "maturity_date": "2029-05-30"
        },
        "pricing": {
            "pricing_date": "2026-06-03",
            "price": 98.42,
            "bid_price": 98.17,
            "mid_price": 98.42,
            "ask_price": 98.67,
            "currency": null,
            "source": "icevpdt"
        },
        "lifecycle_status": "active"
    },
    "errors": [],
    "meta": {
        "request_id": "3f1c8a2e-9b04-4e77-bd1a-0c2f5e6a7d10",
        "as_of": "2026-06-04T20:00:00+00:00",
        "page": null
    }
}

The pricing object always has the same seven keys, whatever the product. Anything we don't have for a given security comes back as JSON null — never an empty string or an "N/A" sentinel.

Alongside the price we return lifecycle_statusactive, inactive, or null. It's computed from the security master: a security past maturity or flagged matured/called/redeemed reads inactive; one that's still live and recently priced reads active; anything we can't place stays null.

The authoritative, field-by-field contract — every key, enum, and status code, including the response envelope — is the OpenAPI 3.1 spec (openapi.yaml). This page is the narrative guide; the spec is the source of truth.

A CUSIP works just as well

If you hold CUSIPs rather than ISINs, use byCusip. We resolve it to the ISIN through the security master and answer with the identical envelope — your CUSIP echoes back in reference.cusip.

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/byCusip?cusip=06370EDU9"

A price on a particular date

For a historical look-up, add a date:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/byIsinHistorical?isin=US06370EDU91&date=2025-09-15"

Markets don't price every security every day, so we don't make you guess whether a given date has a row. The pricing object grows three extra fields that tell you exactly what we returned relative to what you asked for:

{
    "requested_date": "2025-09-15",
    "effective_date": "2025-09-12",
    "match": "prior",
    "price": 97.10,
    "bid_price": 96.85,
    "mid_price": 97.10,
    "ask_price": 97.35,
    "currency": null,
    "source": "icevpdt",
    "pricing_date": "2025-09-12"
}

match is one of exact (we had a row on your date), prior (we fell back to the most recent earlier date), next (nothing on or before your date, so we reached forward to the first later one), or none (we have no price for this security at all). When match is none you still get 200effective_date and the price fields are simply null. It isn't an error, so there's nothing in errors; the enum tells the whole story.


Looking up a lot of them at once

To price a list, POST it to the bulk endpoint instead of firing one request per ISIN:

curl -H "x-api-key: $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"isin_list": ["US06370EDU91", "US912828YL86", "NOTANISIN"]}' \
    https://api.sqxnotes.com/v1/price/bulk/byIsin

The response sorts every ISIN you sent into one of three buckets, all three always present even when empty:

{
    "data": {
        "success": [
            { "reference": { "...": "..." }, "pricing": { "...": "..." }, "lifecycle_status": "active" }
        ],
        "unprocessed": [
            { "isin": "NOTANISIN", "reason": "invalid_isin: ISIN must be 12 characters, got 9" }
        ],
        "not_found": ["US912828YL86"]
    },
    "errors": [],
    "meta": { "...": "..." }
}

Duplicates in your input are de-duped, and the cap is 1000 ISINs per request. Send more and you get 429 with a QUOTA_LIMIT_EXCEEDED error telling you the limit and what you sent.


When we have the security but no price

A 404 means we don't recognize the identifier at all. It does not mean "no price" — those are different answers. If the security is in our master but we simply don't carry a price for it (its product type has no price table, or nothing's been captured yet), you still get 200 with the full reference block and lifecycle_status, and the pricing fields come back null. You can tell an unpriced-but-known security from a stale one by reading lifecycle_status alongside the null price.


The whole price row

byIsin deliberately returns the same seven keys for every product. The price tables hold much more — a corporate bond's latest row has 52 columns — and /price/latest returns all of it:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/latest?isin=AED01390C246"

Or name the columns you want with fields, and you get exactly those keys, in that order:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/latest?isin=AED01390C246&fields=pricing_date,clean_price,bid_price,ask_price,data_source"
{
    "data": {
        "product": "corporate_bond",
        "reference": {
            "isin": "AED01390C246",
            "cusip": null,
            "description": "4.57% DB REDEEM 23/05/2027 AED 100000",
            "type": "corporate_bond",
            "issuer": "United Arab Emirates",
            "currency": "AED",
            "ticker": null,
            "maturity_date": "2027-05-23",
            "last_pricing_date": null,
            "status": null
        },
        "pricing": {
            "pricing_date": "2026-09-03",
            "clean_price": "100.114995",
            "bid_price": "100.104456",
            "ask_price": "100.125534",
            "data_source": "deriveddata"
        },
        "lifecycle_status": null
    },
    "errors": [],
    "meta": { "...": "..." }
}

Four things to know about this route that byIsin never made you think about:

The list form is POST /price/latest/bulk with the same body shape as bulk/byIsin plus an optional fields list; the three buckets are the same. Because the rows differ by product, two success items can have different pricing keys when your list mixes products.


Filtering on the fields you asked for

Any of the row-returning routes takes a filter of the form <field><op><value>, with op one of >=, <=, !=, =, >, <:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/range?isin=AED01390C246&from=2026-08-01&to=2026-08-31&fields=pricing_date,bid_price&filter=bid_price>=100"

One rule: a filter may only name a field the request asked for. Filtering on a column you didn't request would let you read its values out of which rows came back, so it's a 400 (messageCode 1010) telling you to add the field to fields or drop the filter. Values are typed from the column — numbers compare as numbers, dates as dates — and are bound as query parameters, never spliced into SQL.


Every price in a date range

Where byIsinHistorical gives you one price nearest a date, /price/range gives you every price in a window, ascending by date, from and to both inclusive:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/range?isin=AED01390C246&from=2026-08-24&to=2026-08-28&fields=pricing_date,bid_price,ask_price"
{
    "data": {
        "product": "corporate_bond",
        "reference": { "isin": "AED01390C246", "...": "..." },
        "range": { "from": "2026-08-24", "to": "2026-08-28" },
        "prices": [
            { "pricing_date": "2026-08-24", "bid_price": "100.167192", "ask_price": "100.194793" },
            { "...": "..." },
            { "pricing_date": "2026-08-28", "bid_price": "100.173271", "ask_price": "100.202705" }
        ],
        "lifecycle_status": null
    },
    "errors": [],
    "meta": { "...": "..." }
}

fields and filter work as on /price/latest. A to before from is a 400 (messageCode 1012) rather than an empty list — an empty list would look exactly like a security with no prices. An empty prices array on a 200 means we know the security and the window simply holds no row.

The list form is POST /price/range/bulk with {"isin_list": [...], "from": "...", "to": "...", "fields": [...]}; one window, many ISINs, each success item carrying its own prices array.

Ranges are counted before they are read: 1,000 or more rows becomes a job (see the large-requests section). One ISIN over a year of daily prices is enough on its own, and so is a few days of the treasury intraday series.


A whole product on a date

/price/universe starts from a product instead of an ISIN and returns every price it holds on a date, or across a window:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/universe?product=corporate_bond&date=2026-08-28&fields=isin,bid_price"

Send date for one day or from and to for a window, not both. product is one of structured_note, corporate_bond, municipal_bond, exchange_traded, cd, uit, treasury_bond, alternative_investment. Rows carry price columns only — no reference block per row, because a universe is tens of thousands of rows and identity is something you fetch once from the reference routes.

A universe is nearly always a job: a single corporate-bond date is about 97,000 rows, so the call above answers 202 and the CSV arrives a few seconds later. The synchronous 200 with data.prices[] is the small case — a narrow filter, or a small product.


Intraday treasury prices

Treasuries are priced through the day, about every 15 minutes. Add intraday=true to /price/latest for the most recent intraday print instead of the daily row:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/price/latest?isin=US3130AFFX04&intraday=true&fields=pricing_datetime,bid,ask"
{ "product": "treasury_bond", "pricing": { "pricing_datetime": "2026-09-03 16:15:00", "bid": "97.8325", "ask": "97.9325" } }

On /price/range a treasury's history is its intraday series — there is no daily aggregate to fall back to — so a treasury range returns intraday rows whether or not you send the flag, and the whole of the last day is included.

intraday=true on anything that isn't a treasury is a 400 (messageCode 1015) naming the ISIN, never a silent fall-through to the daily row — if you asked for intraday data and got a daily print, you couldn't tell. On the bulk forms the non-treasury lands in unprocessed and the treasuries in the same list are still served. A treasury, for this purpose, is any ISIN present in our treasury price table; the security master types most of them as corporate bonds, and we resolve that for you.


When a request is too large for one call

The API answers on the connection whenever it can. A request for 1,000 or more ISINs, or one whose result reaches 1,000 rows, becomes a job instead: you get 202 at once, with a URL to poll.

{
    "data": {
        "job_id": "674be29b-4ddb-4dfe-91f2-70a685be4af9",
        "status": "queued",
        "status_url": "https://api.sqxnotes.com/v1/jobs/674be29b-4ddb-4dfe-91f2-70a685be4af9",
        "row_count": 96812,
        "next": "Poll status_url until it returns HTTP 200 with a download_url."
    },
    "errors": [],
    "meta": { "...": "..." }
}

Poll status_url. While the job is queued or running you get 202 again; when it's done you get 200 with a presigned download link:

{
    "data": {
        "job_id": "674be29b-4ddb-4dfe-91f2-70a685be4af9",
        "status": "done",
        "kind": "price_universe",
        "row_count": 96812,
        "download_url": "https://sqx-api-jobs-prod.s3.amazonaws.com/...",
        "expires_at": "2026-09-03T21:39:08+00:00",
        "next": "Download the CSV from download_url before expires_at."
    },
    "errors": [],
    "meta": { "...": "..." }
}

The link is valid for an hour from the poll that produced it (poll again for a fresh one); the file itself is kept for 7 days. A job that failed answers 500 with messageCode 1060 and the cause in message. A job is visible only to the key that submitted it — anyone else's job_id is a 404, indistinguishable from one that never existed. Most jobs finish within seconds; polling every 15 seconds is plenty, and bound your loop rather than waiting forever.

The CSV is one row per price row (or per ISIN, for a latest-price job). Because products have different columns, the header is product followed by every column any product in the result has; a column a product lacks is empty on its rows. A reference-fields job is keyed isin,product followed by the fields you asked for.

You don't have to size your request in advance — the retrieval routes hand off on their own. If you already know it's large, or you have a file of ISINs, go straight to the job route:

curl -H "x-api-key: $API_KEY" \
    -F "file=@isins.txt" -F kind=latest -F fields=pricing_date,bid_price \
    https://api.sqxnotes.com/v1/jobs/isins

file is ISINs one per line or comma-separated. kind is latest (the default), range (add from and to), universe (add product; no file needed) or reference (add fields). A JSON body with the same keys and an isin_list works too. The response is the same 202.


Reference fields, by name

Alongside the price, you can ask for reference fields — coupon, maturity, issuer, and the rest of what the vendor tables hold — by naming them:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/reference/fields?isin=AED01390C246&fields=bond.InterestRate,bond.MaturityDate,issur.IssuerName"
{
    "data": {
        "product": "corporate_bond",
        "reference": { "isin": "AED01390C246", "...": "..." },
        "reference_fields": {
            "bond.InterestRate": "4.57000000",
            "bond.MaturityDate": "2027-05-23",
            "issur.IssuerName": "United Arab Emirates"
        }
    },
    "errors": [],
    "meta": { "...": "..." }
}

Only fields that are one-per-security are served here. Schedules — coupons, calls, puts, redemptions, sinking funds — are several rows per security and are not on this route.

The list form is POST /reference/fields/bulk with {"isin_list": [...], "fields": [...]}, one field list for the whole list; an ISIN whose product lacks one of the fields lands in unprocessed with the field in its reason. At 1,000 or more ISINs it becomes a job like the price routes.


Yield curves

Curves are a different shape of data from everything above: they aren't per-security, they're market-level, so nothing here names an ISIN. We offer three families:

Start with discovery — GET /curves lists every (family, curve) pair with rows in the last 30 days, each with its latest snapshot and tenor count:

curl -H "x-api-key: $API_KEY" "https://api.sqxnotes.com/v1/curves"
{
    "data": {
        "families": ["treasury_bond", "corporate_bond", "zero_coupon"],
        "window_days": 30,
        "curves": [
            { "family": "treasury_bond", "curve": "otr", "latest_pricing_datetime": "2026-09-03 23:59:00", "points": 11 },
            { "family": "corporate_bond", "curve": "A", "latest_pricing_datetime": "2026-09-03 00:00:00", "points": 34 },
            { "family": "zero_coupon", "curve": "US", "latest_pricing_datetime": "2026-09-03 00:00:00", "points": 33 }
        ]
    },
    "errors": [],
    "meta": { "...": "..." }
}

GET /curves/latest?family=corporate_bond&curve=A returns every tenor of that curve at its own most recent snapshot:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/curves/latest?family=corporate_bond&curve=A"
{
    "data": {
        "family": "corporate_bond",
        "curve": "A",
        "cadence": "daily",
        "currency": null,
        "pricing_datetime": "2026-09-03 00:00:00",
        "points": [
            { "tenor": "0.083", "tenor_label": "1M", "yield": "4.74301100", "pricing_datetime": "2026-09-03 00:00:00" },
            { "tenor": "5.000", "tenor_label": "5Y", "yield": "5.02236900", "pricing_datetime": "2026-09-03 00:00:00" }
        ]
    },
    "errors": [],
    "meta": { "...": "..." }
}

Tenor and yield are decimal strings, like every other decimal value in this API — tenor is years as stored ("0.083"), tenor_label is the delivery spelling (round(tenor*12)M under a year, truncate(tenor)Y from a year up). A ratings curve carries 34 tenors; a zero-coupon curve carries 33. The tenor = 0 row is never served, as none of our deliveries serve it.

"Latest" is per tenor, not per curve. GET /curves/latest?family=treasury_bond&curve=otr doesn't return one snapshot — the treasury curve prints at different minutes for different tenors (about 234 snapshots a day across 11 tenors), so each point carries its own pricing_datetime, and data.pricing_datetime is the newest of them. For a daily curve every tenor shares one snapshot, so this collapses to "the latest day" — one rule serves both cadences.

GET /curves/range returns every snapshot in a window, grouped:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/curves/range?family=corporate_bond&curve=BBB&from=2026-08-25&to=2026-08-29"
{
    "data": {
        "family": "corporate_bond",
        "curve": "BBB",
        "cadence": "daily",
        "currency": null,
        "range": { "from": "2026-08-25", "to": "2026-08-29" },
        "snapshots": [
            { "pricing_datetime": "2026-08-25 00:00:00", "points": [ { "tenor": "0.083", "tenor_label": "1M", "yield": "4.98000000" } ] }
        ]
    },
    "errors": [],
    "meta": { "...": "..." }
}

A snapshot's points don't repeat pricing_datetime — it's the snapshot's, given once. As on every other route, at 1,000 or more rows the request becomes a job (202, same poll-and-download flow as above): three days of the intraday otr curve is already past the threshold, while a working week of a daily ratings curve is not.

zero_coupon responses carry currency — the country's currency from our reference table, null where the country has none — on both /curves/latest and /curves/range; every other family answers currency: null.

GET /curves/constituents lists a curve's member securities, keyed by family and curve like the other curve routes. For a ratings curve, give it a date:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/curves/constituents?family=corporate_bond&curve=BBB&date=2026-09-03"
{ "data": { "family": "corporate_bond", "curve": "BBB", "date": "2026-09-03", "isins": ["US00107VAB99", "US00108WAB63", "..."] }, "errors": [], "meta": { "...": "..." } }

date is required for a dated curve — the A curve alone lists about 8,000 ISINs on a given day, so that call is normally a job too. The on-the-run list is different: it's a static list with no history, so date is ignored and the response carries constituents (ISIN plus description) as well as the bare ISIN list:

curl -H "x-api-key: $API_KEY" \
    "https://api.sqxnotes.com/v1/curves/constituents?family=treasury_bond&curve=otr"
{ "data": { "family": "treasury_bond", "curve": "otr", "date": null, "isins": ["US912797SK41", "US91282CRF04", "..."], "constituents": [ { "isin": "US912797SK41", "description": "Bill 1m" }, { "isin": "US91282CRF04", "description": "Bond 10y" } ] }, "errors": [], "meta": { "...": "..." } }

Scope: curves (or the generic price grant — a key that already holds pricing access reads curves with no new grant needed). Billing: every curve call is billed per request, never per ISIN — curves name no security, so they can't be counted against a monthly ISIN cap, and they never are.


When you get input wrong

Bad input returns 400 with a structured error in the errors array, in the same ErrorDetailV2 shape the rest of the v1 API uses — a numeric messageCode, a category, a machine-readable type, and a human message:

{
    "data": null,
    "errors": [
        {
            "category": "VALIDATION_ERROR",
            "type": "INVALID_INPUT",
            "messageCode": 1010,
            "message": "Invalid ISIN: checksum invalid",
            "messageValues": { "isin": "US06370EDU90" }
        }
    ],
    "meta": { "...": "..." }
}

Filter on messageCode, not on message text — the codes are stable, the wording isn't. The platform-wide codes:

messageCodeWhen
1001A required parameter is missing. messageValues.parameter names it.
1010ISIN is malformed or fails its check digit; also a filter the route will not apply.
1011CUSIP is malformed or fails its check digit.
1012A date isn't a valid YYYY-MM-DD, or a window's to is before its from.
1015The request names something this route does not offer — a field, a product, a job kind — or asks for intraday prices on a security that isn't a treasury. messageValues names it.
1033The API key's grant has lapsed (403).
1040The identifier is well-formed but we hold no such security or job (404).
1050The key is over a distinct-ISIN quota (lifetime or monthly), over its per-second rate, or a bulk request exceeded its cap (429).
1060A database failure on our side, or an asynchronous job that failed or could not start (500 / 503).

Lowercase identifiers are silently uppercased — copy-paste from a spreadsheet just works.

On the bulk endpoint, 1050 also covers a request over the 1000-ISIN cap. On the row-returning routes, 1015 is the answer to a field, product or job kind the API does not offer, and to intraday=true on anything that isn't a treasury; 1001 is a missing isin_list, product, date window or (on /reference/fields) fields.


Endpoint reference

MethodPathPurpose
GET/price/byIsin?isin={ISIN}Latest price by ISIN. 200 with the record, 404 if the ISIN is unknown.
GET/price/byCusip?cusip={CUSIP}Latest price by CUSIP. Resolves to ISIN first; same payload as byIsin.
GET/price/byIsinHistorical?isin={ISIN}&date={YYYY-MM-DD}Price as of a date, with a match of exact, prior, next, or none.
POST/v1/price/bulk/byIsinPrice up to 1000 ISINs in one call. Body {"isin_list": [...]}; returns success / unprocessed / not_found.
GET/price/latest?isin={ISIN}[&fields=a,b][&filter=…][&intraday=true]The product's whole latest price row minus insert_date, or exactly the named fields.
POST/price/latest/bulkSame for a list. Body {"isin_list": [...], "fields": [...]}; 1,000+ ISINs → 202 job.
GET/price/range?isin={ISIN}&from={D1}&to={D2}[&fields=…][&filter=…]Every dated price in the window, ascending. 1,000+ rows → 202 job.
POST/price/range/bulkSame for a list. Body {"isin_list": [...], "from": "…", "to": "…", "fields": [...]}.
GET/price/universe?product={P}&date={D} or &from={D1}&to={D2}Every price a product holds on a date or in a window. Normally a 202 job.
GET/reference/fields?isin={ISIN}&fields=a,table.b,coreNamed reference fields. fields required.
POST/reference/fields/bulkSame for a list. Body {"isin_list": [...], "fields": [...]}.
GET/curves?Discovery: every offered (family, curve) with rows in the last 30 days.
GET/curves/latest?family={F}&curve={C}The curve's tenors at each one's own latest snapshot.
GET/curves/range?family={F}&curve={C}&from={D1}&to={D2}Every snapshot in the window, grouped. 1,000+ rows → 202 job.
GET/curves/constituents?family={F}&curve={C}[&date={D}]Member ISINs for a curve and date; date required except for the on-the-run list. Zero-coupon curves have none (400). 1,000+ ISINs → 202 job.
POST/jobs/isinsRun a retrieval as a job regardless of size. Multipart file= of ISINs or a JSON body; kind = latest / range / universe / reference. Always 202.
GET/jobs/{job_id}Poll a job. 202 while running; 200 with download_url when done; 404 if it isn't yours.
GET/versionReport API version. No auth required.

Authentication & versioning

Every request except /version needs a valid API key in the x-api-key header. Keys are scoped per client, and a key can also carry an expiry, a lifetime distinct-ISIN quota — a cap on how many distinct ISINs it will ever be served — a monthly distinct-ISIN cap per product (or shared across a chosen set of products), and a per-second request rate. A key whose grant has lapsed answers 403 (messageCode 1033); one over a quota, a monthly cap or its rate answers 429 (messageCode 1050, with the limit and window in messageValues).

The v1 base path is stable. Field additions are non-breaking and ship in-place. Breaking changes — renames, removals, semantic shifts — land at a new major version on a new stage. Minor and patch updates are reported at /version.

On this endpoint family, pricing access and historical-pricing access are separate grants — a key can hold one without the other. The whole-row, date-range, universe and reference-field routes are each their own grant too (a key can hold the latest row without holding ranges or the universe), and the job routes need the jobs grant explicitly. A key that holds the generic pricing grant covers every price route.

A key can also carry a monthly cap on distinct ISINs for a product — or one cap shared across several products, say 10,000 ISINs a month between structured notes and corporate bonds — and a per-second request rate. Over either is a 429 with messageCode 1050; messageValues carries the limit, the window (the UTC calendar month, or second) and, for a monthly cap, the products it spans. The month resets on the first, UTC. ISINs that return no data are not charged against any cap, and an ISIN already served to you this month is not charged twice.

Want this data flowing into your systems? Talk to us about coverage, delivery, and the API.

Contact us to learn more