Docs
POST /v2/journal/import

Bulk-import journal trades

journal_importTrades

Uploads many journal trades in one request and reports how many were created or skipped, with each failed row. Re-sending the same import_id is safe: it returns the first result without importing twice.

Query parameters

import_id string

Your idempotency id for this upload (required). Sending the same import_id again returns the first result and imports nothing.

format string

Body format: jsonl (default) or csv.

Request body

text/plainrequired

JSONL (one normalized trade object per line) or fixed-column CSV

Details

The body is JSONL (format=jsonl, the default: one trade object per line, in the POST /v2/journal/trades shape) or fixed-column CSV (format=csv). Each failed row is listed in errors as {row, code}, where code is a stable machine-readable reason.

Example

http
POST /v2/journal/import?import_id=2026-09-import-1&format=jsonl
json
{
  "data": {
    "created": 42,
    "skipped": 1,
    "errors": [{ "row": 17, "code": "missing_price" }]
  },
  "meta": { "caps": { "tier": "pro", "applied": [] } }
}

Response

Prices are dollars, timestamps epoch milliseconds, strikes integer thousandths of a dollar; null means unknown. Units →

200application/json

{created, skipped, errors: [{row, code}]} in data

object

A successful response: the payload consumers parse plus response metadata. data shapes are the platform types — never reshaped by the envelope.

data object required

The result of a bulk journal import: counts + per-row failures. Stored per import_id so a re-POST with the same id returns this verbatim (no-op).

created integer required
errors array<ImportError> required
code string required
row integer required
skipped integer required
meta object required

Response metadata.

caps object nullable

meta.caps — the entitlement caps that shaped this response. applied lists the caps that actually changed it (for example range_clamped).

applied array<string> required

Which caps actually shaped this response (e.g. range_clamped). Empty = nothing was clamped.

darkpool boolean nullable

Whether this account can use Off-Exchange in the site.

flow boolean nullable

Whether the OPRA option-flow capability (flow) is granted to this principal in the app: site Pro plus a CBOE non-professional attestation (never on an itm_ key). Emitted explicitly — true and false — by the account endpoints, so the app reads the grant instead of inferring it from tier and attestation; absent on routes that do not report it.

gexDepth string nullable

GEX data depth when the route reports it. Camel-cased to match the browser capability bundle; absent on unrelated routes.

tier string required

The tier the request was served under.

cursor string nullable

Opaque continuation cursor (pass back as ?cursor=); absent when there is nothing more to read.

plane string nullable

Which serving tier answered the read (meta.plane). Informational provenance: treat it as an opaque label, because new values may appear.

Errors

Every error is the JSON error envelope; branch on error.code.

StatusMeaning
400

invalid_params — missing import_id / bad format

401

unauthenticated