> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trdrs.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Save an instrument candidate

> Private preview, disabled unless VENUE_CONFIGURATION_ENABLED is enabled and the vault is configured. This branch has not enabled these routes in the public sandbox. Existing trdrs_sk partner/tenant keys do not authorize these routes. Requires venue:configure. Strictly validates executable facts and mappings. An identical idempotency-key retry recovers the same candidate; a changed body conflicts. A candidate does not change any existing trading account or active catalog. Maximum HTTP body 512 KiB; canonical specification maximum 256 KiB.



## OpenAPI

````yaml /partner-platform/openapi.json post /api/partner/venues/{venueId}/instruments
openapi: 3.1.0
info:
  title: trdrs Engine API
  version: 1.1.0
  description: >-
    ## API Reference


    This is the served OpenAPI contract for the trdrs engine: market data,
    trading and account

    routes for your firm's traders, trdrs Connect account-registration handoff,
    and preview

    challenge routes.


    See Quick Start for the first integration path: key setup, market config,
    chart data, Connect

    account registrations, idempotency, stream reconnects, and conformance.


    See Overview and API Standards for the cross-cutting contract rules.
servers:
  - url: https://app.trdrs.co
    description: Production
  - url: /
    description: This engine
security: []
tags:
  - name: Venue platform preview
    description: >-
      Disabled private-preview venue configuration APIs.
      VENUE_CONFIGURATION_ENABLED and a vault are required. Every route
      documented here under /api/partner/ is also served under /api/operator/ to
      a verified owner session, by the same router with a different credential:
      a browser must never hold a venue key, so an operator console reaches the
      identical checks that way rather than through a second copy of this
      surface. Not part of the stable public contract until qualification and
      release; existing partner APIs remain unchanged.
  - name: Market data
    description: >-
      Symbol search and resolution, OHLCV history, quote snapshots, the server
      clock, and the live bar stream. Crypto rides each venue’s public feed;
      futures stream from the caller’s own connected Rithmic account. With none
      connected, futures requests answer 503 `feed_requires_connection`.
  - name: News
    description: >-
      Aggregated market news and the economic calendar, from licensed/open
      sources, keyword-tagged with futures roots at ingest. Platform-wide
      content (nothing per-user), admitted exactly like Market data: a licensed
      origin, a session, or a firm API key. Headlines page by published time,
      scope by instrument root, and stream live over SSE; thumbnails serve
      through the image proxy.
  - name: Trading
    description: >-
      The money surface: entries, exits, replaces, cancels, and position/account
      flattening. Every order-placing call uses `clientOrderId` as its
      idempotency key.
  - name: Account
    description: >-
      Reading a connected account. You do not create trading accounts here: a
      trader connects their own broker account (or creates a free demo account)
      in the app, and firms create evaluation accounts through the Partner API
      (Firm accounts → Create evaluation accounts) or register venue accounts
      through Connect (Create an account registration). Account state and the
      durable ledgers: balances, positions, working orders, fills, P&L history,
      and the live account stream.
  - name: Connect
    description: >-
      trdrs Connect account registration, for partner firms. Register an account
      you issued on your own venue — a pending account registration — with the
      trader’s sign-in email, optionally the venue account id and the login name
      your venue issued. The trader finds it waiting in the connect flow the
      moment they sign in with that email: the connect step is pre-filled with
      everything except the credential, which the trader always enters
      themselves. A registration never transmits a password and never grants
      access to anything before the trader’s own login succeeds. These routes
      answer a partner-scoped key only; a firm API key or a user session gets
      401. Registrations expire after 30 days; re-registering the same email +
      account refreshes the expiry instead of duplicating. The end-to-end flow
      guide is **[Quick Start](/docs/guides/quick-start)**.
  - name: Firm accounts
    description: >-
      Evaluation accounts your firm issues on the trdrs venue, through your
      partner key — the other half of account setup. Connect registrations hand
      off accounts that exist on your venue; these routes create and manage
      accounts on ours: the trader trades them on trdrs, and your firm owns the
      lifecycle. Every route is scoped to accounts your firm created through
      this API — an account the same trader opened themselves is invisible and
      untouchable here, by construction. Creation is batched with per-item
      results, and every write carries your own `referenceId`, so a crashed
      pipeline retries safely. Served when the deployment runs the prop engine;
      without it, every route in this group answers `404`.
  - name: Webhooks
    description: >-
      The outbound event bus: register an https endpoint and the platform pushes
      events to it instead of your back office polling us. Every delivery is
      signed (`trdrs-signature: t=<unix>,v1=<hmac-sha256>` over
      `${t}.${rawBody}`) so you can prove it came from us and is fresh, and
      every delivery is durable — a failed attempt is retried with backoff for
      about nine hours and the whole log is readable, so an endpoint that was
      down is a delay rather than a lost event. Serves brokers and prop firms
      alike: the account-registration (`registration.*`) events fire wherever
      Connect does, and the account events fire where the prop engine runs.
  - name: Challenges
    description: >-
      The prop evaluation surface: challenge programs and a trader’s own
      enrollments. **Preview: the one group on this page outside the
      additive-only guarantee** (the pre-contract v1 scaffold; the Phase-1
      rebuild will change these shapes; see Stability). **Cookie-authenticated,
      not key-authenticated**, and served only when the engine runs with
      `CHALLENGES_ENABLED`; without that flag the bundle is absent and every
      route below returns `404`. The firm-console/admin half of this surface is
      deliberately not documented here. It is back office, not licensed surface.
paths:
  /api/partner/venues/{venueId}/instruments:
    post:
      tags:
        - Venue platform preview
      summary: Save an instrument candidate
      description: >-
        Private preview, disabled unless VENUE_CONFIGURATION_ENABLED is enabled
        and the vault is configured. This branch has not enabled these routes in
        the public sandbox. Existing trdrs_sk partner/tenant keys do not
        authorize these routes. Requires venue:configure. Strictly validates
        executable facts and mappings. An identical idempotency-key retry
        recovers the same candidate; a changed body conflicts. A candidate does
        not change any existing trading account or active catalog. Maximum HTTP
        body 512 KiB; canonical specification maximum 256 KiB.
      parameters:
        - name: venueId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 128
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VenueInstrumentSaveRequest'
      responses:
        '201':
          description: 'Scoped result. Cache-Control: no-store.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VenueInstrumentSaveResponse'
        '400':
          description: Invalid input, cursor or required request/version header.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Required credential missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            Verified identity, current owner membership or required scope
            missing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Disabled feature, unavailable resource or wrong venue/environment.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Changed idempotent request or stale version.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          description: Request exceeds the bounded body size.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: JSON body required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service or credential vault unavailable; no success is implied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - venueOperatorKey: []
      x-codeSamples:
        - lang: javascript
          label: TypeScript
          source: >-
            const res = await
            fetch('https://app.trdrs.co/api/partner/venues/{venueId}/instruments',
            {
              method: 'POST',
              headers: {
                'content-type': 'application/json',
                Authorization: `Bearer ${process.env.TRDRS_VENUE_KEY}`,
                "Idempotency-Key": "example-request-1",
              },
              body: JSON.stringify({
                "specification": {
                  "instrumentId": "BTCUSD",
                  "version": "v1",
                  "venueId": "00000000-0000-0000-0000-000000000001",
                  "symbol": "BTCUSD",
                  "name": "Bitcoin / USD",
                  "productModel": "linear_spot",
                  "quoteCurrency": "USD",
                  "settlementCurrency": "USD",
                  "negativePrices": false,
                  "quantity": {
                    "unit": "base_units",
                    "lotSize": "1",
                    "min": "0.001",
                    "max": "100",
                    "step": "0.001"
                  },
                  "contractMultiplier": "1",
                  "minNotional": "10",
                  "ticks": [
                    {
                      "from": "0",
                      "to": null,
                      "size": "0.01"
                    }
                  ],
                  "orderTypes": [
                    "market",
                    "limit"
                  ],
                  "timeInForce": [
                    "gtc"
                  ],
                  "mappings": [],
                  "sessions": {
                    "timezone": "UTC",
                    "coverageFrom": "2026-01-01",
                    "coverageThrough": "2026-12-31",
                    "weekly": [
                      {
                        "day": 0,
                        "windows": [
                          {
                            "startMinute": 0,
                            "endMinute": 0,
                            "endDayOffset": 1
                          }
                        ]
                      },
                      {
                        "day": 1,
                        "windows": [
                          {
                            "startMinute": 0,
                            "endMinute": 0,
                            "endDayOffset": 1
                          }
                        ]
                      },
                      {
                        "day": 2,
                        "windows": [
                          {
                            "startMinute": 0,
                            "endMinute": 0,
                            "endDayOffset": 1
                          }
                        ]
                      },
                      {
                        "day": 3,
                        "windows": [
                          {
                            "startMinute": 0,
                            "endMinute": 0,
                            "endDayOffset": 1
                          }
                        ]
                      },
                      {
                        "day": 4,
                        "windows": [
                          {
                            "startMinute": 0,
                            "endMinute": 0,
                            "endDayOffset": 1
                          }
                        ]
                      },
                      {
                        "day": 5,
                        "windows": [
                          {
                            "startMinute": 0,
                            "endMinute": 0,
                            "endDayOffset": 1
                          }
                        ]
                      },
                      {
                        "day": 6,
                        "windows": [
                          {
                            "startMinute": 0,
                            "endMinute": 0,
                            "endDayOffset": 1
                          }
                        ]
                      }
                    ],
                    "holidays": []
                  },
                  "expiresAt": null,
                  "lastTradeAt": null,
                  "pricing": {
                    "sourceId": "example-feed",
                    "stopTrigger": "last",
                    "maxAgeMs": 1000
                  },
                  "entitlement": null,
                  "state": "enabled"
                }
              }),
            })

            const data = await res.json()
        - lang: shell
          label: cURL
          source: >-
            curl -X POST
            'https://app.trdrs.co/api/partner/venues/{venueId}/instruments' \
              -H "Authorization: Bearer $TRDRS_VENUE_KEY" \
              -H 'Idempotency-Key: example-request-1' \
              -H 'content-type: application/json' \
              -d '{"specification":{"instrumentId":"BTCUSD","version":"v1","venueId":"00000000-0000-0000-0000-000000000001","symbol":"BTCUSD","name":"Bitcoin / USD","productModel":"linear_spot","quoteCurrency":"USD","settlementCurrency":"USD","negativePrices":false,"quantity":{"unit":"base_units","lotSize":"1","min":"0.001","max":"100","step":"0.001"},"contractMultiplier":"1","minNotional":"10","ticks":[{"from":"0","to":null,"size":"0.01"}],"orderTypes":["market","limit"],"timeInForce":["gtc"],"mappings":[],"sessions":{"timezone":"UTC","coverageFrom":"2026-01-01","coverageThrough":"2026-12-31","weekly":[{"day":0,"windows":[{"startMinute":0,"endMinute":0,"endDayOffset":1}]},{"day":1,"windows":[{"startMinute":0,"endMinute":0,"endDayOffset":1}]},{"day":2,"windows":[{"startMinute":0,"endMinute":0,"endDayOffset":1}]},{"day":3,"windows":[{"startMinute":0,"endMinute":0,"endDayOffset":1}]},{"day":4,"windows":[{"startMinute":0,"endMinute":0,"endDayOffset":1}]},{"day":5,"windows":[{"startMinute":0,"endMinute":0,"endDayOffset":1}]},{"day":6,"windows":[{"startMinute":0,"endMinute":0,"endDayOffset":1}]}],"holidays":[]},"expiresAt":null,"lastTradeAt":null,"pricing":{"sourceId":"example-feed","stopTrigger":"last","maxAgeMs":1000},"entitlement":null,"state":"enabled"}}'
components:
  schemas:
    VenueInstrumentSaveRequest:
      type: object
      additionalProperties: false
      properties:
        specification:
          $ref: '#/components/schemas/VenueInstrumentCandidateSpecification'
      required:
        - specification
      example:
        specification:
          instrumentId: BTCUSD
          version: v1
          venueId: 00000000-0000-0000-0000-000000000001
          symbol: BTCUSD
          name: Bitcoin / USD
          productModel: linear_spot
          quoteCurrency: USD
          settlementCurrency: USD
          negativePrices: false
          quantity:
            unit: base_units
            lotSize: '1'
            min: '0.001'
            max: '100'
            step: '0.001'
          contractMultiplier: '1'
          minNotional: '10'
          ticks:
            - from: '0'
              to: null
              size: '0.01'
          orderTypes:
            - market
            - limit
          timeInForce:
            - gtc
          mappings: []
          sessions:
            timezone: UTC
            coverageFrom: '2026-01-01'
            coverageThrough: '2026-12-31'
            weekly:
              - day: 0
                windows:
                  - startMinute: 0
                    endMinute: 0
                    endDayOffset: 1
              - day: 1
                windows:
                  - startMinute: 0
                    endMinute: 0
                    endDayOffset: 1
              - day: 2
                windows:
                  - startMinute: 0
                    endMinute: 0
                    endDayOffset: 1
              - day: 3
                windows:
                  - startMinute: 0
                    endMinute: 0
                    endDayOffset: 1
              - day: 4
                windows:
                  - startMinute: 0
                    endMinute: 0
                    endDayOffset: 1
              - day: 5
                windows:
                  - startMinute: 0
                    endMinute: 0
                    endDayOffset: 1
              - day: 6
                windows:
                  - startMinute: 0
                    endMinute: 0
                    endDayOffset: 1
            holidays: []
          expiresAt: null
          lastTradeAt: null
          pricing:
            sourceId: example-feed
            stopTrigger: last
            maxAgeMs: 1000
          entitlement: null
          state: enabled
    VenueInstrumentSaveResponse:
      type: object
      additionalProperties: false
      properties:
        instrument:
          $ref: '#/components/schemas/VenueInstrumentCandidate'
      required:
        - instrument
      example:
        instrument:
          id: 00000000-0000-0000-0000-000000000001
          venueId: 00000000-0000-0000-0000-000000000001
          environment: sandbox
          specification:
            instrumentId: BTCUSD
            version: v1
            venueId: 00000000-0000-0000-0000-000000000001
            symbol: BTCUSD
            name: Bitcoin / USD
            productModel: linear_spot
            quoteCurrency: USD
            settlementCurrency: USD
            negativePrices: false
            quantity:
              unit: base_units
              lotSize: '1'
              min: '0.001'
              max: '100'
              step: '0.001'
            contractMultiplier: '1'
            minNotional: '10'
            ticks:
              - from: '0'
                to: null
                size: '0.01'
            orderTypes:
              - market
              - limit
            timeInForce:
              - gtc
            mappings: []
            sessions:
              timezone: UTC
              coverageFrom: '2026-01-01'
              coverageThrough: '2026-12-31'
              weekly:
                - day: 0
                  windows:
                    - startMinute: 0
                      endMinute: 0
                      endDayOffset: 1
                - day: 1
                  windows:
                    - startMinute: 0
                      endMinute: 0
                      endDayOffset: 1
                - day: 2
                  windows:
                    - startMinute: 0
                      endMinute: 0
                      endDayOffset: 1
                - day: 3
                  windows:
                    - startMinute: 0
                      endMinute: 0
                      endDayOffset: 1
                - day: 4
                  windows:
                    - startMinute: 0
                      endMinute: 0
                      endDayOffset: 1
                - day: 5
                  windows:
                    - startMinute: 0
                      endMinute: 0
                      endDayOffset: 1
                - day: 6
                  windows:
                    - startMinute: 0
                      endMinute: 0
                      endDayOffset: 1
              holidays: []
            expiresAt: null
            lastTradeAt: null
            pricing:
              sourceId: example-feed
              stopTrigger: last
              maxAgeMs: 1000
            entitlement: null
            state: enabled
          contentHash: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
          createdAt: '2026-09-14T12:00:00.000Z'
          state: candidate
          tradingReady: false
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
      required:
        - error
      example:
        error: invalid_instrument
    VenueInstrumentCandidateSpecification:
      type: object
      additionalProperties: false
      properties:
        instrumentId:
          type: string
        version:
          type: string
        venueId:
          type: string
          format: uuid
        symbol:
          type: string
        name:
          type: string
        productModel:
          type: string
          enum:
            - linear_spot
            - linear_future
            - linear_perpetual
            - linear_cfd
        quoteCurrency:
          type: string
        settlementCurrency:
          type: string
        negativePrices:
          type: boolean
        quantity:
          type: object
          additionalProperties: false
          properties:
            unit:
              type: string
              enum:
                - contracts
                - base_units
                - lots
            lotSize:
              type: string
              description: >-
                Exact base-ten decimal string, at most 18 fractional digits. No
                exponent notation or binary floating-point conversion.
            min:
              type: string
              description: >-
                Exact base-ten decimal string, at most 18 fractional digits. No
                exponent notation or binary floating-point conversion.
            max:
              type: string
              description: >-
                Exact base-ten decimal string, at most 18 fractional digits. No
                exponent notation or binary floating-point conversion.
            step:
              type: string
              description: >-
                Exact base-ten decimal string, at most 18 fractional digits. No
                exponent notation or binary floating-point conversion.
          required:
            - unit
            - lotSize
            - min
            - max
            - step
        contractMultiplier:
          type: string
          description: >-
            Exact base-ten decimal string, at most 18 fractional digits. No
            exponent notation or binary floating-point conversion.
        minNotional:
          type: string
          description: >-
            Exact base-ten decimal string, at most 18 fractional digits. No
            exponent notation or binary floating-point conversion.
        ticks:
          type: array
          items:
            type: object
            additionalProperties: false
            properties:
              from:
                type:
                  - string
                  - 'null'
                description: >-
                  Exact base-ten decimal string, at most 18 fractional digits.
                  No exponent notation or binary floating-point conversion.
              to:
                type:
                  - string
                  - 'null'
                description: >-
                  Exact base-ten decimal string, at most 18 fractional digits.
                  No exponent notation or binary floating-point conversion.
              size:
                type: string
                description: >-
                  Exact base-ten decimal string, at most 18 fractional digits.
                  No exponent notation or binary floating-point conversion.
            required:
              - from
              - to
              - size
        orderTypes:
          type: array
          items:
            type: string
            enum:
              - market
              - limit
              - stop
              - stop_limit
        timeInForce:
          type: array
          items:
            type: string
            enum:
              - day
              - gtc
              - ioc
              - fok
              - post_only
        mappings:
          type: array
          items:
            type: object
            additionalProperties: false
            properties:
              connectionId:
                type: string
                format: uuid
              providerSymbol:
                type: string
            required:
              - connectionId
              - providerSymbol
        sessions:
          type: object
          additionalProperties: false
          properties:
            timezone:
              type: string
            coverageFrom:
              type: string
              format: date
            coverageThrough:
              type: string
              format: date
            weekly:
              type: array
              items:
                type: object
                additionalProperties: false
                properties:
                  day:
                    type: integer
                    minimum: 0
                    maximum: 6
                  windows:
                    type: array
                    items:
                      type: object
                      additionalProperties: false
                      properties:
                        startMinute:
                          type: integer
                          minimum: 0
                          maximum: 1439
                        endMinute:
                          type: integer
                          minimum: 0
                          maximum: 1439
                        endDayOffset:
                          type: integer
                          enum:
                            - 0
                            - 1
                      required:
                        - startMinute
                        - endMinute
                        - endDayOffset
                required:
                  - day
                  - windows
            holidays:
              type: array
              items:
                type: object
                additionalProperties: false
                properties:
                  date:
                    type: string
                    format: date
                  windows:
                    type: array
                    items:
                      type: object
                      additionalProperties: false
                      properties:
                        startMinute:
                          type: integer
                          minimum: 0
                          maximum: 1439
                        endMinute:
                          type: integer
                          minimum: 0
                          maximum: 1439
                        endDayOffset:
                          type: integer
                          enum:
                            - 0
                            - 1
                      required:
                        - startMinute
                        - endMinute
                        - endDayOffset
                required:
                  - date
                  - windows
          required:
            - timezone
            - coverageFrom
            - coverageThrough
            - weekly
            - holidays
        expiresAt:
          type:
            - string
            - 'null'
          format: date-time
        lastTradeAt:
          type:
            - string
            - 'null'
          format: date-time
        pricing:
          type: object
          additionalProperties: false
          properties:
            sourceId:
              type: string
            stopTrigger:
              type: string
              enum:
                - last
                - mark
                - bid_ask
            maxAgeMs:
              type: integer
              minimum: 1
              maximum: 2000
          required:
            - sourceId
            - stopTrigger
            - maxAgeMs
        entitlement:
          type:
            - string
            - 'null'
        state:
          type: string
          enum:
            - enabled
            - disabled
      required:
        - instrumentId
        - version
        - venueId
        - symbol
        - name
        - productModel
        - quoteCurrency
        - settlementCurrency
        - negativePrices
        - quantity
        - contractMultiplier
        - minNotional
        - ticks
        - orderTypes
        - timeInForce
        - mappings
        - sessions
        - expiresAt
        - lastTradeAt
        - pricing
        - entitlement
        - state
      description: >-
        Immutable candidate only. No activation or execution admission. Quote
        and settlement currencies must match. Futures use contracts and require
        expiry/last-trade timestamps; spot uses base units. Quantity bounds must
        be step-aligned; non-lot lotSize is 1. Multiplier is 1 for base units
        and equals lotSize for lots. Tick bands are contiguous, zero-anchored
        and cover the full permitted price domain; null bounds mean infinity.
        Negative prices require futures. Weekly calendar includes all seven
        distinct days; holidays replace windows on their local opening date,
        including overnight windows. Overlapping windows and
        ambiguous/nonexistent daylight-saving boundaries are refused. Calendar
        coverage must be explicit. Mappings must belong to this venue and
        environment. The strict parser enforces cross-field rules beyond this
        structural schema.
    VenueInstrumentCandidate:
      type: object
      additionalProperties: false
      properties:
        id:
          type: string
          format: uuid
        venueId:
          type: string
          format: uuid
        environment:
          type: string
          enum:
            - sandbox
            - production
        specification:
          $ref: '#/components/schemas/VenueInstrumentCandidateSpecification'
        contentHash:
          type: string
        createdAt:
          type: string
          format: date-time
        state:
          const: candidate
        tradingReady:
          const: false
      required:
        - id
        - venueId
        - environment
        - specification
        - contentHash
        - createdAt
        - state
        - tradingReady
  securitySchemes:
    venueOperatorKey:
      type: http
      scheme: bearer
      description: >-
        Private-preview venue operator key (trdrs_vk_sandbox_… or
        trdrs_vk_production_…). Bound to one venue/environment and explicit
        scopes. Issued by a verified owner session; accepted only on documented
        /api/partner/venues/{venueId} routes. Existing trdrs_sk keys are not
        interchangeable. Never grants trader, login or key-management authority.

````