---
title: "List the org's projects (any member)"
method: GET
path: "/v1/orgs/{org_id}/projects"
tags: ["projects"]
---

# List the org's projects (any member)

`GET /v1/orgs/{org_id}/projects`

## Request

- Base URL: `https://api.wavehouse.cloud`
- URL: `https://api.wavehouse.cloud/v1/orgs/{org_id}/projects`
- Auth: one of:
  - API key in cookie `whc_session`
  - HTTP bearer
  - API key in header `X-API-Key`

## Path parameters

- `org_id` string, required

## Query parameters

- `limit` integer: page size; 0 or absent means 50
- `cursor` string: next_cursor from the previous page; absent for the first page

## Response `200`

OK

- ProjectPage
  - `data` ProjectView[], required
    - `connection` ProjectConnectionView
      - `auth_configured` boolean, required: false until the org sets a data-plane auth config
      - `auth_mode` string, required: jwks | hmac | public | unconfigured
      - `hint` string: one-line next step for the customer
      - `hmac_fingerprint` string: non-secret fingerprint (trailing checksum) of the active HMAC secret; shown as whc_hmac_…<fingerprint>
      - `url` string: Public HTTPS endpoint, https://<project_id>.<base-domain>
    - `created_at` string, date-time, required
    - `default_role` string, required: policy role for roleless requests (the 'public' access level); empty = locked
    - `deletion_grace_seconds` integer, required: how long a deletion scheduled now keeps the project's data before destroying it; cancellable until then
    - `destroy_after` string, date-time: instant a scheduled deletion becomes due; present only while status is deleting or destroying
    - `name` string, required
    - `org_id` string, required: the org that owns the project
    - `project_id` string, required
    - `provisioning_failed` boolean: setting this project up did not finish and nothing is retrying it; POST .../provision resumes it from where it stopped
    - `settings` ProjectSettingsView, required
      - `cors_allowed_origins` string[]: browser origins the data-plane allows. Empty = block all browser origins (server-side ingest/queries are unaffected by CORS); "*" = allow any origin. Otherwise each entry must be an exact scheme://host[:port] — no path, no wildcard: the engine matches origins literally, and an entry it cannot match this way is rejected with a 422 naming it. Only affects browser clients. The WaveHouse Cloud console is always allowed automatically and need not be listed
      - `dedupe_enabled` boolean: drop duplicate rows by a stable id field (idempotent ingest)
      - `dedupe_id_field` string: JSON field the dedupe key reads (engine default: event_id)
      - `dedupe_require_id` boolean: reject rows missing the dedupe id field (strict idempotency)
      - `query_default_max_rows` integer: fallback result LIMIT when a query specifies none; 0 = engine default (10000)
      - `query_timeout_seconds` integer: max seconds a read may run; 0 = engine default (30)
    - `status` string, required: pending | provisioning | active | suspended | deleting (scheduled, cancellable until destroy_after) | destroying (the teardown has begun and can no longer be cancelled)
    - `writes_paused` boolean: writes are paused for maintenance and resume on their own; reads, the id, credentials and policy are unaffected
  - `next_cursor` string, nullable, required: pass as cursor to fetch the next page; null on the last page

## Other responses

- `429`: Rate limited, per client IP, API key or org; a client IP is also refused on every route for a while after repeated authentication failures. A limited operation carries RateLimit-Policy and RateLimit on every response; wait Retry-After seconds before retrying.
- `default`: Error

---

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