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

# GET /v1/movers

> Top gainers and decliners across the universe over a chosen window.

The 20 biggest score gainers and 20 biggest decliners over the last 7, 30, or 90 days.

## Parameters

| Query    | Required | Values             |
| -------- | -------- | ------------------ |
| `window` | **yes**  | `7d`, `30d`, `90d` |

A request with no `window` or an invalid value returns `400 { error: "window must be one of [...] " }`.

## When to use it

* Daily / weekly "what's moving" digest.
* Spotting accelerating or distressed companies you don't already track.
* Validating that a thesis (e.g. "fintech is heating up") is showing in the data.

## Response

```json theme={null}
{
  "window": "30d",
  "window_start": "2026-04-12T18:30:00Z",
  "window_end":   "2026-05-12T18:30:00Z",
  "gainers": [
    {
      "domain": "anthropic.com",
      "company_name": "Anthropic",
      "composite_now": 72.4,
      "composite_then": 64.1,
      "delta": 8.3,
      "ki_rating_now": "KI-1",
      "ki_rating_then": "KI-2+"
    },
    ...
  ],
  "decliners": [
    {
      "domain": "examplecorp.com",
      "company_name": "Example Corp",
      "composite_now": 41.0,
      "composite_then": 53.6,
      "delta": -12.6,
      "ki_rating_now": "KI-3",
      "ki_rating_then": "KI-2"
    },
    ...
  ]
}
```

`delta = composite_now − composite_then`. Both lists are sorted by `|delta|` DESC.

## Eligibility for movers

A domain is eligible if it has at least two scoring runs: one inside the window and one before it. Newly-scored domains with no prior history are excluded — they have nothing to move against.

## Caching

The full response is cached server-side for 5 minutes per `(pipeline_version, window)` pair. Two callers requesting `?window=30d` 30 seconds apart get bit-identical responses.

## No pagination

There's no `limit` or `cursor`. Movers always returns 20 + 20. If you want a deeper view, compose `/v1/distribution` + per-domain `/v1/score/{domain}/history`.


## OpenAPI

````yaml GET /v1/movers
openapi: 3.1.0
info:
  title: Kepler Insights API
  version: 1.0.0
  summary: Curated company-scoring intelligence over a 67-signal engine.
  description: >
    The Kepler Insights API exposes a curated subset of the Kepler scoring
    engine

    over a stable REST surface. Every score is a composite over 67 signals
    organized

    into 4 buckets (Team & Structure, Market Position, Momentum & Tailwinds,

    Financial Health), with a separate scale premium that lifts established

    companies whose underlying fundamentals justify a higher tier.


    **Authentication.** All requests require a single header: `X-API-Key`.

    Keys are issued from the developer console at
    `https://console.keplerinsights.us`.


    **Sandbox.** Test keys prefixed `ki_test_` accept only the four canned

    domains (`acme.test`, `unicorn.test`, `struggling.test`, `cohort.test`),

    never invoke fetchers, and return deterministic responses tagged with

    `mode: sandbox`. Live keys prefixed `ki_live_` reject test domains and

    run against the real engine.


    **Cold vs cached.** `GET /v1/score/{domain}` is always cached (404 if no

    recent record exists). `POST /v1/score` decides per-call based on your

    tier's freshness window: a fresh record returns inline (`200`), a stale

    or missing one queues a cold pipeline run and returns `202` with a

    `job_id` to poll. Cold spend is bounded by per-tier monthly caps +

    circuit breakers.
  contact:
    name: Kepler Insights API support
    email: noah@keplerinsights.us
  license:
    name: Proprietary
servers:
  - url: https://api.keplerinsights.us
    description: Production
security:
  - apiKey: []
tags:
  - name: scoring
    description: Score a company and retrieve the latest result.
  - name: history
    description: Time-series of past scoring runs for a single company.
  - name: company
    description: Per-company analytics (cohort, confidence).
  - name: universe
    description: Distribution + movers across the full scored universe.
  - name: meta
    description: Signal manifest + caller usage + async job tracking.
paths:
  /v1/movers:
    get:
      tags:
        - universe
      summary: Top gainers and decliners across the universe.
      description: |
        Top 20 gainers and 20 decliners by composite-score delta over the
        chosen window. Response is cached server-side for 5 minutes per
        `(pipeline_version, window)` pair.
      operationId: getMovers
      parameters:
        - in: query
          name: window
          required: true
          schema:
            type: string
            enum:
              - 7d
              - 30d
              - 90d
            default: 30d
      responses:
        '200':
          description: Top movers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MoversResponse'
        '400':
          description: Bad `window` value.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    MoversResponse:
      type: object
      properties:
        mode:
          type: string
        window:
          type: string
          enum:
            - 7d
            - 30d
            - 90d
        window_start:
          type: string
          format: date-time
        window_end:
          type: string
          format: date-time
        gainers:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/MoverRow'
        decliners:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/MoverRow'
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          example: unauthorized
        message:
          type: string
        reason:
          type: string
          description: Additional context for rate-limit responses.
    MoverRow:
      type: object
      properties:
        domain:
          type: string
        company_name:
          type: string
        composite_now:
          type: number
        composite_then:
          type: number
        delta:
          type: number
          description: composite_now − composite_then
        ki_rating_now:
          type: string
        ki_rating_then:
          type: string
  responses:
    Unauthorized:
      description: Missing or invalid `X-API-Key`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: >
        Live keys are prefixed `ki_live_`, test keys `ki_test_`. Issue + revoke

        keys at https://console.keplerinsights.us. Never embed a key in
        client-side

        code — every endpoint is backend-to-API only.

````