---
title: "Generate content from brief"
method: POST
path: "/content/generate"
tags: ["Content"]
---

# Generate content from brief

`POST /content/generate`

## Request

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

Generate content from an existing brief. The brief must have a complete outline. The content generation runs asynchronously - use the returned content ID with the jobs endpoint to track progress.

## Request body

- object
  - `brief_id` string, uuid, required: ID of the brief to generate content from. The brief must have a non-empty outline.
  - `generate_images` boolean: Generate a hero image for the content. Uses hero image credits.

## Response `201`

Content generation started

- object
  - `data` object
    - `id` string, uuid: Content ID
    - `brief_id` string, uuid: Brief ID
    - `title` string: Content title (from brief topic)
    - `status` 'generating': Content status
    - `created_at` string, date-time
    - `content_url` string: URL to view the content in the Frase app
    - `status_url` string: URL to check generation status
  - `request_id` string

## Other responses

- `400`: Validation failed
- `401`: Authentication failed
- `403`: Refused because the organization's SUBSCRIPTION is not in good standing (`subscription_inactive`): canceled, paused, past due beyond the grace period, or an expired trial. Nothing is generated and no credit is spent. This is NOT a quota refusal, and none of the quota remedies clear it: waiting for the monthly reset, enabling paid overage and upgrading the plan all leave it refused. The `message` names the account state; an organization admin resolves it in Billing settings. The same status also carries the AUTH-layer refusals, which are about the KEY rather than the account: `insufficient_scope` (the key lacks `write:content`), `ip_not_allowed` (the request came from an address outside the key's allowlist), and `key_missing_user` (the key has no associated user and must be regenerated). Branch on `error.code`, not on the status.
- `404`: Brief not found
- `429`: Refused for a quota: the organization's monthly article allowance (`article_limit_exceeded`), the SITE's own monthly article budget (`site_article_budget_exceeded`), or the monthly hero image allowance (`hero_image_limit_exceeded`). Nothing is generated and no credit is spent, and a retry cannot succeed until the relevant cap changes. `site_article_budget_exceeded` is a separate cap from the organization allowance: paid overage and plan upgrades do NOT lift it, and it can refuse while the organization has plenty of articles left. An organization admin raises it in Site settings, or you can generate for a different site. `rate_limit_exceeded` is a different thing entirely and DOES clear on a clock: generation is capped at 30 calls per hour for each key owner in an organization, and this response carries `Retry-After` (seconds) plus the `X-RateLimit-*` headers. Wait out the window and retry.

---

[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)
