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.

  1. GET /validation-reference/exchanges
  2. GET /validation-reference/contracts/{exchange_code}
  3. GET /validation-reference/contract-type/{exchange_code}/{contract_code}
  4. GET /validation-reference/expiries/{exchange_code}/{contract_code}/{contract_type}
  5. 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-reference
  • GET /validation-reference/irs-reference
  • GET /validation-reference/ladder-reference
  • GET /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.

Was this page helpful?