---
title: "Generate a cover from reference images (async)"
method: POST
path: "/api/v1/covers/generate-reference"
tags: ["Covers"]
---

# Generate a cover from reference images (async)

`POST /api/v1/covers/generate-reference`

## Request

- Base URL: `https://beyourcover.com`
- URL: `https://beyourcover.com/api/v1/covers/generate-reference`
- Auth: HTTP bearer

Generates a NEW cover for a book from 1-4 reference images plus art direction. A vision model reads the references and writes a self-contained prompt which the text-to-image chain renders — the image model never receives the reference images, so the output is an original cover in the referenced style, not a derivative. Costs 1 credit. References come from `POST /api/v1/uploads` (`reference_upload_ids`) and/or existing covers in the account (`reference_cover_ids`). Uploads are size-, dimension-, and content-checked, and instructions are moderated, all before the credit is reserved. Covers produced this way have a null `coverStyle` (they sit outside the template system).

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `bookId` string, uuid, required: The book the new cover belongs to.
  - `instructions` string, required: Art direction: what to take from the references and what to change.
  - `reference_upload_ids` string[]: upload_ids from POST /api/v1/uploads. Combined with reference_cover_ids, 1-4 total.
  - `reference_cover_ids` string[]: Public coverIds of existing covers to use as references. Combined with reference_upload_ids, 1-4 total.
  - `external_ref` string: Optional caller-supplied reference, echoed on the job and webhooks.
  - `webhookUrl` string: Optional per-job webhook URL.

## 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 `generate_reference`.
- `400`: `code` is one of: `missing_instructions`, `missing_reference_images`, `too_many_reference_images`, `invalid_upload`, `upload_not_found`, `file_too_large`, `file_too_small`, `invalid_image_dimensions`, `reference_cover_not_found`, `invalid_field_type`, `field_too_long`, `content_policy_violation` (a reference image or the instructions were blocked). No credit is reserved for any of these.
- `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`: `code` is `book_not_found` (book missing or not owned) or `reference_cover_not_found` (a referenced cover is missing, not owned, or an unpurchased premade cover).
- `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`. The reserved credit is 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)
