Concepts · Collections

Collections

Some things Esy makes are made of other things: a clip art pack is a set of pieces with a cover, a story book is a run of pages. A collection is that whole, owned by Esy. Its members keep their ids through every re-roll, every piece of work lands on a member by id, and the cover, publishing and cost are read from the whole — never from whichever order happened to run last.

In rollout

This page describes the model being built now, packs first. The packs API reference ships on this site with the endpoints. Until then packs are still placed as Generation Orders, as in Publish packs with a worker team, and existing integrations keep working unchanged while clients move over.

Collection, order, or artifact?

These three are easy to confuse, and the difference decides how you read everything else.

What it isLivesExample
ArtifactOne made thingForeverA bear sticker
OrderOne batch of work Esy executesUntil it settles“Draw these 12 prompts”
CollectionOne named thing made of many artifacts, redone piece by piece over many ordersForeverThe “Beach Bears” pack

If it has its own title or cover, its members can be redone one at a time, and it outlives the order that started it, it is a collection. An order is never a collection: a pack with one re-roll already spans two orders.

What a collection holds

a pack, drawn as a treeascii
collection  pack-7f3a91c2 · "Beach Bears" · kind pack · format clipart
├─ spec          brief, style kit (slug + the version used), render settings
├─ cover         artifact
├─ delivery      unpublished | published | partial | failed
├─ etag          "42"  — changes whenever the collection or a member changes
└─ items
   ├─ pitem-91c2  "Bear with a water gun"   accepted  → current + print
   │   └─ attempts   order-…/run-…  failed  $0.11
   │                 order-…/run-…  completed  $0.11
   ├─ pitem-4b07  "Bear on a surfboard"     review    → current artifact
   └─ pitem-c3e1  "Bear on a surfboard" B&W companionOf pitem-4b07
PartWhat it is for
kindWhat sort of collection: pack today, story-book next. Each kind has its own route and its own words.
specThe kind’s settings, checked against the kind’s schema. Library references are stored with the version they resolved to, so editing a style kit later never changes how an existing pack was made.
itemsThe members. Each has an id that never changes — renaming, re-rolling or reordering keeps it.
attemptsEvery time Esy tried to make a member: the order and run, the outcome, and what it cost.
etagA version tag. Edits send it back; if someone changed the collection in between, the edit is refused with 409 and the current collection, instead of silently overwriting their change.
clientRefYour own id for it, unique per workspace. Creating with the same clientRef twice returns the one collection.
annotationsSmall key-values of yours that Esy stores and returns but never interprets.

Lifecycle

statuses shared by every kindascii
collection   planning → ready → working → review → complete
             + attention (something failed or a budget stopped)
             + failed (planning failed) · archived

item         pending → working → review → accepted
             + failed · removed (restorable) · locked (planned, not unlocked)

Publishing is tracked apart from status, in delivery, so a complete collection can be published, taken down, and published again without its status moving.

Working on a collection

You read and edit a collection like any resource. Anything that does work or spends money is a named action on it, written {collection}:verb, so a rename and a render never look alike in your logs or your bill.

ActionWhat happens
:renderEsy makes every pending member, or only the ones you list (a re-roll). It places the orders itself and tags each job with its member.
items/…:accept · :rejectKeep a member’s result, or send it back to pending.
:makeCover · :makeSheetBuild the cover or a contact sheet from accepted members.
:exportPrintMake print-size renditions of accepted members.
:publish · :unpublishDeliver the whole collection to its outlet, or take it down.
:archiveHide it from lists. Nothing is deleted.

Every action takes a requestId: send the same one again after a timeout and you get the first result back, not a second render and a second bill. Every action that starts work returns what it started — the orders, the members covered, the attempt ids and the budget cap — so you can charge, and refund a failed attempt, exactly once.

Knowing when something changed

Esy calls you rather than making you poll. Events are thin: they say which collection changed and its new version, and you read the collection for the rest. A late event for a version you have already seen is safe to ignore.

an eventjson
{
  "type": "pack.updated",
  "resource": { "type": "pack", "id": "pack-7f3a91c2", "version": 43 },
  "clientRef": "cp_2f1a…",
  "occurredAt": "2026-09-17T14:03:11Z"
}

Deliveries are signed exactly like every other Esy webhook — see Webhooks — and may arrive more than once, so dedupe on webhook-id. To catch anything a long outage missed, list with updatedAfter every few minutes rather than every few seconds.

What stays with your app

Esy owns the collection; your app asks for work and shows what Esy returns. What stays yours is what is genuinely your business: your customers, prices, credits and checkout. For free previews the line is the same — you decide how many a customer gets, and Esy counts previews against the customer reference you send, so a new pack or a retry cannot reset the count.

Kinds

KindMembersStatus
packPieces — clip art, coloring pages or illustrations — plus a coverFirst, in rollout
story-bookPages, drawing on a pack for its charactersNext
In short
  • A collection is one named thing made of many artifacts; an order is one batch of work toward it.
  • Members keep their ids through every re-roll, and results land on them by id.
  • Work is a named action with a requestId; edits carry the etag.
  • Esy tells you something changed; you read the collection to see what.