Overview
Payment and delivery are separate in Shoppex. An order can be paid withstatus: "COMPLETED" while one of its line items is still waiting for delivery.
Use asynchronous fulfillment when your system needs more than 15 seconds to generate content. Use manual fulfillment when a merchant needs to prepare an account, link, code, or file after payment.
Fulfillment is tracked per line item. The invoice payment status does not change when a line item moves between delivery states.
Delivery States
A line item enters
AWAITING_FULFILLMENT in either of these cases:
- its dynamic delivery callback returns an explicit
{"status":"pending"}acknowledgement - it belongs to a
DYNAMICproduct that has nodynamic_webhookURL configured
Read Fulfillment State
Order read responses expose these fields on every item. The example below shows the relevant response fields:id is the line item ID used as {item_id} in the fulfillment endpoints. The order path accepts the same order identifier used by the existing order endpoints.
Fulfill a Line Item
status: "COMPLETED", and the line item must not already be delivered. Provide at least one of message, codes, links, or files.
cURL
Each
files[].attachment_id must refer to an existing attachment owned by the same shop. Upload attachments in the dashboard before calling this endpoint. If any attachment is missing or belongs to another shop, the entire request fails and no partial delivery is stored.Customer Email
notify_customer controls the buyer’s “product ready” email:
- omit it or set it to
trueto request the customer email after the content is stored - set it to
falseto store the content without sending that email
order:item.delivered after a successful fulfillment.
Error Responses
Both endpoints reject invalid requests with the standard error envelope. Themessage distinguishes the cause:
Idempotency
Both fulfillment endpoints support the standardIdempotency-Key header. Reuse the same key when retrying the same request after a network interruption. Shoppex scopes the key to the authenticated API key and route and replays the stored response during the 24-hour idempotency window.
For example, every retry of the delivery above should keep Idempotency-Key: fulfill-order_123-018f6f2e-7c3a-7b21-9d4e-5a1b2c3d4e5f-v1.
Retry Failed Dynamic Delivery
FAILED to PENDING.
It does not take a request body.
cURL
FAILED dynamic line item with a failed delivery event can be retried. If no retryable event exists, fulfill the line item manually instead.
Fulfillment Webhook Events
These are normal merchant webhook events. Subscribe to them in Settings → Webhooks or through the Developer API. They use the normal event-webhook signature, not the product’s dynamic delivery signing secret.order:item.delivered
Emitted after late content is stored through manual or API fulfillment.
order:item.delivery_failed
Emitted when the single dynamic delivery attempt ends in a terminal failure. Shoppex also marks the line item FAILED and notifies the merchant.
These events report fulfillment state. They do not change or replace payment events such as
order:paid.Next Steps
Dynamic Product Delivery
Implement the synchronous and asynchronous callback contract.
Webhook Events
Verify normal merchant webhook signatures and review event payloads.