CUSIP Lookup API
Search Canadian fixed-income bonds by CUSIP or ISIN in real time. Designed for typeahead inputs — fast prefix matching, full bond record returned on each keystroke.
Overview
The CUSIP Lookup API is a read-only REST endpoint that powers bond identifier
search widgets. It accepts a partial CUSIP, ISIN, or issuer name and returns
matching bonds instantly — ideal for wiring into an <input> field
with a debounce of 150–300 ms.
Each result includes the full bond record (coupon, maturity, currency, issuer type) plus the most recent CIRO price if available.
Base URL
All API requests are made over HTTPS to:
https://api-cusip.yieldexchange.ca
Authentication
Every request must include your API key in the X-API-Key HTTP header.
Keys are managed on the API Keys page of the dashboard.
X-API-Key: yex_sk_360ece523dcc8d4d93aa2331e698b0c8
Rate Limits
The lookup endpoint is optimised for typeahead usage.
Standard keys allow 600 requests / minute (10 req/sec) per key.
Burst of up to 30 requests is permitted. A 429 Too Many Requests
response is returned when exceeded; retry after the Retry-After header value.
GET /api/lookup Primary
Prefix-matches the query against CUSIP and ISIN fields (indexed scan). When the query contains only letters, falls back to a partial issuer name search. Results are ordered: exact match → prefix match → alphabetical.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| q | string | required | — |
CUSIP prefix (e.g. 1350), ISIN prefix (e.g. CA1350),
or partial issuer name (e.g. Royal Bank).
Min 1 char, max 20 chars.
|
| limit | integer | optional | 10 | Max results to return (1–50). Use 1 for exact lookup. |
| status | string | optional | "active" |
Filter by lifecycle: active (not yet matured),
matured, or all.
|
Headers
| Header | Required | Description |
|---|---|---|
| X-API-Key | required | Your API key. |
GET /api/bonds/{id}
Fetch a single bond by exact CUSIP or ISIN. Returns the full record plus the most recent CIRO price observation.
Path Parameter
| Parameter | Type | Description |
|---|---|---|
| id | string |
9-char CUSIP (e.g. 135087T53) or 12-char ISIN
(e.g. CA135087T537). Case-insensitive.
|
Response Schema
GET /api/lookup — response envelope
BondRecord object
PriceRecord object (nested in each result)
Live Demo
Enter your API key and start typing a CUSIP, ISIN, or issuer name. Results appear as you type (150 ms debounce).
Code Examples
Typeahead search — prefix query
# Search for all GoC bonds starting with "1350" curl -s -X GET \ "https://api-cusip.yieldexchange.ca/api/lookup?q=1350&limit=10&status=active" \ -H "X-API-Key: yex_sk_360ece523dcc8d4d93aa2331e698b0c8"
import requests API_KEY = "yex_sk_360ece523dcc8d4d93aa2331e698b0c8" BASE = "https://api-cusip.yieldexchange.ca" def lookup(query: str, limit: int = 10, status: str = "active"): resp = requests.get( f"{BASE}/api/lookup", params={"q": query, "limit": limit, "status": status}, headers={"X-API-Key": API_KEY}, timeout=5, ) resp.raise_for_status() return resp.json()["results"] # Typeahead: called on each keystroke for bond in lookup("1350"): print(f"{bond['cusip']} {bond['issuer_name']} mat={bond['maturity_date']}")
const API_KEY = "yex_sk_360ece523dcc8d4d93aa2331e698b0c8"; const BASE = "https://api-cusip.yieldexchange.ca"; /** * Typeahead lookup — wire to an input's `oninput` handler with debounce. * @param {string} query - partial CUSIP, ISIN, or issuer name * @returns {Promise<BondRecord[]>} */ async function lookupBond(query, limit = 10, status = "active") { const url = new URL(`${BASE}/api/lookup`); url.searchParams.set("q", query); url.searchParams.set("limit", limit); url.searchParams.set("status", status); const res = await fetch(url, { headers: { "X-API-Key": API_KEY }, }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); return data.results; } // Debounce helper function debounce(fn, ms) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), ms); }; } // Wire to input const input = document.querySelector("#cusip-search"); input.addEventListener("input", debounce(async (e) => { if (e.target.value.length < 2) return; const results = await lookupBond(e.target.value); // render results … }, 150));
interface PriceRecord { price_date: string; mid_price: number | null; yield_mid: number | null; g_spread_bps: number | null; } interface BondRecord { id: number; cusip: string | null; isin: string | null; issuer_name: string; issuer_type: "GOC" | "PROV" | "FIN" | "CORP"; province_code: string | null; coupon_rate: number | null; maturity_date: string | null; issue_date: string | null; currency: string; amount_outstanding_cad: number | null; confidence_score: number; source_name: string; latest_price: PriceRecord | null; } interface LookupResponse { query: string; status: string; count: number; results: BondRecord[]; } const API_KEY = "yex_sk_360ece523dcc8d4d93aa2331e698b0c8"; const BASE = "https://api-cusip.yieldexchange.ca"; async function lookupBond( query: string, limit: number = 10, status: string = "active" ): Promise<BondRecord[]> { const url = new URL(`${BASE}/api/lookup`); url.searchParams.set("q", query); url.searchParams.set("limit", String(limit)); url.searchParams.set("status", status); const res = await fetch(url.toString(), { headers: { "X-API-Key": API_KEY }, }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data: LookupResponse = await res.json(); return data.results; }
Exact CUSIP or ISIN lookup
# By exact CUSIP curl -s "https://api-cusip.yieldexchange.ca/api/bonds/135087T53" \ -H "X-API-Key: yex_sk_360ece523dcc8d4d93aa2331e698b0c8" # By exact ISIN (same endpoint, auto-detected) curl -s "https://api-cusip.yieldexchange.ca/api/bonds/CA135087T537" \ -H "X-API-Key: yex_sk_360ece523dcc8d4d93aa2331e698b0c8"
def get_bond(identifier: str): """Fetch a single bond by CUSIP or ISIN.""" resp = requests.get( f"{BASE}/api/bonds/{identifier.upper()}", headers={"X-API-Key": API_KEY}, ) if resp.status_code == 404: return None resp.raise_for_status() return resp.json() bond = get_bond("CA135087T537") print(bond["cusip"], bond["coupon_rate"], bond["maturity_date"])
Example JSON response
{
"query": "CA135087T",
"status": "active",
"count": 3,
"results": [
{
"id": 4821,
"cusip": "135087T53",
"isin": "CA135087T537",
"issuer_name": "CANADA (GOVERNMENT OF)",
"issuer_type": "GOC",
"province_code": null,
"coupon_rate": 3.25,
"maturity_date": "2035-12-01",
"issue_date": "2025-07-03",
"currency": "CAD",
"amount_outstanding_cad": 22500000000,
"confidence_score": 0.97,
"source_name": "bmo_etf",
"latest_price": {
"price_date": "2026-04-07",
"mid_price": 98.14,
"yield_mid": 3.41,
"g_spread_bps": null
}
}
// … more results
]
}
Errors
| HTTP Status | Code | When it occurs |
|---|---|---|
| 401 | Unauthorized | Missing or invalid X-API-Key header. |
| 404 | Not Found | CUSIP/ISIN not in the database (/api/bonds/{id} only). |
| 422 | Unprocessable Entity | Missing required query parameter q, or value out of range. |
| 429 | Too Many Requests | Rate limit exceeded. Check Retry-After header. |
| 500 | Internal Server Error | Unexpected server error. Contact support if persistent. |