OMS API

The OMS API exposes a thin HTTP layer over the NTS OMS command stream.

Base path (examples):


Authentication

All requests require:

x-api-token: <token>

Tokens are configured via the API_TOKENS environment variable on the server. If no tokens are configured, the service may run in an open “dev” mode, but that is not recommended for production.


Models

ContractIn

{
  "secType": "FUT",
  "symbol": "ES",
  "lastTradeDateOrContractMonth": "202503",
  "exchange": "SMART",
  "currency": "USD"
}

Fields:

OrderIn

{
  "action": "BUY",
  "totalQuantity": 1,
  "orderType": "MKT",
  "lmtPrice": null,
  "tif": "DAY",
  "outsideRth": true,
  "goodAfterTime": null,
  "goodTillDate": null
}

Fields:

BracketSpec / RunnerSpec

Optional wrappers that specify:

These are serialized and carried in the envelope for downstream logic in ibgatekeeper and related runners.

SubmitOrdersReq

{
  "asof": null,
  "orders": [ /* list of OrderEnvelope */ ],
  "tenant": "nts",
  "idem_hint": null,
  "dry_run": false
}

Key fields:

SubmitAck

Returned by most OMS submission endpoints:

{
  "status": "enqueued",
  "message_id": "1764...",
  "idem_key": "oms:..."
}

Fields:


Endpoints

GET /healthz

Simple health check.

Response:

{"status": "ok", "version": "0.1.0"}

POST /oms/ping

Simple envelope test, useful for connectivity and plumbing checks.

Request:

curl -X POST "$OMS_BASE/oms/ping"   -H "Content-Type: application/json"   -H "x-api-token: $API_TOKEN"   -d '{"echo": "hello-nts"}'

Payload:

{
  "echo": "hello-nts"
}

Behavior:

Response:

{
  "status": "enqueued",
  "message_id": "1764...",
  "idem_key": "oms:..."
}

POST /oms/orders

Submit one or more orders into the OMS command stream.

Request:

curl -X POST "$OMS_BASE/oms/orders"   -H "Content-Type: application/json"   -H "x-api-token: $API_TOKEN"   -d '{
    "asof": null,
    "orders": [
      {
        "contract": {
          "secType": "FUT",
          "symbol": "ES",
          "lastTradeDateOrContractMonth": "202503",
          "exchange": "SMART",
          "currency": "USD"
        },
        "order": {
          "action": "BUY",
          "totalQuantity": 1,
          "orderType": "MKT",
          "tif": "DAY",
          "outsideRth": true
        },
        "bracket": null,
        "runner": null,
        "refs": { "case": "demo", "strategy": "nts-demo" },
        "exit_policy": "bracket"
      }
    ],
    "tenant": "nts",
    "idem_hint": null,
    "dry_run": false
  }'

Behavior:

Response:

{
  "status": "enqueued",
  "message_id": "1764...",
  "idem_key": "oms:..."
}

Errors:


POST /oms/flatten

Submit a “flatten positions” command.

Request example:

curl -X POST "$OMS_BASE/oms/flatten"   -H "Content-Type: application/json"   -H "x-api-token: $API_TOKEN"   -d '{
    "account": null,
    "sec_types": ["FUT"],
    "exclude": [],
    "cancel_open_first": true,
    "wait_seconds": 30
  }'

Fields:

Behavior:

Response:

{
  "status": "enqueued",
  "message_id": "1764...",
  "idem_key": "oms:..."
}

GET /ib/events/tail

Read a recent tail of parsed IBKR events from ib:events.

Request:

curl -s "$OMS_BASE/ib/events/tail?count=50"   -H "x-api-token: $API_TOKEN"

Response:

[
  {
    "id": "1764...",
    "json": {
      "event_type": "orderStatus",
      "orderId": 1234,
      "status": "Filled",
      "filled": 1,
      "remaining": 0,
      "avgFillPrice": 4800.25,
      "symbol": "ES"
    }
  },
  {
    "id": "...",
    "json": { "...": "..." }
  }
]

This endpoint is useful for building blotter UIs and for debugging ibgatekeeper behavior.


Envelope & Security Model

The OMS API never writes raw order JSON directly to Redis. Every command is:

  1. Wrapped in an envelope:

  2. kind (e.g., "oms.submit", "oms.flatten", "oms.ping")

  3. tenant
  4. payload
  5. ts (timestamp)
  6. nonce
  7. Optional idem_key

  8. Signed using a shared secret (ENVELOPE_SECRET), and the signature is embedded in the envelope.

  9. Written to a Redis Stream (e.g., oms:commands) as a single json field containing the envelope JSON.

Downstream workers (ibgatekeeper, runners, etc.):

This separation lets you add more consumers in the future (e.g., paper trading, audit logging) without changing the OMS API surface.