Who am IGET /v1/me
Returns the workspace this key belongs to, its plan, remaining AI credits, connected channels and suppliers, and the scopes this key holds. Call it first to learn what you're allowed to do.
Returns 200 Me
Developers · API v1.0.0
Everything in the app (templates, previews, print files, products across suppliers, mockups, Etsy and Shopify listings, the order queue, Radar and analytics) is one REST API and one MCP server. On every plan, not just Enterprise.
Create an API key in Settings → Developers, pick its scopes, then:
curl https://api.pod-os.com/v1/me \
-H "Authorization: Bearer $POD_API_KEY"# 1. This week's opportunities
curl "https://api.pod-os.com/v1/radar/cards?limit=3" -H "Authorization: Bearer $POD_API_KEY"
# 2. Template from a starter (free) or a prompt (AI credits)
curl -X POST https://api.pod-os.com/v1/templates \
-H "Authorization: Bearer $POD_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"source":{"type":"prompt","prompt":"watercolor pet memorial ornament","variations":4}}'
# 3. Freeze a version, then put it on blanks from several suppliers
curl -X POST https://api.pod-os.com/v1/templates/tpl_123/versions -H "Idempotency-Key: $(uuidgen)" ...
curl -X POST https://api.pod-os.com/v1/products -H "Idempotency-Key: $(uuidgen)" ... \
-d '{"template_id":"tpl_123","targets":[{"product_type":"ornament-round"},{"product_type":"mug-11oz","supplier":"gelato"}]}'The MCP server lives at https://mcp.pod-os.com/mcp. It speaks Streamable HTTP and OAuth 2.1 (PKCE, dynamic client registration), so clients that support remote MCP connect with just the URL. Clients without OAuth send an API key as a bearer token. Tools that publish, approve orders, refund, message buyers or spend AI credits take a confirm argument. Without confirm: true they return a preview and change nothing, so the agent has to ask you first.
Settings → Connectors → Add custom connector → paste the URL → Connect. Approve the scopes on the POD OS consent screen. Works in Claude.ai, Claude Desktop and Claude Code:
claude mcp add --transport http pod-os https://mcp.pod-os.com/mcpSettings → Apps & Connectors → Advanced → Developer mode, then Create → MCP server URL https://mcp.pod-os.com/mcp, authentication OAuth. The search and fetch tools make the workspace usable in deep research too.
{
"mcpServers": {
"pod-os": {
"httpUrl": "https://mcp.pod-os.com/mcp",
"headers": { "Authorization": "Bearer $POD_API_KEY" }
}
}
}{
"type": "mcp",
"server_url": "https://mcp.pod-os.com/mcp",
"server_label": "pod-os",
"authorization": "Bearer $POD_API_KEY"
}Prompts included: Launch a product from an idea and Review today's orders. Resources: pod://templates/…, pod://products/…, pod://orders/…, the catalog and the agent guide.
Keys belong to one workspace and carry scopes. Send Authorization: Bearer pod_live_…. Keys are stored hashed; you see the secret once. OAuth connectors get at most the scopes you tick, and publishing and order approval are separate scopes so you can hand an agent “draft everything, publish nothing”.
| workspace:read | See the workspace name, plan and the scopes of this key. |
| templates:read | List and read templates, versions and starter designs. |
| templates:write | Create, edit and version templates (prompt-generated templates use AI credits). |
| renders:write | Render previews and queue print files. |
| products:read | List products and the supplier catalog. |
| products:write | Create products across suppliers, auto-fit designs and render mockups. |
| listings:read | Read listing drafts and published listings. |
| listings:write | Generate and edit listing copy. |
| listings:publish | Publish listings to Etsy and Shopify (public, may incur marketplace fees). |
| orders:read | List and read orders and their pre-flight results. |
| orders:write | Approve, reject and send proofs for orders (approval sends paid work to suppliers). |
| radar:read | Read Radar opportunity cards. |
| analytics:read | Read sales and conversion analytics. |
| webhooks:manage | Create, list and delete webhook endpoints. |
Every POST, PATCH and DELETE needs an Idempotency-Key header (8–255 chars, a UUID works). Retrying with the same key and body returns the first response with Idempotent-Replayed: true. The same key with a different body returns 422 idempotency_key_reused. Keys last 24 hours, per workspace.
Lists return { data, has_more, next_cursor }, newest first. Pass next_cursor as cursor. limit is 1–100, default 20. Cursors are keyset-based, so pages stay stable while new rows arrive.
Per key (120 requests a minute by default, set per key). Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset; a 429 adds Retry-After.
{ "error": { "code": "insufficient_scope", "message": "This key is missing scope(s): orders:write",
"details": { "missing": ["orders:write"] }, "request_id": "req_…" } }Codes: unauthorized, insufficient_scope, not_found, validation_error, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, rate_limited, conflict, internal_error.
Print renders, mockups and publishing return 202 with a job. Poll it or subscribe to the webhook. Print files are content-addressed: the same template version and inputs never render twice.
Events: template.created, template.version_created, render.succeeded, render.failed, product.created, mockups.succeeded, listing.published, listing.failed, order.created, order.approved, order.rejected, order.proof_sent.
Each delivery is signed: Pod-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, t + "." + rawBody)>. Return a 2xx within 10 seconds; failures retry after 30 s, 2 min, 10 min and 1 h. De-duplicate by Pod-Event-Id.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret: string, rawBody: string, header: string) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false; // replay window
const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest();
const got = Buffer.from(parts.v1 ?? "", "hex");
return got.length === expected.length && timingSafeEqual(got, expected);
}GET /v1/meReturns the workspace this key belongs to, its plan, remaining AI credits, connected channels and suppliers, and the scopes this key holds. Call it first to learn what you're allowed to do.
Returns 200 Me
GET /v1/startersProven starter designs (family ornament, pet portrait, teacher tumbler…). Pass a starter id to create_template with source.type=starter.
| limit | integer 1–100 | query. Page size, 1-100. Default 20. Default 20. |
| cursor | string | query. Opaque cursor from the previous page's next_cursor. |
| niche | string ≤80 | query. Filter by niche, e.g. christmas. |
| product_type | string ≤64 | query. Catalog product type, e.g. tee, mug-11oz, ornament-round, tumbler-20oz. See list_catalog. |
Returns 200 { data: Starter[], has_more, next_cursor }
GET /v1/templatesThe workspace's templates, newest first. Filter by text or status. Cursor-paginated.
| limit | integer 1–100 | query. Page size, 1-100. Default 20. Default 20. |
| cursor | string | query. Opaque cursor from the previous page's next_cursor. |
| q | string ≤120 | query. Search name and tags. |
| status | "draft" | "generating" | "ready" | "archived" | query. |
Returns 200 { data: Template[], has_more, next_cursor }
POST /v1/templatesCreate a template from a design prompt (AI generates artwork variations; uses one AI credit per variation and finishes in the background: status goes generating → draft), from a starter, from a PSD URL, or blank for a product type. Next: update_template to pick a variation and set fields, then create_template_version.
| name | string ≤120 | Defaults to a name derived from the source. |
| source * | object | object | object | object | One of the variants below.
|
| product_types | string ≤64[] | Products this design targets. Defaults from the source. |
Returns 201 Template
GET /v1/templates/{template_id}One template with its personalization fields, product types, AI variations and latest version number.
| template_id * | string | path. ID, prefixed tpl_. |
Returns 200 Template
PATCH /v1/templates/{template_id}Edit the working draft: name, personalization fields, product types, tags, chosen AI variation, status. Live products keep their pinned version until you cut a new one.
| template_id * | string | path. ID, prefixed tpl_. |
| name | string ≤120 | |
| personalization_fields | object[] | |
| product_types | string ≤64[] | |
| tags | string ≤40[] | |
| selected_variation | integer 0–7 | Pick one AI variation as the artwork. |
| status | "ready" | "archived" |
Returns 200 Template
POST /v1/templates/{template_id}/versionsFreeze the current draft as an immutable, numbered version. Print renders and products pin a version, so edits never change what's already selling.
| template_id * | string | path. ID, prefixed tpl_. |
| note | string ≤500 | Change note, e.g. "bigger name text". |
Returns 201 TemplateVersion
GET /v1/templates/{template_id}/versionsAll immutable versions of a template, newest first.
| template_id * | string | path. ID, prefixed tpl_. |
Returns 200 { data: TemplateVersion[] }
POST /v1/templates/{template_id}/previewSynchronous low-res preview (≤1024 px) of a template with buyer inputs, plus pre-flight warnings (overflow, low-res photo, profanity, trademark). Free; use it to check a design before cutting a version or queueing a print file.
| template_id * | string | path. ID, prefixed tpl_. |
| inputs | object | Buyer choices keyed by personalization field key, e.g. {"name": "Luna"}. Photo fields take an HTTPS URL. Default {}. |
| version | integer 1–9007199254740991 | Template version. Defaults to the working draft. |
| product_type | string ≤64 | Catalog product type, e.g. tee, mug-11oz, ornament-round, tumbler-20oz. See list_catalog. |
| width | integer 64–1024 | Preview width in px (low-res, max 1024). Default 512. |
Returns 200 Preview
POST /v1/rendersQueue a full-resolution print file for a pinned template version, product type and surface. Returns immediately (202) with a job; poll get_render or listen for the render.succeeded webhook. Identical inputs return the same content-addressed file.
| template_id * | string | ID, prefixed tpl_. |
| version * | integer 1–9007199254740991 | Pinned template version. Print files always render from an immutable version. |
| inputs | object | Buyer choices keyed by personalization field key, e.g. {"name": "Luna"}. Photo fields take an HTTPS URL. Default {}. |
| product_type * | string ≤64 | Catalog product type, e.g. tee, mug-11oz, ornament-round, tumbler-20oz. See list_catalog. |
| surface | string ≤40 | Print surface, e.g. front, back, sleeve, wrap. Default "front". |
| format | "png" | "pdf" | Default "png". |
Returns 202 RenderJob
GET /v1/renders/{render_id}Status of a print render. file_url is set when status is succeeded.
| render_id * | string | path. ID, prefixed rnd_. |
Returns 200 RenderJob
GET /v1/catalogProduct types you can sell, with each supplier's base cost, delivery time, regions and print surfaces (size in mm, DPI).
Returns 200 { data: CatalogItem[] }
GET /v1/productsProducts (a template on a specific blank from a specific supplier), newest first.
| limit | integer 1–100 | query. Page size, 1-100. Default 20. Default 20. |
| cursor | string | query. Opaque cursor from the previous page's next_cursor. |
| template_id | string | query. ID, prefixed tpl_. |
| supplier | "printify" | "printful" | "gelato" | "own" | query. Print partner. own = the seller prints in-house. |
Returns 200 { data: Product[], has_more, next_cursor }
POST /v1/productsPut one template on many blanks at once (e.g. tee from Printify, mug from Gelato). Each target becomes a product; auto_fit fits the design to every surface. Nothing is published or ordered yet. Next: create_mockups, then generate_listing.
| template_id * | string | ID, prefixed tpl_. |
| template_version | integer 1–9007199254740991 | Defaults to the latest version. |
| targets * | object[] | |
| auto_fit | boolean | Fit the design to every surface of every product. Default true. |
Returns 201 { data: Product[] }
GET /v1/products/{product_id}One product with variants, price, base cost, fit report and mockups.
| product_id * | string | path. ID, prefixed prd_. |
Returns 200 Product
POST /v1/products/{product_id}/auto-fitRe-fit the design to the product's print surfaces (contain, cover or stretch). The fit report flags clipping and effective DPI.
| product_id * | string | path. ID, prefixed prd_. |
| mode | "contain" | "cover" | "stretch" | Default "contain". |
| surfaces | string[] | Defaults to every surface of the product. |
Returns 200 Product
POST /v1/products/{product_id}/mockupsRender mockups from the real print file: flat, lifestyle, model, gift and close-up scenes per color. media_kit=true also renders the lead image, how-it-works panel and a 12-second video (5 AI credits). Async (202): poll get_mockup_job or wait for mockups.succeeded.
| product_id * | string | path. ID, prefixed prd_. |
| scenes | "flat" | "lifestyle" | "model" | "gift" | "closeup"[] | Default ["flat","lifestyle"]. |
| colors | string ≤40[] | Product colors to render. Defaults to the first variant color. |
| media_kit | boolean | Also render lead image with badges, how-it-works panel and a 12-second video (uses AI credits). Default false. |
Returns 202 MockupJob
GET /v1/mockups/{mockup_job_id}Status and image URLs of a mockup job.
| mockup_job_id * | string | path. ID, prefixed mkj_. |
Returns 200 MockupJob
GET /v1/listingsListing drafts and published listings, newest first.
| limit | integer 1–100 | query. Page size, 1-100. Default 20. Default 20. |
| cursor | string | query. Opaque cursor from the previous page's next_cursor. |
| status | "draft" | "publishing" | "published" | "failed" | query. |
| channel | "etsy" | "shopify" | query. Sales channel. |
Returns 200 { data: Listing[], has_more, next_cursor }
POST /v1/listingsWrite a listing draft for a product: title (≤140 chars), 13 tags (≤20 chars each) and description from Radar keywords and your brand profile, with a trademark check. Creates a draft only; nothing goes live until publish_listing.
| product_id * | string | ID, prefixed prd_. |
| channel * | "etsy" | "shopify" | Sales channel. |
| keywords | string ≤60[] | Target search phrases. Defaults to Radar keywords for the template niche. |
| niche | string ≤120 | Buyer niche or occasion, e.g. "nurse graduation gift". |
| tone | "warm" | "playful" | "minimal" | "premium" | Default "warm". |
Returns 201 Listing
GET /v1/listings/{listing_id}One listing with copy, price, trademark check and channel URL once published.
| listing_id * | string | path. ID, prefixed lst_. |
Returns 200 Listing
PATCH /v1/listings/{listing_id}Change title, tags, description or price of a draft. The trademark check re-runs on every edit.
| listing_id * | string | path. ID, prefixed lst_. |
| title | string ≤140 | |
| tags | string ≤20[] | |
| description | string ≤10000 | |
| price_cents | integer 100–1000000 |
Returns 200 Listing
POST /v1/listings/{listing_id}/publishPublish a draft to Etsy or Shopify with personalization fields mapped. Public, and Etsy charges its listing fee. Refused while the trademark check fails. Async: status goes publishing → published (listing.published webhook).
| listing_id * | string | path. ID, prefixed lst_. |
| quantity | integer 1–999 | Default 999. |
| as_draft_on_channel | boolean | Create it on Etsy/Shopify as an inactive draft instead of live. Default false. |
Returns 202 Listing
GET /v1/ordersOrders newest first. status=needs_review is the review queue; each order carries its pre-flight result (clean, warnings, blocked).
| limit | integer 1–100 | query. Page size, 1-100. Default 20. Default 20. |
| cursor | string | query. Opaque cursor from the previous page's next_cursor. |
| status | "needs_review" | "approved" | "in_production" | "shipped" | "rejected" | "cancelled" | query. |
| channel | "etsy" | "shopify" | query. Sales channel. |
Returns 200 { data: Order[], has_more, next_cursor }
GET /v1/orders/{order_id}One order with buyer inputs, pinned template versions, pre-flight issues, supplier and proof status.
| order_id * | string | path. ID, prefixed ord_. |
Returns 200 Order
POST /v1/orders/{order_id}/approveApprove an order in the review queue: the print file renders and the order is sent to the supplier, which charges your supplier account. Orders with warnings need override_warnings=true; blocked orders can't be approved.
| order_id * | string | path. ID, prefixed ord_. |
| supplier | "printify" | "printful" | "gelato" | "own" | "auto" | auto lets the router choose (cheapest / fastest / EU-local per your rules). Default "auto". |
| override_warnings | boolean | Approve even when pre-flight shows warnings. Blocked orders can't be approved. Default false. |
Returns 200 Order
POST /v1/orders/approveApprove up to 100 orders at once. Orders with warnings or blocks are skipped (with the reason), never force-approved.
| order_ids * | string[] | |
| supplier | "printify" | "printful" | "gelato" | "own" | "auto" | Default "auto". |
Returns 200 BatchApproveResult
POST /v1/orders/{order_id}/rejectTake an order out of production. With refund=true it is also cancelled and refunded on the channel; that can't be undone.
| order_id * | string | path. ID, prefixed ord_. |
| reason * | string ≤500 | Shown in the audit log, and to the buyer if notify_buyer is true. |
| notify_buyer | boolean | Default false. |
| refund | boolean | Also cancel and refund on Etsy/Shopify. Default false. |
Returns 200 Order
POST /v1/orders/{order_id}/proofEmail / Etsy-message the buyer a proof of the exact print before production. The order waits for their approval.
| order_id * | string | path. ID, prefixed ord_. |
| message | string ≤1000 | Note to the buyer sent with the proof. |
Returns 200 Order
GET /v1/radar/cardsThis week's opportunity cards for the workspace's niches: demand and competition scores (0-100), launch-by date, risk, keywords, suggested product types and a ready-made prompt for create_template.
| limit | integer 1–100 | query. Page size, 1-100. Default 20. Default 20. |
| cursor | string | query. Opaque cursor from the previous page's next_cursor. |
| niche | string ≤80 | query. |
| risk | "low" | "medium" | "high" | query. |
Returns 200 { data: RadarCard[], has_more, next_cursor }
GET /v1/radar/cards/{card_id}One opportunity card.
| card_id * | string | path. ID, prefixed rdr_. |
Returns 200 RadarCard
GET /v1/analytics/summaryOrders, revenue, supplier cost, margin, AOV, views and conversion for a date range (default last 30 days), plus top templates.
| from | string | query. YYYY-MM-DD, inclusive. Defaults to 30 days ago. |
| to | string | query. YYYY-MM-DD, inclusive. Defaults to today. |
Returns 200 AnalyticsSummary
GET /v1/analytics/templatesViews, orders, conversion, revenue and AOV per template, sorted by revenue, orders or conversion.
| from | string | query. YYYY-MM-DD, inclusive. Defaults to 30 days ago. |
| to | string | query. YYYY-MM-DD, inclusive. Defaults to today. |
| sort | "revenue" | "orders" | "conversion" | query. Default "revenue". |
| limit | integer 1–100 | query. Default 20. |
Returns 200 { data: TemplateStats[] }
GET /v1/webhook-endpointsEndpoints that receive signed event deliveries. Secrets are never returned after creation.
Returns 200 { data: WebhookEndpoint[] }
POST /v1/webhook-endpointsSubscribe an HTTPS URL to events. The response includes the signing secret once; every delivery carries Pod-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, t + "." + body)>.
| url * | string | HTTPS URL that receives POSTed events. |
| events * | "template.created" | "template.version_created" | "render.succeeded" | "render.failed" | "product.created" | "mockups.succeeded" | "listing.published" | "listing.failed" | "order.created" | "order.approved" | "order.rejected" | "order.proof_sent"[] | Event types to deliver. |
| description | string ≤200 |
Returns 201 WebhookEndpoint
DELETE /v1/webhook-endpoints/{endpoint_id}Stop deliveries to an endpoint.
| endpoint_id * | string | path. ID, prefixed whe_. |
Returns 200 Deleted
| workspace_id * | string | |
| workspace_name * | string | |
| plan * | "free" | "starter" | "pro" | "scale" | |
| ai_credits_remaining * | integer -9007199254740991–9007199254740991 | |
| scopes * | "workspace:read" | "templates:read" | "templates:write" | "renders:write" | "products:read" | "products:write" | "listings:read" | "listings:write" | "listings:publish" | "orders:read" | "orders:write" | "radar:read" | "analytics:read" | "webhooks:manage"[] | |
| auth * | "api_key" | "oauth" | |
| connected_channels * | "etsy" | "shopify"[] | |
| connected_suppliers * | "printify" | "printful" | "gelato" | "own"[] |
| key * | string | Stable key used in render inputs, e.g. name. |
| label * | string ≤80 | What the buyer sees, e.g. "Pet's name". |
| type * | "text" | "date" | "photo" | "choice" | "color" | "number" | |
| required * | boolean | Default true. |
| max_length | integer 1–500 | Text fields only. |
| options | string ≤80[] | Choice fields only. |
| id * | string | ID, prefixed tpl_. |
| object * | "template" | |
| name * | string | |
| status * | "draft" | "generating" | "ready" | "archived" | |
| source * | "prompt" | "starter" | "psd" | "blank" | |
| product_types * | string ≤64[] | |
| personalization_fields * | PersonalizationField[] | |
| current_version * | integer -9007199254740991–9007199254740991 | null | Latest immutable version, or null until the first version is cut. |
| preview_url * | string | null | |
| variations * | object[] | AI artwork variations (prompt templates). |
| tags * | string[] | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| updated_at * | string | ISO 8601 timestamp, UTC. |
| object * | "template_version" | |
| template_id * | string | ID, prefixed tpl_. |
| version * | integer 1–9007199254740991 | |
| note * | string | null | |
| doc_hash * | string | sha256 of the frozen template document. |
| created_at * | string | ISO 8601 timestamp, UTC. |
| id * | string | ID, prefixed str_. |
| object * | "starter" | |
| name * | string | |
| niche * | string | |
| product_types * | string ≤64[] | |
| preview_url * | string | |
| personalization_fields * | PersonalizationField[] | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| object * | "preview" | |
| template_id * | string | ID, prefixed tpl_. |
| version * | integer -9007199254740991–9007199254740991 | null | |
| image_url * | string | PNG/SVG data URL or signed URL, valid 1 hour. |
| width * | integer -9007199254740991–9007199254740991 | |
| height * | integer -9007199254740991–9007199254740991 | |
| warnings * | object[] | Pre-flight warnings: overflow, low-res photo, profanity… |
| id * | string | ID, prefixed rnd_. |
| object * | "render" | |
| status * | "queued" | "running" | "succeeded" | "failed" | |
| template_id * | string | ID, prefixed tpl_. |
| version * | integer -9007199254740991–9007199254740991 | |
| product_type * | string ≤64 | Catalog product type, e.g. tee, mug-11oz, ornament-round, tumbler-20oz. See list_catalog. |
| surface * | string | |
| format * | "png" | "pdf" | |
| file_url * | string | null | Signed URL of the print file once succeeded. |
| dpi * | integer -9007199254740991–9007199254740991 | null | |
| content_hash * | string | null | Content address; identical inputs never render twice. |
| warnings * | object[] | |
| error * | string | null | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| completed_at * | string | null |
| product_type * | string ≤64 | Catalog product type, e.g. tee, mug-11oz, ornament-round, tumbler-20oz. See list_catalog. |
| name * | string | |
| suppliers * | object[] | |
| surfaces * | object[] |
| id * | string | ID, prefixed prd_. |
| object * | "product" | |
| template_id * | string | ID, prefixed tpl_. |
| template_version * | integer -9007199254740991–9007199254740991 | null | |
| product_type * | string ≤64 | Catalog product type, e.g. tee, mug-11oz, ornament-round, tumbler-20oz. See list_catalog. |
| supplier * | "printify" | "printful" | "gelato" | "own" | Print partner. own = the seller prints in-house. |
| title * | string | |
| retail_price_cents * | integer -9007199254740991–9007199254740991 | |
| base_cost_cents * | integer -9007199254740991–9007199254740991 | |
| variants * | object[] | |
| fit * | object[] | |
| mockup_urls * | string[] | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| id * | string | ID, prefixed mkj_. |
| object * | "mockup_job" | |
| product_id * | string | ID, prefixed prd_. |
| status * | "queued" | "running" | "succeeded" | "failed" | |
| images * | object[] | |
| video_url * | string | null | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| id * | string | ID, prefixed lst_. |
| object * | "listing" | |
| product_id * | string | ID, prefixed prd_. |
| channel * | "etsy" | "shopify" | Sales channel. |
| status * | "draft" | "publishing" | "published" | "failed" | |
| title * | string ≤140 | |
| tags * | string ≤20[] | |
| description * | string | |
| price_cents * | integer -9007199254740991–9007199254740991 | |
| trademark_check * | object | |
| external_id * | string | null | |
| url * | string | null | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| published_at * | string | null |
| id * | string | ID, prefixed ord_. |
| object * | "order" | |
| channel * | "etsy" | "shopify" | Sales channel. |
| external_id * | string | |
| status * | "needs_review" | "approved" | "in_production" | "shipped" | "rejected" | "cancelled" | |
| buyer_name * | string | |
| ship_country * | string ≤2 | |
| total_cents * | integer -9007199254740991–9007199254740991 | |
| currency * | string ≤3 | |
| items * | object[] | |
| preflight * | object | |
| supplier * | "printify" | "printful" | "gelato" | "own" | null | |
| supplier_cost_cents * | integer -9007199254740991–9007199254740991 | null | |
| proof * | object | null | |
| rejection_reason * | string | null | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| updated_at * | string | ISO 8601 timestamp, UTC. |
| approved * | string[] | |
| skipped * | object[] | |
| total_supplier_cost_cents * | integer -9007199254740991–9007199254740991 |
| id * | string | ID, prefixed rdr_. |
| object * | "radar_card" | |
| title * | string | |
| niche * | string | |
| demand_score * | number 0–100 | |
| competition_score * | number 0–100 | |
| launch_by * | string | Date (YYYY-MM-DD) to launch by to catch the demand curve. |
| risk * | "low" | "medium" | "high" | |
| risk_notes * | string[] | |
| keywords * | string[] | |
| suggested_product_types * | string ≤64[] | |
| suggested_prompt * | string | A ready-made brief for create_template (source.type=prompt). |
| created_at * | string | ISO 8601 timestamp, UTC. |
| object * | "analytics_summary" | |
| from * | string | |
| to * | string | |
| orders * | integer -9007199254740991–9007199254740991 | |
| revenue_cents * | integer -9007199254740991–9007199254740991 | |
| supplier_cost_cents * | integer -9007199254740991–9007199254740991 | |
| gross_margin_cents * | integer -9007199254740991–9007199254740991 | |
| aov_cents * | integer -9007199254740991–9007199254740991 | |
| views * | integer -9007199254740991–9007199254740991 | |
| conversion_rate * | number | Orders / listing views, 0-1. |
| top_templates * | object[] |
| template_id * | string | ID, prefixed tpl_. |
| name * | string | |
| views * | integer -9007199254740991–9007199254740991 | |
| orders * | integer -9007199254740991–9007199254740991 | |
| conversion_rate * | number | |
| revenue_cents * | integer -9007199254740991–9007199254740991 | |
| aov_cents * | integer -9007199254740991–9007199254740991 |
| id * | string | ID, prefixed whe_. |
| object * | "webhook_endpoint" | |
| url * | string | |
| events * | "template.created" | "template.version_created" | "render.succeeded" | "render.failed" | "product.created" | "mockups.succeeded" | "listing.published" | "listing.failed" | "order.created" | "order.approved" | "order.rejected" | "order.proof_sent"[] | |
| description * | string | null | |
| enabled * | boolean | |
| secret | string | Signing secret (whsec_…). Returned only when the endpoint is created. |
| created_at * | string | ISO 8601 timestamp, UTC. |
| id * | string | Event id, evt_…. Use it to de-duplicate deliveries. |
| object * | "event" | |
| type * | "template.created" | "template.version_created" | "render.succeeded" | "render.failed" | "product.created" | "mockups.succeeded" | "listing.published" | "listing.failed" | "order.created" | "order.approved" | "order.rejected" | "order.proof_sent" | |
| workspace_id * | string | |
| created_at * | string | ISO 8601 timestamp, UTC. |
| data * | object | The resource the event is about, in its API shape. |
| id * | string | |
| object * | string | |
| deleted * | true |