---
title: "What to do now on a site"
method: GET
path: "/next-actions"
tags: ["Next actions"]
---

# What to do now on a site

`GET /next-actions`

## Request

- Base URL: `https://next.frase.io/api/v1`
- URL: `https://next.frase.io/api/v1/next-actions`
- Auth: one of:
  - API key in header `X-API-KEY`
  - HTTP bearer

The ranked, cross-domain list of what to do now on one site: the same daily brief the workspace's Home page shows, as stored, with nothing ranked at request time. `todos` are the actions, `updates` the news, `more_todos` the next-best actions behind the day's cap; every item carries a deterministic `cta` and, where a v1 row backs it, a `resource` pointer naming what to open next. `status` is `ready` when a brief is stored for the site, or when the day's run finished without finding anything for it (empty lists, the run's date), and `none` when the brief has not reached the site yet (empty lists, `brief_date` null). The newest ready brief dated no later than the current UTC day is served; API keys have no viewer clock. A member-bound MCP token is served by the member's reveal hour on the UTC clock, as Home serves a member whose browser clock it has not seen. Kinds with no v1 route behind them today (comments, the review queue, Answers signals, page updates, setup nudges) are not carried, nor is crawlability, which the brief ranks for the organization and never stores on a site's row; they arrive under a dated note here when their routes exist. Requires the read scope of every area the brief spans or points at: `read:opportunities`, `read:analytics`, `read:audits`, `read:content`, `read:ai-visibility`, `read:site-health`. Reads are org-scoped, so a site belonging to another organization, or one in Trash, returns 404.

## Query parameters

- `site_id` string, uuid, required

## Response `200`

The site's next actions

- object
  - `data` object, required
    - `site_id` string, uuid, required
    - `brief_date` string, date, nullable, required: The day the brief is for.
    - `status` 'ready' | 'none', required
    - `home_only_items` integer, required: Items in the brief that only Home shows: team work the API carries no resource for (comments, review queue, citation fixes, answers signals, setup nudges, crawlability), counted as stored. Home re-checks setup nudges at read time and hides a satisfied one, so the count is an upper bound. An empty list here is not by itself a quiet day.
    - `todos` object[], required
      - `id` string, required: The brief's stable item id. Completions are keyed on it.
      - `kind` 'performance_alert' | 'analytics_insight' | 'audit' | 'opportunity' | 'optimization_win' | 'ai_visibility', required
      - `domain` 'analytics' | 'site_health' | 'opportunities' | 'optimizations' | 'ai_visibility', required
      - `title` string, required
      - `context` string, required: One or two sentences on why it matters today.
      - `severity` 'critical' | 'high' | 'medium' | 'low', required
      - `score` number, nullable, required
      - `cta` object, required: Stamped at ranking, never narrated.
        - `label` string, required
        - `path` string, required: App-relative path the action opens.
      - `resource` object, nullable, required: What to open next: `opportunity` reads GET /opportunities/{id}, `content` GET /content/{id}, `audit` GET /audits/{id}, `audit_run` asks for a new audit of the site whose id it carries (POST /audits), `ai_visibility_prompt` GET /ai-visibility/prompts/{id}. Null when the action lands on a page rather than a row.
        - `type` 'opportunity' | 'content' | 'audit' | 'audit_run' | 'ai_visibility_prompt', required
        - `id` string, required
      - `site_id` string, uuid, nullable, required
      - `carried_over` boolean, required: True when the item also stood in the previous day's brief and was not completed.
      - `more` object, nullable, required
        - `count` integer, required
        - `note` string, required
        - `path` string, nullable, required: The app path that opens the full list behind the tail, where the item's cta opens one row.
      - `completed_at` string, date-time, nullable, required
    - `updates` object[], required
      - `id` string, required: The brief's stable item id. Completions are keyed on it.
      - `kind` 'performance_alert' | 'analytics_insight' | 'audit' | 'opportunity' | 'optimization_win' | 'ai_visibility', required
      - `domain` 'analytics' | 'site_health' | 'opportunities' | 'optimizations' | 'ai_visibility', required
      - `title` string, required
      - `context` string, required: One or two sentences on why it matters today.
      - `severity` 'critical' | 'high' | 'medium' | 'low', required
      - `score` number, nullable, required
      - `cta` object, required: Stamped at ranking, never narrated.
        - `label` string, required
        - `path` string, required: App-relative path the action opens.
      - `resource` object, nullable, required: What to open next: `opportunity` reads GET /opportunities/{id}, `content` GET /content/{id}, `audit` GET /audits/{id}, `audit_run` asks for a new audit of the site whose id it carries (POST /audits), `ai_visibility_prompt` GET /ai-visibility/prompts/{id}. Null when the action lands on a page rather than a row.
        - `type` 'opportunity' | 'content' | 'audit' | 'audit_run' | 'ai_visibility_prompt', required
        - `id` string, required
      - `site_id` string, uuid, nullable, required
      - `carried_over` boolean, required: True when the item also stood in the previous day's brief and was not completed.
      - `more` object, nullable, required
        - `count` integer, required
        - `note` string, required
        - `path` string, nullable, required: The app path that opens the full list behind the tail, where the item's cta opens one row.
      - `completed_at` string, date-time, nullable, required
    - `more_todos` object[], required
      - `id` string, required: The brief's stable item id. Completions are keyed on it.
      - `kind` 'performance_alert' | 'analytics_insight' | 'audit' | 'opportunity' | 'optimization_win' | 'ai_visibility', required
      - `domain` 'analytics' | 'site_health' | 'opportunities' | 'optimizations' | 'ai_visibility', required
      - `title` string, required
      - `context` string, required: One or two sentences on why it matters today.
      - `severity` 'critical' | 'high' | 'medium' | 'low', required
      - `score` number, nullable, required
      - `cta` object, required: Stamped at ranking, never narrated.
        - `label` string, required
        - `path` string, required: App-relative path the action opens.
      - `resource` object, nullable, required: What to open next: `opportunity` reads GET /opportunities/{id}, `content` GET /content/{id}, `audit` GET /audits/{id}, `audit_run` asks for a new audit of the site whose id it carries (POST /audits), `ai_visibility_prompt` GET /ai-visibility/prompts/{id}. Null when the action lands on a page rather than a row.
        - `type` 'opportunity' | 'content' | 'audit' | 'audit_run' | 'ai_visibility_prompt', required
        - `id` string, required
      - `site_id` string, uuid, nullable, required
      - `carried_over` boolean, required: True when the item also stood in the previous day's brief and was not completed.
      - `more` object, nullable, required
        - `count` integer, required
        - `note` string, required
        - `path` string, nullable, required: The app path that opens the full list behind the tail, where the item's cta opens one row.
      - `completed_at` string, date-time, nullable, required

## Other responses

- `400`: site_id missing or not a UUID (`param: "site_id"`)
- `403`: The key lacks the read scope of an area the brief spans; the message names the missing scopes
- `404`: Site not found in this organization, or in Trash

---

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