---
title: "Generate an AI email asset"
method: POST
path: "/assets/generate"
tags: ["Assets"]
---

# Generate an AI email asset

`POST /assets/generate`

## Request

- Base URL: `https://enterprise.knak.io/api/published/v1`
- URL: `https://enterprise.knak.io/api/published/v1/assets/generate`
- Auth: none declared
- TypeScript: <https://skmtc.dev/knak/apis/knak-enterprise-api/docs/assets/generate/post.ts> (a function with typed inputs; its response is checked against the schema)

Generate an AI-powered email [asset](#tag/asset_model) from a text prompt. The asset is created immediately and returned in the response with `ai_generation_status: started`. AI content generation runs asynchronously in the background. Poll `GET /assets/{asset_id}` to check when `ai_generation_status` changes to `completed` or `failed`.

The asset must be associated with a campaign (asset folder). The brand is automatically resolved from the campaign.

## Request body

- object
  - `prompt` string, required: Text instructions describing the email to generate. This is the main input for the AI generation.
  - `type` 'email', required: The type of asset to generate. Currently only `email` is supported.
  - `campaign_id` string, required: The ID of the campaign (asset folder) where the asset will be created. The brand is automatically resolved from the campaign.
  - `name` string, nullable: Optional name for the asset. If not provided, a name may be auto-generated.
  - `theme_id` string, nullable: Optional theme ID to base the generated email on. Must belong to your company.
  - `subject` string, nullable: Optional subject line for the email. If not provided, the AI will generate a subject line automatically.
  - `from_name` string, nullable: Sender name for the email.
  - `from_email` string, nullable: Sender email address.
  - `reply_email` string, nullable: Reply-to email address.
  - `tags` string[], nullable: Tags to apply to the generated asset.
  - `images` object[], nullable: Images to provide as context for AI generation. Maximum 10 images.
    - `url` string, uri, required: Publicly accessible URL of the image.
    - `filename` string, required: Filename for the image.
  - `files` object[], nullable: Files (e.g. PDFs) to provide as context for AI generation. Maximum 2 files.
    - `url` string, uri, required: Publicly accessible URL of the file.
    - `filename` string, required: Filename for the file.
  - `asset_id` string, nullable: Optional. When provided, overwrites the target email asset's content with a new version instead of creating a new asset. Must reference an email asset in your company, and you must have save permission on that asset. `campaign_id` is still required and its brand is used for the regenerated content.
  - `module_ids` string[], nullable: Optional module IDs to use as building blocks for the generated email. Each module must belong to your company. Only the latest published version of each module is used; modules without a published version are ignored. Maximum 10 modules.
  - `module_variations` object, nullable: Optional variation choices for the modules in `module_ids`, keyed by module ID. Each value maps a variation `id` from `GET /modules` to `true` (show it) or `false` (hide it), overriding the variation's `enabled_by_default`. Variations you leave out keep their defaults, and an empty object keeps all of that module's defaults. Every module listed here must also be in `module_ids`.
  - `skip_editor_restrictions` boolean, nullable: When `true`, admin-configured editor restrictions are bypassed during generation so the AI can produce content that locked or hidden restrictions would otherwise forbid. Only takes effect when the authenticated user has the "bypass editor restrictions" permission; otherwise it is ignored and restrictions still apply.

## Response `200`

Asset created successfully. AI content generation is running asynchronously. Poll GET /assets/{asset_id} to check generation status.

- AssetItem
  - `data` Asset
    - `type` string, required
    - `id` string, required
    - `attributes` object, required
      - `id` string, required
      - `creator_id` string, required
      - `subject` string, required
      - `from_name` string, nullable, required
      - `from_email` string, nullable, required
      - `reply_email` string, nullable, required
      - `type` 'email' | 'landing', required
      - `name` string, required
      - `folder_path` string, required
      - `campaign` string, required
      - `brand` string, required
      - `language_code` string, nullable, required
      - `version` string, required
      - `parent_asset_id` string, nullable, required
      - `ai_generation_status` 'started' | 'completed' | 'failed', nullable: Status of AI content generation. Only present on assets created via the /assets/generate endpoint. Null for non-AI assets.
      - `ai_generation_error` string, nullable: Why AI content generation failed, when `ai_generation_status` is `failed` (for example, an image URL in the prompt that could not be accessed). Null otherwise.
      - `deleted` boolean: Whether the asset has been deleted. Only true for an asset whose AI generation failed in the last 3 days; other deleted assets return 404.
      - `approval_status` 'draft' | 'review' | 'rejected' | 'approved' | 'completed', nullable, required: Where the asset is in your company's approval workflow.

## Other responses

- `400`: Bad Request
- `401`: Unauthenticated
- `403`: Forbidden - AI generation is not enabled for this account, or (when `asset_id` is provided) the caller does not have save permission on the target asset.
- `409`: Conflict - an asset with the supplied `name` already exists in this company. Returned only when `name` is sent and a concurrent request claimed the same name first. Retry with a different name.
- `422`: Unprocessable Entity - the request is well-formed but a generation input was rejected. `meta.reason` identifies which one: `invalid_attached_image` (an image URL could not be loaded, was too large, or exceeded the maximum pixel dimensions), `too_many_references` (images, files and URLs in the prompt total more than 27), `unrequested_module_variations` (`module_variations` lists a module that is not in `module_ids`) or `unknown_module_variation` (a variation ID does not belong to the module it is listed under).
- `429`: Too Many Requests - either the per-minute rate limit (5 requests per minute) or the organization's daily generation quota was exceeded. The daily quota is shared across every surface that generates assets, and `meta.limit` / `meta.used` are present when the quota is the cause. Retry no sooner than the `Retry-After` header indicates.
- `default`: Unexpected server error.

---

[API](https://skmtc.dev/knak/apis/knak-enterprise-api.md) - [All operations](https://skmtc.dev/knak/apis/knak-enterprise-api/llms.txt) - [OpenAPI document](https://skmtc.dev/knak/apis/knak-enterprise-api/revisions/31d2c94edfcc?raw)
