---
title: "Generate routed content suggestions"
method: POST
path: "/v1/projects/{projectId}/content-suggestions"
tags: ["Content"]
---

# Generate routed content suggestions

`POST /v1/projects/{projectId}/content-suggestions`

## Request

- Base URL: `https://www.seoforgpt.io/api`
- URL: `https://www.seoforgpt.io/api/v1/projects/{projectId}/content-suggestions`
- Auth: HTTP bearer

Queues the strategic content planner. A 202 response includes status=generating, job_id, and retry_after_seconds; poll with jobId until complete. topics contains saved new-article and existing-page update brief opportunities; skipped_topics contains covered_existing_url route-only signals.

## Path parameters

- `projectId` string, uuid, required

## Request body

- object
  - `count` integer
  - `jobId` string, uuid: Returned by a generating response; provide it to poll the same job.

## Response `200`

Routed content suggestions

- ContentSuggestionsResponse
  - `data` object
    - `status` string
    - `project_id` string, uuid
    - `topic_count` integer
    - `created_count` integer
    - `skipped_count` integer: Number of returned covered_existing_url route-only skip signals.
    - `href` string
    - `titles` string[]
    - `topics` ContentSuggestionTopic[]
      - `id` string, nullable
      - `title` string
      - `type` string, nullable
      - `audience` string, nullable
      - `source` string, nullable
      - `reason` string, nullable
      - `content_action` 'new_article' | 'optimize_existing_url' | 'covered_existing_url'
      - `target_url` string, nullable
      - `target_title` string, nullable
      - `coverage_status` string, nullable
      - `match_reason` string, nullable
      - `created_at` string, nullable
      - `persisted` boolean: True when this suggestion was saved as a generated topic. covered_existing_url items are route-only skip signals and return false.
      - `position` integer
    - `skipped_topics` ContentSuggestionTopic[]: Route-only covered_existing_url items that should be skipped instead of generated.
      - `id` string, nullable
      - `title` string
      - `type` string, nullable
      - `audience` string, nullable
      - `source` string, nullable
      - `reason` string, nullable
      - `content_action` 'new_article' | 'optimize_existing_url' | 'covered_existing_url'
      - `target_url` string, nullable
      - `target_title` string, nullable
      - `coverage_status` string, nullable
      - `match_reason` string, nullable
      - `created_at` string, nullable
      - `persisted` boolean: True when this suggestion was saved as a generated topic. covered_existing_url items are route-only skip signals and return false.
      - `position` integer
  - `meta` BillingMeta: Plan and quota snapshot (shape may evolve)

## Other responses

- `202`: Strategic planner is still generating; retry with the returned job_id.
- `401`: Missing or invalid bearer token
- `402`: Billing or quota gate
- `404`: Resource not found
- `429`: Rate limit exceeded. Responses include the current IETF `RateLimit` and `RateLimit-Policy` structured fields, compatibility `RateLimit-*` and `X-RateLimit-*` fields, and `Retry-After` on 429.
- `500`: Server error
- `default`: Any documented or unexpected 4xx or 5xx response uses the same typed error envelope.

---

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