> ## Documentation Index
> Fetch the complete documentation index at: https://jetemail.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate or revise template content with AI

> Runs one AI action against a template and returns a validated draft. Dashboard session only: API keys are rejected with 403 `ai_dashboard_only`.



## OpenAPI

````yaml /openapi.json post /marketing/ai/generate
openapi: 3.0.0
info:
  title: JetEmail API
  version: 1.0.0
  description: API documentation for JetEmail's transactional email service.
servers:
  - url: https://api.jetemail.com
    description: Production
security:
  - apiKeyAuth: []
tags:
  - name: Email
    description: Send transactional email
  - name: Outbound
    description: 'Outbound sending: keys, SMTP users, domains, logs, suppression'
  - name: Inbound
    description: Inbound routing, domains and forward destinations
  - name: DMARC
    description: DMARC aggregate-report domain setup, DNS verification and analytics
  - name: Marketing
    description: >-
      Marketing suite: templates, audiences, contacts, broadcasts, themes,
      assets and signup forms
  - name: Signup Forms
    description: Hosted signup pages and form submissions
externalDocs:
  description: Download OpenAPI Specification
  url: /openapi.json
paths:
  /marketing/ai/generate:
    post:
      tags:
        - Marketing
      summary: Generate or revise template content with AI
      description: >-
        Runs one AI action against a template and returns a validated draft.
        Dashboard session only: API keys are rejected with 403
        `ai_dashboard_only`.
      requestBody:
        required: true
        description: Total body size must stay under 75,000 bytes.
        content:
          application/json:
            schema:
              type: object
              required:
                - requestId
                - templateId
                - action
              properties:
                requestId:
                  type: string
                  pattern: ^[a-zA-Z0-9_-]{16,100}$
                  description: >-
                    Idempotency key, stable across retries. Replaying one
                    returns the original result without charging; reusing one
                    with different input is a 409.
                templateId:
                  type: string
                  description: Template to work on. Required.
                action:
                  type: string
                  enum:
                    - subject_variants
                    - rewrite_block
                    - translate_block
                    - draft_email
                    - template_chat
                    - generate_template
                  description: >-
                    Selects the task and the credit cost. `rewrite_block` and
                    `translate_block` require `target`.
                prompt:
                  type: string
                  maxLength: 4000
                  description: Required for every action except `translate_block`.
                tone:
                  type: string
                  maxLength: 80
                  default: Match the current brand and request
                language:
                  type: string
                  maxLength: 80
                  default: English
                history:
                  type: array
                  description: Ignored; the server uses its own template-scoped history.
                  items:
                    type: object
                    properties:
                      role:
                        type: string
                        enum:
                          - user
                          - assistant
                      content:
                        type: string
                context:
                  type: object
                  description: >-
                    The live editor content, which is the source of truth for
                    the request.
                  properties:
                    name:
                      type: string
                      maxLength: 200
                    subject:
                      type: string
                      maxLength: 300
                    previewText:
                      type: string
                      maxLength: 500
                    blocks:
                      type: array
                      maxItems: 50
                      description: Builder blocks; rejected if over 50,000 bytes as JSON.
                      items:
                        type: object
                    styles:
                      type: object
                      description: EmailStyles; rejected if over 10,000 bytes as JSON.
                target:
                  type: object
                  nullable: true
                  description: >-
                    The selected block, for block-scoped actions. All three
                    fields are required when present.
                  properties:
                    id:
                      type: string
                      maxLength: 100
                    type:
                      type: string
                      maxLength: 30
                    content:
                      type: string
                      maxLength: 5000
      responses:
        '200':
          description: Validated draft
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  replayed:
                    type: boolean
                    description: >-
                      True when the requestId was already completed; the stored
                      result was returned and nothing was charged.
                  requestId:
                    type: string
                  result:
                    $ref: '#/components/schemas/MarketingAiResult'
                  chat:
                    type: object
                    properties:
                      conversationId:
                        type: string
                      userMessage:
                        $ref: '#/components/schemas/MarketingAiMessage'
                      assistantMessage:
                        allOf:
                          - $ref: '#/components/schemas/MarketingAiMessage'
                        description: >-
                          Omitted if the generation succeeded but persisting it
                          did not; `result` is still authoritative.
                  credits:
                    $ref: '#/components/schemas/MarketingAiCredits'
        '400':
          description: >-
            Invalid request (codes `ai_invalid_request`,
            `ai_template_required`). Includes an unknown action, a malformed
            requestId, a missing prompt, an invalid target, or oversized
            template content.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '401':
          description: Unauthorized (code `unauthorized`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '402':
          description: >-
            Payment required (codes `ai_paid_plan_required`,
            `ai_credits_exhausted`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '403':
          description: >-
            Forbidden (codes `ai_dashboard_only`, `ai_owner_blocked`). API-key
            callers always receive `ai_dashboard_only`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '404':
          description: >-
            Template not found, or not owned by the caller (code
            `ai_template_not_found`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '409':
          description: >-
            Idempotency conflict (codes `ai_idempotency_conflict`,
            `ai_in_progress`). The requestId is in flight, or was already used
            with different input.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '413':
          description: Request body over 75,000 bytes (code `ai_input_too_large`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '429':
          description: >-
            Rate limited per user and per account (code `ai_rate_limited`). The
            body adds `retryAfter` in seconds, mirroring the Retry-After header.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/MarketingAiError'
                  - type: object
                    properties:
                      retryAfter:
                        type: integer
        '500':
          description: >-
            Credit bookkeeping failed (codes `ai_credit_error`,
            `ai_migration_required`, `ai_plan_not_configured`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '502':
          description: >-
            Generation failed; credits were released (codes
            `ai_generation_failed`, `ai_invalid_output`, `ai_empty_response`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '503':
          description: >-
            AI unavailable (codes `ai_disabled`, `ai_not_configured`,
            `ai_provider_unavailable`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
        '504':
          description: Generation timed out (code `ai_timeout`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketingAiError'
components:
  schemas:
    MarketingAiResult:
      type: object
      description: >-
        Validated AI output. Always a draft: applying it is a separate user
        action, and nothing here is saved or sent. `kind` selects the shape.
      required:
        - kind
        - message
      properties:
        kind:
          type: string
          enum:
            - subject_variants
            - block
            - template
        message:
          type: string
          description: Short plaintext summary of what changed.
        variants:
          type: array
          description: kind=subject_variants only.
          items:
            type: object
            properties:
              subject:
                type: string
              previewText:
                type: string
        blockId:
          type: string
          description: 'kind=block only: the rewritten block.'
        content:
          type: string
          description: 'kind=block only: escaped inline content.'
        html:
          type: string
          description: 'kind=block only: rendered block HTML.'
        subject:
          type: string
          description: kind=template only.
        previewText:
          type: string
          description: kind=template only.
        blocks:
          type: array
          description: >-
            kind=template only: builder blocks, reduced to the supported block
            allowlist.
          items:
            type: object
        styles:
          type: object
          description: 'kind=template only: EmailStyles.'
    MarketingAiMessage:
      type: object
      description: One stored turn of a template-scoped conversation.
      properties:
        id:
          type: string
        requestId:
          type: string
          description: Ties the user turn to its assistant reply.
        role:
          type: string
          enum:
            - user
            - assistant
        content:
          type: string
        result:
          allOf:
            - $ref: '#/components/schemas/MarketingAiResult'
          description: Present only on succeeded assistant turns.
        status:
          type: string
          enum:
            - pending
            - succeeded
            - failed
        creditCost:
          type: integer
        errorCode:
          type: string
          description: Empty unless status is failed.
        createdAt:
          type: integer
          description: Unix seconds
        completedAt:
          type: integer
          nullable: true
          description: Unix seconds
    MarketingAiCredits:
      type: object
      description: >-
        AI credit wallet for the authenticated owner, for the current monthly
        UTC cycle.
      properties:
        available:
          type: boolean
          description: False when the plan carries no AI grant, so no wallet exists yet.
        planLevel:
          type: integer
          description: Marketing plan level; 0 is free.
        monthlyCredits:
          type: integer
          description: Credits granted per cycle by the plan.
        granted:
          type: integer
        reserved:
          type: integer
          description: Credits held by generations that are still in flight.
        consumed:
          type: integer
        remaining:
          type: integer
          description: >-
            granted - reserved - consumed. A request needs at least its cost
            here.
        cycleKey:
          type: string
          example: 2026-08
        cycleEndsAt:
          type: integer
          description: Unix seconds
        blocked:
          type: boolean
          description: True when AI is disabled for this account by an operator.
        blockedReason:
          type: string
    MarketingAiError:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          description: Human-readable message, safe to display.
        code:
          type: string
          description: Stable machine-readable code. Branch on this, not on the message.
          example: ai_credits_exhausted
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      description: API key for account management endpoints. Use your api_ prefixed token.

````