> ## 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.

# Search events

> Finds events for free text and never comes back empty. Results come in
order of how they were found, each labeled with `match`:

- `match`: every word matched in a title, outcome or category, allowing
  common shorthand (dems, gop, btc, fed) and the last word as a prefix
  so results follow typing; or the query names a person, team, place or
  subject a market is labeled with, however its title is worded.
- `similar`: some of the words matched, a title is close in spelling, or
  the market means close to the same thing.
- `related`: trending in the category the query is about, named in
  `related_category`.
- `trending`: trending anywhere, most traded first.

Misspelled words are replaced by the closest word listings use, shown
in `corrected_query`. An empty `q` lists what is trending. Pages go up
to 300 results; pass `next_offset` as `offset` for the next page.

Plain language in the query narrows the search: "dem senate races
closing this month under 30c" filters to markets closing within a
month whose leading outcome costs under 30¢, and searches for "dem
senate races". Also understood: a venue name, "on both venues",
"longshots", "coin flips", "favorites", "movers", "closing
today/this week/this month", "over $50k traded". What was understood
comes back in `filters`, and `query` is what was searched for. The
same filters can be set as parameters, which win over the query. With
filters on, results can be empty: they are what you asked for.




## OpenAPI

````yaml /openapi.yaml get /v1/search
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.


    ## 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.

    ## 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. |

    | 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. |

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

    | 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. |

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

    | 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: Signals
    description: Mispricing leads and unusual trading derived from the graph and history.
  - name: Service
    description: Service status and this document.
paths:
  /v1/search:
    get:
      tags:
        - Events
      summary: Search events
      description: |
        Finds events for free text and never comes back empty. Results come in
        order of how they were found, each labeled with `match`:

        - `match`: every word matched in a title, outcome or category, allowing
          common shorthand (dems, gop, btc, fed) and the last word as a prefix
          so results follow typing; or the query names a person, team, place or
          subject a market is labeled with, however its title is worded.
        - `similar`: some of the words matched, a title is close in spelling, or
          the market means close to the same thing.
        - `related`: trending in the category the query is about, named in
          `related_category`.
        - `trending`: trending anywhere, most traded first.

        Misspelled words are replaced by the closest word listings use, shown
        in `corrected_query`. An empty `q` lists what is trending. Pages go up
        to 300 results; pass `next_offset` as `offset` for the next page.

        Plain language in the query narrows the search: "dem senate races
        closing this month under 30c" filters to markets closing within a
        month whose leading outcome costs under 30¢, and searches for "dem
        senate races". Also understood: a venue name, "on both venues",
        "longshots", "coin flips", "favorites", "movers", "closing
        today/this week/this month", "over $50k traded". What was understood
        comes back in `filters`, and `query` is what was searched for. The
        same filters can be set as parameters, which win over the query. With
        filters on, results can be empty: they are what you asked for.
      operationId: searchEvents
      parameters:
        - name: q
          in: query
          description: What to look for, in plain language. Empty lists what is trending.
          schema:
            type: string
            maxLength: 200
          example: democrats senate
        - name: limit
          in: query
          description: Results per page.
          schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 20
        - name: offset
          in: query
          description: Pass the previous response's `next_offset`.
          schema:
            type: integer
            minimum: 0
            maximum: 300
            default: 0
        - name: venue
          in: query
          description: Only events on this venue. Wins over a venue named in `q`.
          schema:
            $ref: '#/components/schemas/Venue'
        - name: category
          in: query
          description: Only events in this category.
          schema:
            $ref: '#/components/schemas/CategoryName'
        - name: cross_venue
          in: query
          description: Only events listed on both venues.
          schema:
            type: boolean
            default: false
        - name: closing
          in: query
          description: Days ahead an event must close within.
          schema:
            type: integer
            enum:
              - 1
              - 7
              - 30
        - name: price_min
          in: query
          description: Cheapest the leading outcome's Yes price may be, in cents.
          schema:
            type: integer
            minimum: 0
            maximum: 100
        - name: price_max
          in: query
          description: Dearest the leading outcome's Yes price may be, in cents.
          schema:
            type: integer
            minimum: 0
            maximum: 100
        - name: min_volume
          in: query
          description: Least traded in the last 24 hours, in USD.
          schema:
            type: integer
            minimum: 0
        - name: moved
          in: query
          description: Only events whose leading outcome moved 5 cents or more today.
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: A page of results.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-Daily-Quota-Limit:
              $ref: '#/components/headers/X-Daily-Quota-Limit'
            X-Daily-Quota-Remaining:
              $ref: '#/components/headers/X-Daily-Quota-Remaining'
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                required:
                  - data
                  - graph_run
                  - filters
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: false
                      required:
                        - match
                        - event
                      properties:
                        match:
                          type: string
                          enum:
                            - match
                            - similar
                            - related
                            - trending
                        event:
                          $ref: '#/components/schemas/Event'
                  graph_run:
                    $ref: '#/components/schemas/GraphRunID'
                  next_offset:
                    type: integer
                    minimum: 1
                  query:
                    type: string
                    description: What was searched for once filters were taken out of it.
                  corrected_query:
                    type: string
                  related_category:
                    $ref: '#/components/schemas/CategoryName'
                  filters:
                    type: array
                    description: The filters in force, to show and to remove.
                    items:
                      type: object
                      additionalProperties: false
                      required:
                        - kind
                        - label
                        - value
                      properties:
                        kind:
                          type: string
                          enum:
                            - venue
                            - cross_venue
                            - category
                            - closing
                            - price
                            - volume
                            - moved
                        label:
                          type: string
                        value:
                          type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/Unavailable'
        default:
          $ref: '#/components/responses/Error'
components:
  schemas:
    Venue:
      type: string
      enum:
        - kalshi
        - polymarket
    CategoryName:
      type: string
      enum:
        - Sports
        - Politics
        - Economics
        - Crypto
        - Culture
        - Tech & Science
        - Weather
        - World
        - Other
    Event:
      type: object
      additionalProperties: false
      required:
        - venue
        - id
        - title
        - category
        - venues
        - markets
        - mutually_exclusive
        - volume_24h_usd
        - outcomes
      properties:
        venue:
          $ref: '#/components/schemas/Venue'
        id:
          $ref: '#/components/schemas/MarketID'
        title:
          type: string
        image_url:
          type: string
          format: uri
          description: The venue's artwork for the event, on the venue's own image host.
        category:
          $ref: '#/components/schemas/CategoryName'
        venues:
          type: array
          items:
            $ref: '#/components/schemas/Venue'
        twin:
          type: object
          description: The same event on the other venue.
          additionalProperties: false
          required:
            - venue
            - id
          properties:
            venue:
              $ref: '#/components/schemas/Venue'
            id:
              $ref: '#/components/schemas/MarketID'
        markets:
          type: integer
        mutually_exclusive:
          type: boolean
          description: At most one outcome can happen.
        starts_at:
          $ref: '#/components/schemas/Timestamp'
        closes_at:
          $ref: '#/components/schemas/Timestamp'
        volume_24h_usd:
          $ref: '#/components/schemas/Decimal'
          description: Traded in the last 24 hours on every venue listing the event.
        outcomes:
          type: array
          items:
            $ref: '#/components/schemas/Outcome'
        summary:
          type: string
          description: One line on what decides the event, from labeling.
        topics:
          type: array
          items:
            type: string
          description: Names the event is about; each opens a topic page.
    GraphRunID:
      type: integer
      description: The graph run the response was read from.
      minimum: 1
    MarketID:
      type: string
      pattern: ^[A-Za-z0-9][A-Za-z0-9_.-]{0,199}$
    Timestamp:
      type: string
      format: date-time
    Decimal:
      type: string
      description: An exact decimal number.
      pattern: ^-?[0-9]+(\.[0-9]+)?$
      example: '0.4100'
    Outcome:
      type: object
      additionalProperties: false
      required:
        - label
        - venue
        - market_id
        - title
        - prices
        - volume_24h_usd
      properties:
        label:
          type: string
          description: The outcome in a few words, such as `Chiefs` or `25 bps cut`.
        venue:
          $ref: '#/components/schemas/Venue'
        market_id:
          $ref: '#/components/schemas/MarketID'
        title:
          type: string
          description: The full market question.
        chance:
          $ref: '#/components/schemas/Decimal'
          description: >-
            Implied chance from 0 to 1, the midpoint of the best Yes ask and 1
            minus the best No ask across venues.
        prices:
          type: array
          description: Current asks on every venue with a proven-equivalent market.
          items:
            $ref: '#/components/schemas/VenuePrice'
        best_venue:
          $ref: '#/components/schemas/Venue'
          description: >-
            The venue with the lowest Yes ask, when more than one lists the
            outcome.
        volume_24h_usd:
          $ref: '#/components/schemas/Decimal'
        change_24h:
          $ref: '#/components/schemas/Decimal'
          description: Change in the listed market's Yes ask over 24 hours.
        sparkline:
          type: array
          description: Hourly Yes asks over the last 24 hours, oldest first.
          items:
            $ref: '#/components/schemas/Decimal'
    Error:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: A stable machine-readable code.
            message:
              type: string
              description: A human-readable explanation.
    VenuePrice:
      type: object
      additionalProperties: false
      required:
        - venue
        - market_id
      properties:
        venue:
          $ref: '#/components/schemas/Venue'
        market_id:
          $ref: '#/components/schemas/MarketID'
        yes_ask_usd:
          $ref: '#/components/schemas/Decimal'
        no_ask_usd:
          $ref: '#/components/schemas/Decimal'
        observed_at:
          $ref: '#/components/schemas/Timestamp'
  headers:
    X-RateLimit-Limit:
      description: Requests allowed per minute for this key.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests left in the current minute.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Unix time when the minute window resets.
      schema:
        type: integer
    X-Daily-Quota-Limit:
      description: Requests allowed per UTC day.
      schema:
        type: integer
    X-Daily-Quota-Remaining:
      description: Requests left today.
      schema:
        type: integer
  responses:
    BadRequest:
      description: Invalid parameter or market.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: invalid_parameter
              message: 'Invalid or unsupported query parameter: limit.'
    Unauthorized:
      description: Missing, invalid or revoked API key.
      headers:
        WWW-Authenticate:
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: api_key_required
              message: Send an API key in the X-API-Key header or as a Bearer token.
    TooManyRequests:
      description: Rate limit or daily quota exceeded.
      headers:
        Retry-After:
          description: Seconds until the limit resets.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unavailable:
      description: No graph run has finished yet.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Error:
      description: Any other error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  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.

````