# List All Subscriptions

```
GET 
/v1/dashboard-subscriptions
```

**What is this account emailing, and to whom?** Every subscription you may reach, one cursor page at a time.

THE QUESTION THIS EXISTS FOR. Until this route, a subscription could only be listed under a dashboard you already knew about (`GET /v1/viz/{viz_id}/subscriptions`), so answering it meant enumerating every dashboard first — measured at **eleven calls to find five rows**, six of them empty. A colleague who does not already know a subscription exists cannot find it that way, which is exactly the person who asks: an admin auditing outbound mail, or the manager of somebody who left. Both sibling resources already answered account-wide (`GET /v1/alerts`, `GET /v1/refreshes`); subscriptions were the odd one out.

`vizId` narrows it to one dashboard, resolved through the ACL first (403 when out of reach) and `total` counted — the same answer the viz-scoped path gives, so a caller has one route for both questions.

Without it, every distinct dashboard on the page is resolved and rows on a dashboard you cannot reach are dropped; the DB is read until the page is full or exhausted, so a short page still means "last page", and `total` is `null` (**not counted**, never "zero"). Same shape, same reasoning, same fill bound as `GET /v1/alerts`.

ORPHANS ARE LISTED, and this is the only place they appear. A subscription whose dashboard was deleted keeps mailing its recipients and keeps its Task; `GET`/`DELETE` on its id both tolerate that (`_assert_may_touch_orphan`) but the viz-scoped list cannot — its guard resolves a viz that is gone. So an orphan row was reachable only by an id nobody had. Listing it here is the difference between "we cannot stop this email" and "delete row 13".

Cursor-paginated. The wire query parameter is `exclusiveStartKey` (what the cURL tab and the parameter table show); the TypeScript SDK takes it as the `exclusiveStartKey` option and the Python SDK as the `exclusive_start_key` keyword — one parameter, spelled per language. Pass the previous page's `nextKey` and stop when it comes back `null` — or let `iterAll()` / `iter_all()` drive the cursor for you (see the SDKs page, "Pagination").

## Request[​](#request "Direkter Link zur request")

## Responses[​](#responses "Direkter Link zur Responses")

* 200
* 404
* 422

Successful Response

Not found

Validation Error
