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

> ## Agent Instructions
> Prices are US dollars per contract that pays $1: 0.46 means 46 cents. Spread is the Yes ask plus the No ask minus $1. Liquidity grades are deep, tradeable and thin; lists hide thin markets unless include_thin=true. Relations are proven from contract terms, never inferred from wording; a lead marked informational is never executable. Every figure carries a graph_run; read /agents/reading-order first, then /concepts/relations and /concepts/liquidity.

# Compare a chosen purchase against a cross-venue contract

> Account-independent whole-share estimates using current depth, live Kalshi event/series fee overrides, and captured Polymarket fee schedules. Missing, stale, disconnected or limited recorded books trigger bounded public venue reads (four seconds per contract, up to 500 levels). A failed refresh remains unavailable; no stale quote is promoted. Automated settlement assessments bind full source versions. USD/USDC estimates assume parity and funded balances with exclusions in pricing. Missing evidence, unsupported assets, unknown fees and stale or incomplete books prevent a savings recommendation. No order or account is created. Responses are never cached.



## OpenAPI

````yaml /openapi.yaml get /v1/markets/{venue}/{id}/comparison
openapi: 3.1.0
info:
  title: Routeur Graph API
  version: '2026-09-15'
  summary: >-
    Proven relations between Kalshi and Polymarket contracts, with the history
    and signals built on them.
  description: >
    Routeur reads every open market on Kalshi and global Polymarket, and proves

    which ones imply, exclude or equal each other from each venue's structured

    contract terms and exact arithmetic. No relation is inferred from prose, and

    ambiguous or conflicting evidence is withheld.


    ## Authentication

    Send your key in the `X-API-Key` header, or as `Authorization: Bearer
    <key>`.

    Keys look like `rk_live_<12-character id>_<43-character secret>` and are

    shown once when issued. Keep them server-side. One endpoint needs no key:

    `/v1/accuracy`, the public record of how often proven relations held when

    their markets settled.


    ## Rate limits

    Every key has a per-minute limit and a per-day quota set by its tier:


    | Tier | Requests per minute | Requests per day |

    |---|---|---|

    | free | 30 | 2,000 |

    | trader | 120 | 50,000 |

    | pro | 600 | 500,000 |

    | institutional | 3,000 | 10,000,000 |


    Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` and

    `X-RateLimit-Reset` (Unix seconds) for the minute window, and

    `X-Daily-Quota-Limit` and `X-Daily-Quota-Remaining` for the day (UTC).

    A request over either limit returns `429` with `Retry-After` in seconds.


    ## Conventions

    - Money and prices are decimal strings in USD (for example `"0.4100"`),
    never
      floats. Prices are per contract that pays $1.
    - Times are RFC 3339 in UTC.

    - Successful responses wrap results in `data`. Graph-derived responses also
      name the `graph_run` they were read from; runs finish hourly.
    - Paginated lists return `next_cursor` when more results exist. Pass it back
      as `cursor` unchanged; cursors are opaque.
    - Unknown or repeated query parameters are rejected with `400`, so typos
    never
      silently widen a query.

    ## Liquidity

    Every object that names a market carries its 24-hour volume, its spread and

    a `liquidity` grade, because a price nobody can trade at is not a price:


    | Grade | 24-hour volume or open interest | Round-trip spread |

    |---|---|---|

    | `deep` | $25,000 traded, or $250,000 open interest | 2¢ or less |

    | `tradeable` | $1,000 traded, or $25,000 open interest | 5¢ or less |

    | `thin` | anything less, or no quoted round trip | |


    Lists that suggest something to act on — price gaps, leads, movers, flows,

    large fills, closing soon, strategy matches — leave thin markets out by

    default, and rank what is left by the money behind it. Three parameters

    change that wherever it applies: `min_volume_usd`, `max_spread_usd` and

    `include_thin=true`, which drops both floors. Search and event listings show

    thin markets but rank them below what can be traded.


    ## Errors

    Errors return a JSON body `{"error": {"code": "...", "message": "..."}}`.

    Branch on `code`; messages may change.


    | Status | Code | Meaning |

    |---|---|---|

    | 400 | `invalid_parameter` | A query parameter is unknown, repeated or out
    of range. |

    | 400 | `invalid_market` | The venue is not `kalshi` or `polymarket`, or the
    market id is malformed. |

    | 400 | `invalid_rulebook` | The venue, rulebook kind or id is malformed. |

    | 400 | `invalid_event` | The venue is not `kalshi` or `polymarket`, or the
    event id is malformed. |

    | 400 | `invalid_topic` | The topic name is malformed; use lowercase words
    joined by dashes. |

    | 401 | `api_key_required` | No key was sent. |

    | 401 | `invalid_api_key` | The key is malformed or unknown. |

    | 401 | `api_key_revoked` | The key was revoked. |

    | 401 | `invalid_token` | The bearer credential is not an API key and is not
    a valid service identity token. |

    | 403 | `caller_not_allowed` | The service identity token is valid but its
    identity may not call the API. |

    | 404 | `market_not_found` | The market is not in the latest graph. |

    | 404 | `event_not_found` | The event is not in the latest graph. |

    | 404 | `topic_not_found` | No listed markets are labeled with that topic. |

    | 404 | `strategy_not_found` | No strategy with that id is supported by
    settled history right now. |

    | 404 | `relation_not_found` | Both markets are listed, but no current proof
    relates them. |

    | 404 | `rulebook_not_found` | No such rulebook has been recorded. |

    | 404 | `book_not_found` | No order book is recorded for the market at that
    time. |

    | 404 | `not_found` | No such endpoint. |

    | 429 | `rate_limited` | The per-minute limit was exceeded. |

    | 429 | `daily_quota_exceeded` | The daily quota is used up. |

    | 429 | `too_many_streams` | The key already holds its concurrent live
    streams. |

    | 503 | `graph_unavailable` | No graph run has finished yet. |

    | 503 | `database_unavailable` | The database is not reachable; the
    readiness check answers this while it is down. |

    | 503 | `stream_unavailable` | No live stream capacity is free; retry
    shortly. |

    | 504 | `timeout` | The request took longer than 15 seconds. |

    | 500 | `internal` | Something failed on our side. |


    ## Webhooks

    Mispricing alerts are delivered as signed `POST` requests; see the

    `webhooks` section. Each request carries

    `Routeur-Signature: t=<unix seconds>,v1=<hex>`, where `v1` is

    HMAC-SHA256 of `<t>.<raw body>` keyed by your subscription's signing

    secret. Reject requests whose signature does not match or whose `t` is more

    than five minutes old, and respond `2xx` within 10 seconds.


    `Routeur-Delivery` identifies the delivery and stays the same across
    retries,

    so use it to ignore duplicates. Any response other than `2xx` or `410`, or
    no

    response, is retried with exponential backoff from 30 seconds for up to 8

    attempts; responding `410 Gone` disables the subscription. Endpoints must be

    HTTPS on a public address, and redirects are not followed.
  contact:
    name: Routeur
    url: https://routeur.app
servers:
  - url: https://api.routeur.app
security:
  - apiKey: []
  - bearer: []
tags:
  - name: Events
    description: Real-world events across both venues, the way people browse them.
  - name: Graph
    description: Markets and the relations proven between them.
  - name: History
    description: Recorded quotes and trades.
  - name: Rules
    description: |
      Contract terms and their history. Every version of every market's rule
      text is kept from the day it was first seen, along with the rulebooks
      above it (Kalshi series and event terms, Polymarket resolution metadata)
      and the venue's contract terms documents, with diffs between versions.
  - name: Books
    description: >-
      Order books recorded live from each venue's feed, their history, and the
      health of the feeds.
  - name: Signals
    description: Mispricing leads and unusual trading derived from the graph and history.
  - name: Live
    description: Quotes, trades, relations and leads pushed as they happen.
  - name: Service
    description: Service status and this document.
paths:
  /v1/markets/{venue}/{id}/comparison:
    get:
      summary: Compare a chosen purchase against a cross-venue contract
      description: >-
        Account-independent whole-share estimates using current depth, live
        Kalshi event/series fee overrides, and captured Polymarket fee
        schedules. Missing, stale, disconnected or limited recorded books
        trigger bounded public venue reads (four seconds per contract, up to 500
        levels). A failed refresh remains unavailable; no stale quote is
        promoted. Automated settlement assessments bind full source versions.
        USD/USDC estimates assume parity and funded balances with exclusions in
        pricing. Missing evidence, unsupported assets, unknown fees and stale or
        incomplete books prevent a savings recommendation. No order or account
        is created. Responses are never cached.
      operationId: purchaseComparison
      parameters:
        - in: path
          name: venue
          required: true
          schema:
            type: string
            enum:
              - kalshi
              - polymarket
        - in: path
          name: id
          required: true
          schema:
            type: string
        - in: query
          name: side
          required: true
          schema:
            type: string
            enum:
              - 'yes'
              - 'no'
        - in: query
          name: unit
          required: true
          schema:
            type: string
            enum:
              - usd
              - shares
        - in: query
          name: amount
          required: true
          schema:
            type: string
        - in: query
          name: counterpart
          schema:
            type: string
          description: >-
            A venue:market_id from the returned candidate list; defaults to the
            strongest graph relation.
      responses:
        '200':
          description: >-
            Conditional purchase comparison, automated settlement findings and
            quote quality, with explicit assumptions and blocking reasons.
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/PurchaseComparison'
        '400':
          description: Invalid comparison input
        '401':
          description: Authentication required
        '403':
          description: Caller not allowed
        '404':
          description: Market not found
        '429':
          description: Rate limit reached
        '503':
          description: Data unavailable
components:
  schemas:
    PurchaseComparison:
      type: object
      required:
        - input
        - assessment
        - options
        - best
        - reasons
        - compared_at
        - candidates
        - pricing
      properties:
        input:
          type: object
          required:
            - side
            - unit
            - amount
          properties:
            side:
              type: string
              enum:
                - 'yes'
                - 'no'
            unit:
              type: string
              enum:
                - usd
                - shares
            amount:
              type: string
        assessment:
          type: object
          required:
            - outcome
            - settlement
            - evidence
            - mapping
            - summary
          properties:
            outcome:
              type: string
              description: Ordinary graph relation or an automated model assessment.
            settlement:
              type: string
              enum:
                - unknown
                - compatible
                - different
            evidence:
              type: string
              enum:
                - pending
                - incomplete
                - stale
                - current
                - inconclusive
            mapping:
              type: string
              enum:
                - unconfirmed
                - same
                - opposite
            summary:
              type: string
            differences:
              type: array
              description: >-
                Current source-validated settlement consequences. May be present
                while other terms remain unknown; never establishes
                interchangeable payouts.
              items:
                $ref: '#/components/schemas/PurchaseFinding'
            receipt:
              $ref: '#/components/schemas/PurchaseReceipt'
        options:
          type: array
          maxItems: 2
          items:
            type: object
            required:
              - contract
              - quote
            properties:
              contract:
                $ref: '#/components/schemas/PurchaseContract'
              quote:
                $ref: '#/components/schemas/PurchaseQuote'
        best:
          type:
            - integer
            - 'null'
          minimum: 0
          maximum: 1
          description: >-
            Index of the qualified better estimate; null for ties or any
            unresolved eligibility condition.
        advantage:
          type: string
          description: >-
            Absolute USD trading-cost difference for shares; additional whole
            shares for a dollar budget. Subject to pricing assumptions.
        pricing:
          type: object
          required:
            - kind
            - currency
            - assumptions
            - excluded
          properties:
            kind:
              type: string
              enum:
                - trading_cost
                - conditional_at_par
            currency:
              type: string
              enum:
                - USD
            assumptions:
              type: array
              items:
                type: string
            excluded:
              type: array
              items:
                type: string
        reasons:
          type: array
          items:
            type: string
        compared_at:
          type: string
          format: date-time
        candidates:
          type: array
          items:
            $ref: '#/components/schemas/Relation'
    PurchaseFinding:
      type: object
      required:
        - topic
        - result
        - explanation
        - citations
      properties:
        topic:
          type: string
        result:
          type: string
          enum:
            - agree
            - different
            - unknown
        explanation:
          type: string
        citations:
          type: array
          items:
            type: object
            required:
              - contract
              - source_id
              - quote
            properties:
              contract:
                type: integer
                minimum: 0
                maximum: 1
              source_id:
                type: string
              quote:
                type: string
                description: Exact substring of the named captured source.
    PurchaseReceipt:
      type: object
      required:
        - id
        - model
        - policy
        - status
        - challenge
        - assessed_at
        - expires_at
        - left_hash
        - right_hash
        - mapping
        - scope
        - findings
      properties:
        id:
          type: string
        model:
          type: string
        policy:
          type: string
        status:
          type: string
          enum:
            - complete
            - inconclusive
        reason:
          type: string
        challenge:
          type: string
        assessed_at:
          type: string
          format: date-time
        expires_at:
          type: string
          format: date-time
        left_hash:
          type: string
        right_hash:
          type: string
        mapping:
          type: string
          enum:
            - same
            - opposite
            - unconfirmed
        scope:
          type: string
        findings:
          type: array
          items:
            $ref: '#/components/schemas/PurchaseFinding'
    PurchaseContract:
      type: object
      required:
        - venue
        - id
        - title
        - yes_label
        - no_label
        - rules_hash
        - evidence_hash
        - sources
        - evidence_issues
        - currency
        - payout
      properties:
        venue:
          type: string
          enum:
            - kalshi
            - polymarket
        id:
          type: string
        title:
          type: string
        yes_label:
          type: string
        no_label:
          type: string
        rules_hash:
          type: string
        evidence_hash:
          type: string
          description: >-
            SHA-256 of contract identity and full captured source versions and
            texts.
        currency:
          type: string
        payout:
          type: string
        evidence_issues:
          type: array
          items:
            type: string
        sources:
          type: array
          items:
            type: object
            required:
              - id
              - version
              - text
            properties:
              id:
                type: string
              version:
                type: string
              text:
                type: string
                description: Complete captured text; never silently truncated.
              url:
                type: string
    PurchaseQuote:
      type: object
      required:
        - side
        - quantity
        - principal
        - fee
        - total
        - unfilled
        - as_of
        - valid_until
        - status
        - issues
        - account
      properties:
        side:
          type: string
          enum:
            - 'yes'
            - 'no'
        quantity:
          type: string
        principal:
          type: string
        fee:
          type:
            - string
            - 'null'
          description: Null when unknown; never silently zero.
        total:
          type:
            - string
            - 'null'
          description: Principal plus known taker fees; null when fees are unknown.
        unfilled:
          type: string
          description: Unfilled requested shares; zero for budget mode.
        worst_price:
          type: string
        as_of:
          type: string
          format: date-time
        valid_until:
          type: string
          format: date-time
        status:
          type: string
          enum:
            - current
            - limited
            - unavailable
        issues:
          type: array
          items:
            type: string
        account:
          type: string
          enum:
            - not_checked
          description: >-
            Authenticated funding and eligibility checks occur separately in the
            order ticket.
    Relation:
      type: object
      additionalProperties: false
      required:
        - relation
        - cross_venue
        - evidence
        - market
      properties:
        relation:
          $ref: '#/components/schemas/RelationFromMarket'
        cross_venue:
          type: boolean
        evidence:
          type: array
          description: The structured facts the proof used.
          items:
            type: string
        market:
          $ref: '#/components/schemas/Market'
    RelationFromMarket:
      type: string
      description: |
        A relation from the requested market's side. `implies`: if this market
        resolves Yes, the other does. `implied_by`: the reverse. `contradicts`:
        both cannot resolve Yes. `overlaps`: the outcome sets intersect without
        containment.
      enum:
        - equivalent
        - implies
        - implied_by
        - contradicts
        - overlaps
    Market:
      type: object
      additionalProperties: false
      required:
        - venue
        - id
        - event_id
        - title
        - yes_label
        - no_label
        - event_mutually_exclusive
        - relations
        - volume_24h_usd
        - trades_24h
        - liquidity
      properties:
        venue:
          $ref: '#/components/schemas/Venue'
        id:
          $ref: '#/components/schemas/MarketID'
        event_id:
          type: string
        title:
          type: string
        yes_label:
          type: string
        no_label:
          type: string
        category:
          type: string
        strike:
          $ref: '#/components/schemas/Strike'
        event_mutually_exclusive:
          type: boolean
          description: At most one market in the event can resolve Yes.
        game_starts_at:
          $ref: '#/components/schemas/Timestamp'
        quote:
          $ref: '#/components/schemas/Quote'
        relations:
          $ref: '#/components/schemas/RelationCounts'
        volume_24h_usd:
          $ref: '#/components/schemas/Decimal'
          description: >
            Traded in the last 24 hours, in USD. The venue's own figure where it

            publishes one (Kalshi counts contracts at their $1 face value, as
            its own

            site does; Polymarket reports USDC notional), otherwise the notional
            of

            the fills this platform recorded. `volume_source` says which.
        volume_source:
          type: string
          enum:
            - venue
            - trades
          description: Where `volume_24h_usd` comes from.
        total_volume_usd:
          $ref: '#/components/schemas/Decimal'
          description: Traded over the market's life, where the venue reports it.
        open_interest_usd:
          $ref: '#/components/schemas/Decimal'
          description: Contracts currently held, at face value. Kalshi only.
        spread_usd:
          $ref: '#/components/schemas/Decimal'
          description: >-
            The round trip: the Yes ask plus the No ask less the $1 a winning
            contract pays. Absent when a side has no ask.
        yes_spread_usd:
          $ref: '#/components/schemas/Decimal'
          description: The Yes ask less the Yes bid, where the venue publishes a bid.
        no_spread_usd:
          $ref: '#/components/schemas/Decimal'
          description: The No ask less the No bid.
        trades_24h:
          type: integer
          description: Fills recorded in the last 24 hours.
        liquidity:
          $ref: '#/components/schemas/LiquidityGrade'
        book_spread_usd:
          $ref: '#/components/schemas/Decimal'
          description: >-
            From the recorded order book: the best Yes ask less the best Yes
            bid. Present for markets whose book is recorded.
        book_yes_depth_5c_usd:
          $ref: '#/components/schemas/Decimal'
          description: >-
            USD resting to buy Yes within 5 cents of the best Yes bid, from the
            recorded book.
        book_no_depth_5c_usd:
          $ref: '#/components/schemas/Decimal'
          description: >-
            USD resting to buy No within 5 cents of the best No bid (that is, to
            sell Yes), from the recorded book.
        book_imbalance:
          $ref: '#/components/schemas/Decimal'
          description: >-
            (Yes depth − No depth) / (Yes depth + No depth) over the 5-cent
            windows, from −1 to 1.
        book_at:
          $ref: '#/components/schemas/Timestamp'
          description: When the recorded book last changed.
    Venue:
      type: string
      enum:
        - kalshi
        - polymarket
    MarketID:
      type: string
      pattern: ^[A-Za-z0-9][A-Za-z0-9_.-]{0,199}$
    Strike:
      type: object
      description: >-
        The market's payoff condition as a structured range on its underlying
        quantity.
      additionalProperties: false
      required:
        - type
        - rules_template_hash
      properties:
        type:
          type: string
          description: The venue's strike type, such as `greater`, `less` or `between`.
        floor:
          type: string
          description: Lower bound as an exact rational, such as `83/2`.
        cap:
          type: string
          description: Upper bound as an exact rational.
        custom:
          type: object
          additionalProperties:
            type: string
        functional:
          type: boolean
        rules_template_hash:
          type: string
          description: >-
            Fingerprint of the rules with bounds masked; markets compare only
            within one template.
    Timestamp:
      type: string
      format: date-time
    Quote:
      type: object
      additionalProperties: false
      required:
        - observed_at
      properties:
        yes_ask_usd:
          $ref: '#/components/schemas/Decimal'
        no_ask_usd:
          $ref: '#/components/schemas/Decimal'
        yes_bid_usd:
          $ref: '#/components/schemas/Decimal'
          description: The best resting Yes bid. Only the latest quote carries bids.
        no_bid_usd:
          $ref: '#/components/schemas/Decimal'
          description: The best resting No bid.
        observed_at:
          $ref: '#/components/schemas/Timestamp'
        price_usd:
          $ref: '#/components/schemas/Decimal'
          description: >-
            On history from before quotes were recorded: the closing Yes price
            of the hour or day. Such points carry no asks.
        source:
          type: string
          enum:
            - venue
            - archive
          description: >-
            Where a price_usd point comes from: the venue's own archive, or
            imported history.
    RelationCounts:
      type: object
      additionalProperties: false
      required:
        - implies
        - implied_by
        - equivalent
        - contradicts
        - overlaps
        - cross_venue
      properties:
        implies:
          type: integer
        implied_by:
          type: integer
        equivalent:
          type: integer
        contradicts:
          type: integer
        overlaps:
          type: integer
        cross_venue:
          type: integer
          description: Relations of any kind to the other venue.
    Decimal:
      type: string
      description: An exact decimal number.
      pattern: ^-?[0-9]+(\.[0-9]+)?$
      example: '0.4100'
    LiquidityGrade:
      type: string
      description: |
        How tradeable a market is. `deep`: at least $25,000 traded in 24 hours
        or $250,000 of open interest, with a round trip of 2¢ or less.
        `tradeable`: at least $1,000 traded or $25,000 of open interest, with a
        round trip of 5¢ or less. `thin`: anything less, or no quoted round
        trip. Lists of suggestions leave thin markets out unless asked.
      enum:
        - deep
        - tradeable
        - thin
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
    bearer:
      type: http
      scheme: bearer
      description: The same API key sent as a Bearer token.

````