---
title: "Generate variations of an existing cover (async)"
method: POST
path: "/api/v1/covers/{coverId}/variations"
tags: ["Covers"]
---

# Generate variations of an existing cover (async)

`POST /api/v1/covers/{coverId}/variations`

## Request

- Base URL: `https://beyourcover.com`
- URL: `https://beyourcover.com/api/v1/covers/{coverId}/variations`
- Auth: HTTP bearer

Re-renders the source cover's stored prompt to produce `count` new covers of the same book; the renders run in parallel. Each variation is a top-level cover with no lineage link to the source. Costs `count` credits (unused credits refunded on partial/total failure). The MCP tool `create_cover_variations` runs the same operation. The source cover must have an associated prompt (`missing_prompt` otherwise).

## Path parameters

- `coverId` string, uuid, required

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `count` integer: Number of variations to generate (1-5). 1 credit each.
  - `external_ref` string: Optional caller-supplied reference. (Length/type limits are not enforced on this endpoint in code.)
  - `webhookUrl` string: Optional per-job webhook URL. (Length/type limits are not enforced on this endpoint in code.)

## Response `200`

Idempotent replay of an existing job with the same `Idempotency-Key`.

- JobReplay: 200 envelope returned when an Idempotency-Key matches an existing job. Unlike the fresh 202, `status` reflects the job's current state and `operation` is always present.
  - `jobId` string, uuid, required
  - `status` 'queued' | 'processing' | 'completed' | 'failed', required: Current status of the previously created job.
  - `operation` 'generate' | 'variation' | 'edit_image' | 'upscale' | 'audiobook_cover' | 'remove_text' | 'generate_reference' | 'wrap' | 'wrap_extend_front', required
  - `credits_reserved` integer: What the ORIGINAL job reserved. Returned by the variations, edit-image, upscale, audiobook-cover, remove-text, wraps and extend-front endpoints when the job recorded it.
  - `included_format` boolean: true when the book's marketing kit paid for the ORIGINAL job instead of credits. Returned by the edit-image, upscale, audiobook-cover, remove-text, wraps and extend-front endpoints.
  - `external_ref` string, nullable, required: The external_ref stored on the ORIGINAL job.
  - `created_at` string, date-time, required
  - `poll_url` string, required

## Other responses

- `202`: Job accepted and queued. `operation` is `variation`.
- `400`: `code` is one of: `invalid_count`, `missing_prompt` (the cover has no associated prompt).
- `401`: Missing/malformed API key, unknown or inactive key, or inactive subscription detected during credit checks. `code`: `unauthorized`.
- `402`: Not enough credits (monthly + overage) for the requested operation. `code`: `insufficient_credits`.
- `403`: The API key is valid but its owner has no active enterprise subscription. `code`: `forbidden`.
- `404`: Cover not found or not owned by this API key's user. `code`: `cover_not_found`.
- `429`: The subscription's concurrent-job limit is reached (jobs with status `queued` or `processing` count). `code`: `concurrency_limit`.
- `500`: Server error. `code` is `job_creation_failed` or `internal_error`. Reserved credits are refunded.

---

[API](https://skmtc.dev/beyourcover/apis/beyourcover-partner-api.md) · [All operations](https://skmtc.dev/beyourcover/apis/beyourcover-partner-api/llms.txt) · [OpenAPI document](https://skmtc.dev/beyourcover/apis/beyourcover-partner-api/revisions/82ad2c7c8ede?raw)
