Contract discovery and validation
Use reference values returned by the API instead of hard-coding exchange-specific formats.
ETD discovery
Follow the picker sequence. Pass each returned value unchanged and URL encode path parameters.
GET /validation-reference/exchangesGET /validation-reference/contracts/{exchange_code}GET /validation-reference/contract-type/{exchange_code}/{contract_code}GET /validation-reference/expiries/{exchange_code}/{contract_code}/{contract_type}GET /validation-reference/strikes/{exchange_code}/{contract_code}/{contract_type}/{expiry}for options
from urllib.parse import quote
exchange = "CME"
contracts = requests.get(
f"{C9_API_ENDPOINT}/validation-reference/contracts/{quote(exchange, safe='')}",
headers=HEADERS,
).json()
Expiry formats differ by venue. Use the returned display value, such as MAR-28 or 17-DEC-27, rather than assuming YYYYMM.
Other position types
These endpoints return the accepted dropdown values for their position type:
GET /validation-reference/fi-referenceGET /validation-reference/irs-referenceGET /validation-reference/ladder-referenceGET /validation-reference/fx-symbols
POST/validation-reference/portfolios
Validate a portfolio
POST /validation-reference/portfolios strictly validates and standardises positions without calculating margin. Invalid rows remain visible so they can be corrected.
curl -sS "$C9_API_ENDPOINT/validation-reference/portfolios" \
-H "Authorization: Bearer $C9_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"portfolio": [{
"account_code": "ACCOUNT_1",
"exchange_code": "CME",
"contract_code": "SR3",
"contract_type": "FUT",
"contract_expiry": "MAR-28",
"net_position": 10,
"account_type": "H"
}]
}'
Event-market positions are validated only when their exchange is enabled on the caller's licence.