Send an offer
Resolves the audience (explicit contacts, a static list's members, and/or ad-hoc emails), snapshots each work's price, mints a per-recipient tokenized link, enqueues the sends, and flips the offer to `sending`. The dispatch worker delivers each email asynchronously.
Resolves the audience (explicit contacts, a static list's members, and/or ad-hoc emails), snapshots each work's price, mints a per-recipient tokenized link, enqueues the sends, and flips the offer to sending. The dispatch worker delivers each email asynchronously.
Authorization
bearerAuth offers:createA gallery API key, sent as Authorization: Bearer gpk_… (or the x-api-key header).
In: header
Scope: offers:create
Path Parameters
Query Parameters
Preview this operation without committing it. When true, the request is authenticated, scoped, and validated, but no side effect runs — no write, no idempotency claim, no audit event, no outbound delivery. The response is HTTP 200 with an X-Dry-Run: true header and a body of { "dry_run": true }, plus an effect object describing what the real call would change when this operation can resolve one.
Header Parameters
Optional. Send a unique key per logical operation to make retries safe: a retry with the same key replays the stored success for 14 days instead of re-running the write. Reusing a key with a different body returns 400.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Resolve recipients and start sending an offer.
Response Body
application/json
application/json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
{ "dry_run": true, "effect": { "summary": "string", "count": 0, "targets": [ { "type": "string", "id": "string", "label": "string" } ], "amount": { "minor": -9007199254740991, "currency": "str" }, "details": { "property1": "string", "property2": "string" }, "irreversible": true }}{ "id": "string", "title": "string", "subject": "string", "intro": "string", "template_id": "string", "status": "draft", "track_engagement": true, "scheduled_at": "string", "sent_at": "string", "cc_emails": [ "string" ], "bcc_emails": [ "string" ], "created_by": "string", "metadata": { "property1": "string", "property2": "string" }, "created_at": "string", "updated_at": "string", "items": [ { "offer_id": "string", "artwork_id": "string", "position": -9007199254740991, "caption_override": "string", "price_shown_cents": -9007199254740991, "currency": "string", "price_visible": true, "created_at": "string" } ], "recipients": [ { "id": "string", "offer_id": "string", "contact_id": "string", "email": "string", "expires_at": "string", "delivery_status": "pending", "sent_at": "string", "first_opened_at": "string", "last_activity_at": "string", "open_count": -9007199254740991, "click_count": -9007199254740991, "created_at": "string" } ]}{ "type": "../dictionary", "title": "string", "status": 0, "detail": "string", "code": "string", "retry": "permanent", "details": null}{ "type": "../dictionary", "title": "string", "status": 0, "detail": "string", "code": "string", "retry": "permanent", "details": null}{ "type": "../dictionary", "title": "string", "status": 0, "detail": "string", "code": "string", "retry": "permanent", "details": null}{ "type": "../dictionary", "title": "string", "status": 0, "detail": "string", "code": "string", "retry": "permanent", "details": null}{ "type": "../dictionary", "title": "string", "status": 0, "detail": "string", "code": "string", "retry": "permanent", "details": null}{ "type": "../dictionary", "title": "string", "status": 0, "detail": "string", "code": "string", "retry": "permanent", "details": null}List offers GET
Lists the gallery's offers with cursor pagination. Filter by `status`, fetch an explicit set with `ids` (comma-separated, max 50), and sort by created/updated/sent.
Suggest an offer subject line POST
Suggests an email subject line for an offer from its title, work count, and the gallery name. Read-shaped: it returns a suggestion and writes nothing (the sender edits it before saving). The model loop is server-only (the key never reaches the browser) with a deterministic template fallback; requires a first-party session.