Status Information
This guide explains the different status types in the Shirtigo Cockpit system, including order statuses and individual product item statuses.
Table of Contentsβ
- Status Information
- Webhooks
Order Status Keysβ
The following table shows all possible order status values:
| Status Key | Description |
|---|---|
pending | Order created and payment pending |
open | Payment successful |
successful | Production preparation |
production | In production |
shipped | Shipped |
clarification | Clarification needed |
out-of-stock | Supply shortage |
documents-required | Commercial invoice required |
processing-failed | Order was cancelled due to failed async image processing |
payment-failed | Payment failed |
refund | Order cancelled |
Handling Failed Status Casesβ
When an order enters a failed status, specific actions are required to resolve the issue:
Clarification Statusβ
If the order status is clarification, use the Update delivery address endpoint,
PUT /orders/{order_reference}, to submit a corrected delivery address.
The body differs from the delivery object used when placing an order. It is a flat
address object and requires the id of the address to update:
{
"address": {
"id": 123456,
"street": "MusterstraΓe 12",
"postcode": "12345",
"city": "KΓΆln"
}
}
The id is returned by GET /orders/{order_reference} as the address with type
delivery. Besides id, the endpoint accepts company, firstname, lastname,
care_of, street, postcode and city. The country of an existing order cannot be
changed.
Note: Without
idthe address is silently ignored and the endpoint still answers204. This is the most common cause of "the update did nothing".
The corrected address is validated before it is stored, so a still incomplete
correction is rejected with 400 and the response body names the failing fields. Once it
validates, the clarification is resolved, the order returns to its regular status and an
Order.updated webhook is sent.
Documents Required Statusβ
If the order status is documents-required, use the Upload Merchant Invoice endpoint to submit a customs invoice.
You can either add the merchant-invoice with the initial POST /orders call by adding a document to the request. The document needs to be uploaded upfront by using the Upload Order Document endpoint.
Processing Failed Statusβ
If the order status is processing-failed, check the error in the related design objects and submit the order again with corrected files.
Payment Failed Statusβ
If the order status is payment-failed, this typically occurs due to insufficient credit card funds. You can use the Retry payment endpoint to attempt the payment again.
Important: API orders can only be placed with the following payment methods:
- Prepayment
- Direct debit (requires key account activation)
- Wallet
Order Product Item Status Keysβ
The following table shows all possible status values for individual order product items that can be received through webhooks:
| Status Key | Status Group | Description |
|---|---|---|
pending | preparing | Item was pushed to production system |
ordered | preparing | Pick order for item was created |
printed | processing | Pick label for item printed and item picked |
pretreatment | processing | Product is being pretreated |
embroidery | processing | Product is in embroidery process |
dtg | processing | Product is being printed |
additional | processing | Additional processing step is performed |
branding | processing | Product is being branded |
passed | processing | Product passed quality control |
refused | failed | Product failed quality control and will be reproduced with new item |
sorting | successful | Product is in outbound sorting |
ready | successful | Product ready for shipping |
shipped | successful | Product has been shipped |
cancelled | failed | Product has been cancelled |
Note: The status progression typically follows the order: preparing β processing β successful/failed. Each product item in an order can have its own status, allowing for detailed tracking of individual items. If a item fails a new one will be created for the same orderProduct.
Webhooks
Webhooks provide a way to receive real-time updates for specific events in your Shirtigo Cockpit. This section explains how to register webhooks, available events, and how to verify webhook authenticity.
How to Choose a URL for Your Webhookβ
To use a webhook, you need to define a publicly accessible URL in your system where webhook requests will be sent. The URL should be able to:
- Accept POST requests.
- Process the incoming JSON payload correctly.
- Respond with a 2xx HTTP status code to confirm successful receipt.
Note: If authentication is required, ensure that the webhook URL can still receive requests without restrictions, as this may interfere with delivery.
Available Webhook Eventsβ
Webhooks are triggered by specific events, which are defined by:
- Key: A unique identifier that combines the resource and action.
- Resource: The entity being affected (e.g., Order, Product, Design).
- Action: The type of event occurring (e.g., Created, Updated, Deleted).
Supported Webhook Eventsβ
Keys are case-sensitive. The authoritative list is always available via GET /webhook-types.
| Key | Resource | Action | Description |
|---|---|---|---|
Order.created | Order | created | Triggered when a new order is placed. |
Order.creation-failed | Order | creation-failed | Triggered when an order cannot be created due to an issue (e.g., print file errors). |
Order.updated | Order | updated | Triggered when an order status changes. |
Order.shipped | Order | shipped | Triggered when an order is shipped. |
Order.clarification | Order | clarification | Triggered when an order needs your input. Covers an invalid delivery address (clarification), a supply shortage (out-of-stock) and a missing customs invoice (documents-required); see below. |
Order.canceled | Order | canceled | Triggered when an order is canceled. |
OrderProductItem.updated | OrderProductItem | updated | Triggered when an individual product item's status changes. |
Product.created | Product | created | Triggered when a new product is created. |
Product.updated | Product | updated | Triggered when a product is updated. |
Product.deleted | Product | deleted | Triggered when a product is deleted. |
Design.created | Design | created | Triggered when a design is created. |
Design.rendering-failed | Design | rendering-failed | Triggered when design rendering fails. |
Design.updated | Design | updated | Triggered when a design is updated. |
Design.deleted | Design | deleted | Triggered when a design is deleted. |
GeneratedMedia.rendered | GeneratedMedia | rendered | Triggered when a rendering-task for the Mockup-Factory is completed. |
OrderWarehouseProductItem.updated | OrderWarehouseProductItem | updated | Triggered when an individual warehouse product item's status changes. |
UserInboundShipping.created | UserInboundShipping | created | Triggered when a return for an order arives. |
How to Register a Webhook URLβ
To register a webhook, send a POST request to the /webhooks endpoint with the following parameters:
Webhook Parametersβ
| Parameter | Type | Required | Description |
|---|---|---|---|
resource | string | Required without types | The entity the webhook listens to (e.g., "Order", "Product"). Must be combined with action. |
action | string | Required without types | The event type (e.g., "created", "updated"). Must be combined with resource. |
types | array | Required without resource and action | An array of webhook event keys (e.g., ["Order.created", "Product.updated"]). |
url | string | Yes | The endpoint where the webhook request will be sent. |
secret | string | No | A secret key for verifying request signatures. |
signature_header | string | No | Defines the header field used for webhook signatures (default: signature). |
is_active | boolean | No | Specifies whether the webhook is active (true) or not (false). |
Example: Register a Webhook for New Ordersβ
{
"resource": "Order",
"action": "created",
"url": "https://yourserver.com/api/webhook-listener"
}
This webhook will send a POST request to https://yourserver.com/api/webhook-listener whenever a new order is created.
The Order.clarification Payloadβ
One event key covers three situations, so the payload carries extra fields under
extra_data to tell them apart:
| Field | When | Description |
|---|---|---|
clarification_type | always | The order status key: clarification, out-of-stock or documents-required. |
address_errors | clarification | The individual objections against the delivery address. |
address_validation_errors | clarification | The parsed carrier preflight response, where one is available. |
order_product_references | out-of-stock | References of the order products that are unavailable. |
This is the event to listen to when you place orders with delayed_address_validation,
because an address that fails validation puts the order into clarification instead of
rejecting it at creation time.
Receiving Webhooksβ
When is a Webhook Considered Successfully Delivered?β
A webhook is successfully delivered when your server responds with an HTTP 2xx status code (e.g., 200 OK, 204 No Content).
If your server does not respond with a 2xx status, Shirtigo will retry sending the webhook.
How Are Failed Webhook Deliveries Handled?β
Webhook retries follow an exponential backoff strategy. The waiting time doubles after each failed attempt, so a delivery is attempted five times in total:
| Attempt | Sent after |
|---|---|
| 1 | immediately |
| 2 | ~15 minutes |
| 3 | ~30 minutes |
| 4 | ~60 minutes |
| 5 | ~120 minutes |
After the fifth failed attempt the webhook is disabled (is_active becomes false) and
no further attempts are made, neither for this event nor for any later one. You then have to
reactivate it via PUT /webhooks/{id}.
Tip: Keep this in mind while developing. An endpoint that answers with
500during testing will have its webhook switched off after the fifth failure.
Tip: Ensure your webhook handler responds quickly and always returns a 200 OK status.
How to Verify That a Webhook is Sent by Shirtigo Cockpitβ
Each webhook request includes a cryptographic signature that allows you to verify its authenticity. This signature is calculated using the HMAC SHA-256 algorithm with your webhook's secret key.
When you register a webhook, you can provide:
- A
secretparameter (a random string known only to you and Shirtigo). If you omit it, one is generated for you and returned in the response. - A custom
signature_headerparameter (defaults tosignatureif not specified)
For each webhook request, Shirtigo:
- Takes the JSON payload as a string
- Creates an HMAC SHA-256 hash using your secret
- Sends this signature in the request header you specified
Signature Formatβ
- The signature is a lowercase hexadecimal string of 64 characters.
- It is not base64 encoded and carries no prefix such as
sha256=. - It is calculated over the raw request body, byte for byte as transmitted.
Important: Verify the signature against the raw body, not against a re-serialized object. Parsing the JSON and serializing it again changes key order, spacing and escaping, which produces a different hash and makes every request look invalid.
Important: Retries send a modified body. Each retry carries a new
webhook_call_id, a newcreated_atand an additionalparent_call_id. The signature belongs to the body of that individual request, so recompute it per request rather than caching it.
Example: Verifying Webhook Signature (PHP)β
function verifyWebhookSignature($payload, $receivedSignature, $secret) {
// Calculate expected signature using HMAC SHA-256
$expectedSignature = hash_hmac('sha256', $payload, $secret);
// Use timing-safe comparison
return hash_equals($expectedSignature, $receivedSignature);
}
// In your webhook handler:
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_SIGNATURE']; // Or your custom header
$secret = 'your_webhook_secret';
if (verifyWebhookSignature($payload, $signature, $secret)) {
// Process valid webhook
http_response_code(200);
} else {
// Reject invalid request
http_response_code(401);
}
Example: Verifying Webhook Signature (Node.js)β
const crypto = require('crypto');
// rawBody must be the untouched request body (Buffer or string), NOT a parsed object.
function verifySignature(rawBody, signature, secret) {
const expected = crypto.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const a = Buffer.from(expected, 'utf8');
const b = Buffer.from(String(signature || ''), 'utf8');
// timingSafeEqual throws on differing lengths, so check that first
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
If you use Express, note that express.json() discards the raw body. Keep it around:
app.use(express.json({
verify: (req, res, buf) => { req.rawBody = buf; }
}));
app.post('/webhook-listener', (req, res) => {
if (!verifySignature(req.rawBody, req.get('signature'), process.env.WEBHOOK_SECRET)) {
return res.sendStatus(401);
}
// process req.body
res.sendStatus(200);
});
Security Tips:
- Use a strong, random string as your webhook secret
- Store your secret securely (e.g., in environment variables)
- Always verify the signature before processing webhook data
- Use a timing-safe comparison to prevent timing attacks
How to Test a Webhookβ
You can test webhooks before integrating them into production.
1. Using the Test Endpointβ
Send a POST request to /webhooks/{id}/test with a valid resource_id:
{
"resource_id": "CXY563"
}
This simulates a real event, but the payload will contain "mode": "test".
2. Using a Webhook Testing Serviceβ
Use tools like Webhook.site to inspect real-time webhook requests.
3. Using cURL for Manual Testingβ
curl -X POST https://yourserver.com/webhook-endpoint \
-H "Content-Type: application/json" \
-d '{"type":"Order.created","resource":{"reference":"123456"}}'
Conclusionβ
This documentation covers both the status information available in the Shirtigo Cockpit system and how to use webhooks to receive real-time updates. By understanding the various status types and properly configuring webhooks, you can effectively track orders and automate your workflows.