Download OpenAPI specification:
Submit fulfillment orders to Picsha and receive print-ready output from Picsha storefronts.
Draft v1.0 — published for partner technical review. Endpoint names, fields, and payloads are stable in intent but open to feedback before the spec is frozen.
The Picsha Fulfillment API has two integration surfaces:
storeId — the same slug
as the retailer's storefront subdomain.POST /orders accepts an Idempotency-Key header; retrying with the same key returns the
original result rather than creating a duplicate order.
Returns a presigned URL to PUT the file bytes to directly. Accepted: JPEG, PNG, TIFF,
HEIC, up to 30 MB. The asset is usable in orders once the PUT completes.
| storeId required | string (StoreId) ^[a-z0-9-]{2,30}$ The retailer's Picsha store identifier (same slug as their storefront subdomain). |
| filename required | string |
| contentType required | string Enum: "image/jpeg" "image/png" "image/tiff" "image/heic" |
{- "storeId": "theprintrefineryky",
- "filename": "scan-001.jpg",
- "contentType": "image/jpeg"
}{- "assetId": "ast_9f1c2ab4",
- "expiresAt": "2019-08-24T14:15:22Z"
}Picsha fetches the file from sourceUrl at submission time. The URL must be HTTPS and
reachable by Picsha; expiring signed URLs are fine.
| storeId required | string (StoreId) ^[a-z0-9-]{2,30}$ The retailer's Picsha store identifier (same slug as their storefront subdomain). |
| sourceUrl required | string <uri> |
{- "storeId": "theprintrefineryky",
}{- "assetId": "ast_9f1c2ab4"
}Submits an order for Picsha fulfillment. Returns 202 Accepted immediately; processing
is asynchronous. Typical retouch processing time is one to two minutes per photo.
product: book (AI-designed photo books from 20–200 photos) is v1.1 roadmap and is
documented here so partners can plan for it; sandbox and production accept
product: retouch at launch.
| Idempotency-Key | string <= 64 characters Retrying with the same key returns the original result. |
| storeId required | string (StoreId) ^[a-z0-9-]{2,30}$ The retailer's Picsha store identifier (same slug as their storefront subdomain). |
| product required | string Enum: "retouch" "book"
|
| externalRef | string <= 128 characters Your platform's own order/line identifier; echoed on every status response and webhook. |
| assets required | Array of strings (AssetId) [ 1 .. 200 ] items [ items^ast_[a-z0-9]+$ ] |
object Product options. For | |
object (Customer) Included only where the retailer's production workflow requires it. | |
| webhookUrl | string <uri> Overrides your default webhook endpoint for this order. |
{- "storeId": "theprintrefineryky",
- "product": "retouch",
- "externalRef": "string",
- "assets": [
- "ast_9f1c2ab4"
], - "options": {
- "addons": [
- "colorize"
], - "sizeId": "12x12",
- "style": "auto"
}, - "customer": {
- "name": "string",
- "email": "user@example.com"
},
}{- "orderId": "ord_6f39eb74",
- "status": "received"
}Returns the current state of an order. When status is ready, outputs contains
presigned download URLs valid for 60 minutes; re-fetch for a fresh URL.
Polling is supported, but webhooks are strongly recommended.
| orderId required | string (OrderId) ^ord_[a-z0-9]+$ Examples: ord_6f39eb74 |
{- "orderId": "ord_6f39eb74",
- "externalRef": "string",
- "storeId": "theprintrefineryky",
- "product": "retouch",
- "status": "received",
- "createdAt": "2019-08-24T14:15:22Z",
- "completedAt": "2019-08-24T14:15:22Z",
- "failureReason": "string",
- "outputs": [
- {
- "type": "image",
- "format": "jpeg",
- "width": 0,
- "height": 0,
- "pages": 0,
- "urlExpiresAt": "2019-08-24T14:15:22Z"
}
]
}Optional in v1; strongly encouraged. Lets the partner platform report production progress on a feed order so the retailer and customer see status in one place.
| orderId required | string (OrderId) ^ord_[a-z0-9]+$ Examples: ord_6f39eb74 |
| status required | string Enum: "in_production" "shipped" "completed" "problem" |
| note | string Optional free-text detail (e.g. tracking number, problem description). |
{- "status": "in_production",
- "note": "string"
}{- "error": {
- "code": "invalid_asset",
- "message": "string"
}
}Pull-based access to the fulfillment feed. Use for reconciliation, recovery after webhook downtime, or as a simple polling integration if your platform cannot receive webhooks.
| storeId required | string (StoreId) ^[a-z0-9-]{2,30}$ Examples: theprintrefineryky The retailer's Picsha store identifier (same slug as their storefront subdomain). |
| status | string Default: "ready" Enum: "ready" "in_production" "shipped" "completed" "problem" |
{- "orders": [
- {
- "event": "order.ready",
- "orderId": "ord_6f39eb74",
- "storeId": "theprintrefineryky",
- "source": "storefront",
- "product": "retouch",
- "createdAt": "2019-08-24T14:15:22Z",
- "customer": {
- "name": "string",
- "email": "user@example.com"
}, - "lines": [
- {
- "type": "retouch",
- "label": "8×10 Print",
- "qty": 1,
- "minInches": 0,
- "widthInches": 0,
- "heightInches": 0,
- "sizeId": "string",
- "pageCount": 0
}
], - "outputs": [
- {
- "type": "image",
- "format": "jpeg",
- "width": 0,
- "height": 0,
- "pages": 0,
- "urlExpiresAt": "2019-08-24T14:15:22Z"
}
]
}
]
}All webhook deliveries carry X-Picsha-Signature: t=<unix-ts>,v1=<hex> — an HMAC-SHA256
of "<t>.<raw body>" using your webhook secret. Reject deliveries with a bad signature
or a timestamp older than 5 minutes. Deliveries are retried with exponential backoff for
up to 24 hours; respond 2xx to acknowledge.
| event required | string Enum: "order.processing" "order.ready" "order.failed" |
| orderId required | string (OrderId) ^ord_[a-z0-9]+$ |
| externalRef | string |
| storeId required | string (StoreId) ^[a-z0-9-]{2,30}$ The retailer's Picsha store identifier (same slug as their storefront subdomain). |
| product required | string Enum: "retouch" "book" |
| createdAt | string <date-time> |
{- "event": "order.processing",
- "orderId": "ord_6f39eb74",
- "externalRef": "string",
- "storeId": "theprintrefineryky",
- "product": "retouch",
- "createdAt": "2019-08-24T14:15:22Z"
}Sent when AI processing (and, for storefront orders, payment) is complete. outputs
contains presigned download URLs valid for 60 minutes; fetch the order or the
fulfillment queue for a fresh URL at any time.
| event required | string Value: "order.ready" |
| orderId required | string (OrderId) ^ord_[a-z0-9]+$ |
| storeId required | string (StoreId) ^[a-z0-9-]{2,30}$ The retailer's Picsha store identifier (same slug as their storefront subdomain). |
| source required | string Value: "storefront" |
| product required | string Enum: "retouch" "book" |
| createdAt required | string <date-time> |
object (Customer) Included only where the retailer's production workflow requires it. | |
required | Array of objects (Line) |
required | Array of objects (Output) |
{- "event": "order.ready",
- "orderId": "ord_6f39eb74",
- "storeId": "theprintrefineryky",
- "source": "storefront",
- "product": "retouch",
- "createdAt": "2019-08-24T14:15:22Z",
- "customer": {
- "name": "string",
- "email": "user@example.com"
}, - "lines": [
- {
- "type": "retouch",
- "label": "8×10 Print",
- "qty": 1,
- "minInches": 0,
- "widthInches": 0,
- "heightInches": 0,
- "sizeId": "string",
- "pageCount": 0
}
], - "outputs": [
- {
- "type": "image",
- "format": "jpeg",
- "width": 0,
- "height": 0,
- "pages": 0,
- "urlExpiresAt": "2019-08-24T14:15:22Z"
}
]
}| event required | string Enum: "order.processing" "order.ready" "order.failed" |
| orderId required | string (OrderId) ^ord_[a-z0-9]+$ |
| externalRef | string |
| storeId required | string (StoreId) ^[a-z0-9-]{2,30}$ The retailer's Picsha store identifier (same slug as their storefront subdomain). |
| product required | string Enum: "retouch" "book" |
| createdAt | string <date-time> |
| failureReason required | string |
{- "event": "order.processing",
- "orderId": "ord_6f39eb74",
- "externalRef": "string",
- "storeId": "theprintrefineryky",
- "product": "retouch",
- "createdAt": "2019-08-24T14:15:22Z",
- "failureReason": "asset_unreadable"
}