Download OpenAPI specification:
Programmatic access to Pixelmade — the print-on-demand supplier for custom diamond-painting and craft kits. Register kit designs as templates, look up products and DMC colors, place orders, and receive webhook notifications — from your own tools or an AI coding agent (Claude Code, ChatGPT, Codex).
Authentication. Every request needs a bearer token, scoped to your brand. Create and rotate tokens yourself in the brand portal under Developer (an admin grants API access first). Send it as Authorization: Bearer <token>.
Rate limit. 60 requests/minute per user by default; 429 with a Retry-After header when exceeded.
Orders and payment. For standard accounts, POST /orders creates a payable order in your brand portal (pending_payment) — paying it there is what sends it to production. The API never charges you or bypasses payment. Accounts on invoice terms submit straight to production and are billed by invoice.
| slug | string Filter to a single template by its slug (for idempotent lookups). |
{- "product_templates": [
- {
- "id": 0,
- "uid": "string",
- "external_sku": "pmt_a1b2c3",
- "slug": "string",
- "name": "string",
- "active": true,
- "catalog_product_id": 0,
- "chart_sha256": "string",
- "dithered_image_attached": true
}
]
}Registers a pre-designed kit and returns the pmt_ SKU that makes a storefront variant orderable. Re-posting the same slug updates it in place and keeps the SKU stable. The uploaded dithered_image is the production print file (1 pixel per drill cell, PNG or BMP).
| name required | string |
| slug required | string^[a-z0-9]+(?:-[a-z0-9]+)*$ |
| catalog_product_id required | integer |
| dithered_image required | string <binary> Production print file — image/png or image/bmp, ≤ 10 MB. |
| presentation_image | string <binary> Hero/mockup image (png/jpeg/webp), ≤ 5 MB. |
| original_image | string <binary> Pre-dither source image (png/jpeg/webp), ≤ 5 MB. |
| active | boolean Default: true |
{- "id": 0,
- "uid": "string",
- "external_sku": "pmt_a1b2c3",
- "slug": "string",
- "name": "string",
- "active": true,
- "catalog_product_id": 0,
- "chart_sha256": "string",
- "dithered_image_attached": true
}Standard accounts: the order lands in your brand portal's Orders section as pending_payment with a portal_url — paying it there sends it to production. Invoice-term accounts submit straight to production.
| reference_number required | string Your internal id; unique per brand. |
required | object (CustomerInfo) |
required | Array of objects non-empty |
{- "reference_number": "my_order_001",
- "customer_info": {
- "name": "Jane Smith",
- "email": "jane@example.com",
- "phone": "555-1234",
- "address1": "123 Main St",
- "address2": "Apt 4",
- "city": "Seattle",
- "state": "WA",
- "postal_code": "98001",
- "country": "USA"
},
}{- "id": 100,
- "reference_number": "my_order_001",
- "state": "pending_payment",
- "payment_status": "pending_payment",
- "created_at": "2019-08-24T14:15:22Z",
- "customer_info": {
- "name": "Jane Smith",
- "email": "jane@example.com",
- "phone": "555-1234",
- "address1": "123 Main St",
- "address2": "Apt 4",
- "city": "Seattle",
- "state": "WA",
- "postal_code": "98001",
- "country": "USA"
}, - "lines": [
- {
- "id": 0,
- "product_id": 0,
- "quantity": 0,
- "artwork_location": "string"
}
], - "tracking_info": [
- {
- "carrier": "DHL",
- "tracking_number": "string",
- "tracking_url": "string"
}
], - "allow_cancel": true,
- "cancel_type": "no_cost"
}Quote production/shipping days for a destination and set of line quantities.
object | |
Array of objects |
{- "customer_info": {
- "country": "USA"
}, - "lines": [
- {
- "quantity": 2
}
]
}{- "total_pieces": 2,
- "estimated_production_days_min": 7,
- "estimated_production_days_max": 10,
- "shipping_info": [
- {
- "name": "Economy",
- "estimated_shipping_days_min": 12,
- "estimated_shipping_days_max": 16
}
]
}{- "id": 100,
- "reference_number": "my_order_001",
- "state": "pending_payment",
- "payment_status": "pending_payment",
- "created_at": "2019-08-24T14:15:22Z",
- "customer_info": {
- "name": "Jane Smith",
- "email": "jane@example.com",
- "phone": "555-1234",
- "address1": "123 Main St",
- "address2": "Apt 4",
- "city": "Seattle",
- "state": "WA",
- "postal_code": "98001",
- "country": "USA"
}, - "lines": [
- {
- "id": 0,
- "product_id": 0,
- "quantity": 0,
- "artwork_location": "string"
}
], - "tracking_info": [
- {
- "carrier": "DHL",
- "tracking_number": "string",
- "tracking_url": "string"
}
], - "allow_cancel": true,
- "cancel_type": "no_cost"
}Cancellation is only possible up to a point — check allow_cancel. If the order is already in production, cancel_type is production_cost; if too far along, returns 422.
| id required | integer Example: 100 |
{- "id": 100,
- "reference_number": "my_order_001",
- "state": "pending_payment",
- "payment_status": "pending_payment",
- "created_at": "2019-08-24T14:15:22Z",
- "customer_info": {
- "name": "Jane Smith",
- "email": "jane@example.com",
- "phone": "555-1234",
- "address1": "123 Main St",
- "address2": "Apt 4",
- "city": "Seattle",
- "state": "WA",
- "postal_code": "98001",
- "country": "USA"
}, - "lines": [
- {
- "id": 0,
- "product_id": 0,
- "quantity": 0,
- "artwork_location": "string"
}
], - "tracking_info": [
- {
- "carrier": "DHL",
- "tracking_number": "string",
- "tracking_url": "string"
}
], - "allow_cancel": true,
- "cancel_type": "no_cost"
}[
]Register up to 5 webhooks per brand. We POST order events to your address.
| address required | string <uri> |
| event required | string |
| secret | string |
{- "event": "order_shipped",
- "secret": "your_secret"
}{- "id": 0,
- "event": "order_shipped"
}{- "id": 0,
- "event": "order_shipped"
}