---
title: "List Plans"
method: GET
path: "/api/discovery-plans"
tags: ["Discovery"]
---

# List Plans

`GET /api/discovery-plans`

## Request

- Base URL: `https://api.kolens.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.kolens.ai/api/discovery-plans`
- Auth: HTTP bearer

List discovery plans owned by the calling user.

Scoping (mirrors /api/jobs):
  - With X-Kolens-User-Id (the normal web path): restrict to plans
    owned by that user. Both DiscoveryPlan.user_id and
    APIKey.user_id are honoured (older rows where user_id is NULL
    but the api_key resolves to a user still belong to them).
  - Without the header (CLI / Cowork plugin): legacy per-api_key.

Was previously scoped only by api_key. Every web user shares the
same KOLENS_API_KEY through the Vercel proxy, so plans LEAKED
across users on the listing page until this fix.

## Query parameters

- `status` 'draft' | 'active' | 'disabled', nullable

## Headers

- `x-kolens-user-id` string, nullable

## Response `200`

Successful Response

- DiscoveryPlanOut[]
  - `id` string, required
  - `name` string, required
  - `keyword` string, required
  - `platform` string, required
  - `interval_hours` integer, required
  - `max_videos_per_run` integer, required
  - `region` string, nullable
  - `filters` object, nullable, required
  - `target_list_id` string, nullable, required
  - `status` 'draft' | 'active' | 'disabled', required
  - `effective_status` 'draft' | 'active' | 'disabled' | 'queued' | 'running' | 'failed', required
  - `data_source` string, required
  - `last_run_at` string, nullable, required
  - `next_run_at` string, nullable, required
  - `last_job_id` string, nullable, required
  - `last_job_status` string, nullable
  - `last_error` string, nullable
  - `created_at` string, required
  - `updated_at` string, required
  - `query_plan` QueryPlanEcho: Display-only echo of how the NL query planner interpreted a typed intent sentence (Phase 1). Returned on the create / search-submit response so the UI can show "Interpreted as: [terms] · filters". Only present when the planner flag is ON *and* the planner produced a real (non-passthrough) interpretation — null otherwise so existing clients ignore it. An editable confirm step is Phase 2.
    - `raw_query` string, required
    - `search_terms` string[]
    - `filters` object
    - `market` string, nullable
    - `language` string, nullable
    - `notes` string

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/kolens/apis/kolens-api.md) · [All operations](https://skmtc.dev/kolens/apis/kolens-api/llms.txt) · [OpenAPI document](https://skmtc.dev/kolens/apis/kolens-api/revisions/5d6865ab0a24?raw)
