CitationBenchTalk to Sales
API referenceProduction

Image Generation API — Template-Driven, On-Brand OG Cards and Illustrations

REST API for generating brand-aligned images from reusable templates. Produce OG cards, hero illustrations, CTA banners, and inline graphics rendered via Satori — no prompt engineering required.

Generate brand-aligned images from templates — OG cards, hero illustrations, in-line graphics, CTA banners, list cards, comparison visuals. Every workspace inherits a library of templates; agencies can fork and customize.

Conceptual overview

Image generation in CitationBench is template-driven, not free-form prompt-to-image. Each template defines:

  • A visual layout (rendered via Satori → PNG/JPG)
  • A JSON schema for input data (title, subhead, highlights, brand colors)
  • Brand-specific defaults (font, palette, logo)

40+ templates ship per brand in the system library. You can create new ones or fork existing ones for per-workspace customization. The benefit: every image you generate looks like it came from the same brand without any prompt engineering.

Endpoints

MethodPathPurpose
POST/v1/produce/imageGenerate one image
POST/v1/produce/image/bulkGenerate many images
GET/v1/produce/imageList generated images
GET/v1/produce/image/{id}Get one image
DELETE/v1/produce/image/{id}Delete
GET/v1/produce/image/templatesList available templates
GET/v1/produce/image/templates/{id}Get one template (with schema + sample)
POST/v1/produce/image/templates/{slug}/forkFork a system template into the workspace

POST /v1/produce/image

{
  "templateId": "acme-og-card",
  "data": {
    "title": "How engineering teams track capacity",
    "subhead": "Five patterns that scale",
    "tag": "Performance",
    "ctaText": "Read the article"
  },
  "linkedContentId": "bp_***",
  "purpose": "og"
}
FieldTypeRequiredNotes
templateIdstringyesSlug of the template
dataobjectyesMust match the template's input schema
linkedContentIdstringnoLink the image to a blog post or landing page for organization
purposeenumnoog, social, featured, inline, cta, custom
formatenumnopng (default), jpg, webp
width / heightnumbernoDefaults per template

Response

{
  "imageId": "img_***",
  "templateId": "acme-og-card",
  "url": "https://cdn.citationbench.com/images/img_***.png",
  "width": 1200,
  "height": 630,
  "format": "png",
  "sizeBytes": 84320,
  "linkedContentId": "bp_***",
  "purpose": "og",
  "createdAt": "2026-05-24T08:15:00Z"
}

Synchronous — no invocation handle, since image generation is sub-second.


POST /v1/produce/image/bulk

curl -X POST .../v1/produce/image/bulk -d '{
  "templateId": "acme-og-card",
  "items": [
    { "data": { "title": "Article A", "tag": "Performance" }, "linkedContentId": "bp_A" },
    { "data": { "title": "Article B", "tag": "Performance" }, "linkedContentId": "bp_B" }
  ]
}'

Returns an array of generated images.


GET /v1/produce/image

curl -G .../v1/produce/image \
  --data-urlencode "linkedContentId=bp_***" \
  --data-urlencode "purpose=og"

GET /v1/produce/image/templates

curl .../v1/produce/image/templates
{
  "data": [
    {
      "id": "acme-og-card",
      "name": "Acme OG card",
      "description": "1200×630 OG/Twitter card with brand styling",
      "width": 1200,
      "height": 630,
      "purposes": ["og", "social"],
      "inputSchema": {
        "type": "object",
        "required": ["title"],
        "properties": {
          "title": { "type": "string", "maxLength": 80 },
          "subhead": { "type": "string", "maxLength": 140 },
          "tag": { "type": "string", "maxLength": 24 },
          "ctaText": { "type": "string", "maxLength": 24 }
        }
      },
      "sampleUrl": "https://cdn.citationbench.com/templates/sample/acme-og-card.png"
    },
    {
      "id": "acme-featured",
      "name": "Acme featured image",
      "...": "..."
    }
  ],
  "total": 42
}

POST /v1/produce/image/templates/{slug}/fork

curl -X POST .../v1/produce/image/templates/system.og-card/fork -d '{
  "id":        "acme-og-card",
  "overrides": {
    "logoUrl":   "https://acme.com/logo.svg",
    "palette":   { "primary": "#0070f3", "background": "#ffffff" },
    "font":      "Inter"
  }
}'

Creates a workspace-scoped customized version.


MCP

> Generate an OG image for bp_*** using the standard OG template.

Claude calls produce.blog_post.get (to fetch the title), then produce.image.create.

> Show me my image template library.

Claude calls produce.image.templates.list.


Errors

StatusCodeCause
400validation_errordata failed the template's input schema
404template_not_found
422text_too_longA text field exceeded the template's safe rendering width

Cost

ActionCredits
Per image1
Bulk per image1
Template CRUDfree

Use cases (string things together)

A. Auto-generate OG image for every published blog post

Pillar default refiners include rfn_og-image (a MULTI_IMAGE_REFINER); every blog post gets an OG card without you asking.

B. Per-section in-line illustrations

A MULTI_IMAGE_REFINER can read the article's outline and pick illustration templates per section.

C. Programmatic CTA cards

for OFFER in starter pro enterprise; do
  curl -X POST .../v1/produce/image -d "{
    \"templateId\": \"acme-cta\",
    \"data\":       { \"offer\": \"$OFFER\", \"ctaText\": \"Start free\" }
  }"
done

D. Fork the system OG template, customize once, ship everywhere

curl -X POST .../v1/produce/image/templates/system.og-card/fork -d '{
  "id": "acme-og-card",
  "overrides": { "logoUrl": "...", "palette": { ... } }
}'

# Now every reference to acme-og-card uses your customized version.

On this page