# Measurement API Paths on this page are relative to `https://shruwd.io/api/v1`. | Method | Path | Scope | Role | |---|---|---|---| | `POST` | `/brands/{brandId}/cycles` | `write` | editor | | `GET` | `/brands/{brandId}/cycles` | `read` | viewer | | `GET` | `/brands/{brandId}/visibility` | `read` | viewer | | `GET` | `/brands/{brandId}/visibility/series` | `read` | viewer | | `GET` | `/brands/{brandId}/crawlers` | `read` | viewer | | `GET` | `/brands/{brandId}/answers` | `read` | viewer | > **Warning** > > **Measurement is asynchronous.** Running a cycle schedules work; results arrive over the > following hours. Nothing you can call returns a finished measurement, so do not poll in a > tight loop and do not report a number before there is one. ## Run a cycle ```bash curl -X POST "https://shruwd.io/api/v1/brands/waitlister/cycles" \ -H "Authorization: Bearer $SHRUWD_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` Creates a manual cycle due now and returns its id. It draws on the same period allowance as any cycle. On a free plan this **is** the one snapshot, and is `409 snapshot_taken` once used. A workspace paused pending review is `409 workspace_on_hold`. `GET /brands/{brandId}/cycles?limit=` returns recent cycles with their state and counts. ## Read visibility ```bash curl "https://shruwd.io/api/v1/brands/waitlister/visibility?engine=google_aio" \ -H "Authorization: Bearer $SHRUWD_API_KEY" ``` | Parameter | | |---|---| | `engine` | `google_aio` or `chatgpt` | | `from` `to` | `YYYY-MM-DD`. `to` defaults to today **in the brand's timezone** | Returns `{ engine, range, asOf, nResponses, entities, prompts }`. Each entity carries `mentionRate`, `shareOfVoice` and `avgProminence`, every one of them with its interval or an explicit `insufficient_data`. If `from` reaches past your plan's history window it is clamped, and the response says so in `historyFrom` rather than failing. ## Read the trend ```bash curl "https://shruwd.io/api/v1/brands/waitlister/visibility/series?window=30" \ -H "Authorization: Bearer $SHRUWD_API_KEY" ``` | Parameter | | |---|---| | `window` | `7`, `30` or `90`. Default `30` | | `from` `to` | Default is the last ninety days | Returns `points` (one per cycle close) and, per entity, a `series` **index-aligned** with it. A point below the display floor is `insufficient_data`, never a number. `modelChanges` lists the moments the provider changed its underlying models. A difference spanning one of those may be the model rather than you — see [When a number has moved](https://shruwd.io/docs/metrics/when-a-number-has-moved.md). ## Read crawler activity ```bash curl "https://shruwd.io/api/v1/brands/waitlister/crawlers" \ -H "Authorization: Bearer $SHRUWD_API_KEY" ``` Per-bot activity with verified and unverified hits kept separate. Only verified hits count toward anything. `daily` carries a per-day series per bot, index-aligned with `daily.days`. > **Note** > > A day with no log ingest is `null`, not `0`. It means nobody was watching, not that > nothing happened — do not chart it as zero. ## Read individual answers ```bash curl "https://shruwd.io/api/v1/brands/waitlister/answers?limit=10" \ -H "Authorization: Bearer $SHRUWD_API_KEY" ``` `limit` is 1–50, default 10. Newest first, measured runs only. Each answer carries `prompt`, `engine`, `state`, `executedAt`, whether you were `mentioned` and at what `rank`, the surrounding `context`, the `competitors` named, and the `citations` with `isSelf` marked. > **Warning** > > **This is evidence, not a metric.** Never compute a rate from these rows — the sample is > whatever the last few runs happened to be. It exists so you can read what an answer > actually said, which is useful while a brand is still below the display floor. ## Next steps - [Findings](https://shruwd.io/docs/api/findings.md) — the diagnosed causes behind these numbers - [Metric definitions](https://shruwd.io/docs/metrics/metric-definitions.md) — what each number counts