Skip to main content
With dynamic delivery, Shoply does not hold the goods. When an order is paid it asks your server for them, and sends the buyer whatever your server answers. Use it for a key made on the spot, an account created for the buyer, or stock that lives somewhere else.
This is not a webhook. A webhook tells you something happened. Dynamic delivery asks you for something, and waits for the answer.

Setting it up

On a product’s Variants tab, press Edit on the variant, open Delivery, switch Dynamic on, and press Manage beside it. Enter an https address on your server. Every variant of the store can share one address or have its own. Your store has one signing secret for dynamic delivery, shown in that same dialog. Every request to your server is signed with it.

The request

A POST with a JSON body, once for each line of the order that is delivered this way.
customFields is what the buyer answered to the variant’s custom fields, by each question’s key, such as the username to make a key for. It is {} where the variant asks nothing. A tick box that was ticked is true. deliveryId is the thing to remember. It is the same when a request is tried again after a timeout, so your server can answer with the goods it already made instead of making more. It is a new one when the order is delivered again later, which is a request for new goods.

The answer

Answer 200 with the goods.
  • Plain text: the whole body is one item, however many lines it has.
  • JSON shaped {"items": ["...", "..."]}: one entry for each item.
Anything but a 200, an empty body, or no answer within 60 seconds is a failure, and is tried again.

Checking the request

Every request carries the timestamp it was signed at, and a signature over that timestamp and the body:
Check it the way a webhook’s signature is checked: it is the same scheme, under your store’s delivery signing secret. Use the raw body, compare in constant time, and refuse a timestamp more than a few minutes old. Requests do not come from one fixed IP address, so the signature is the only thing that says a request is Shoply’s. Do not allowlist an address in its place. A second header, X-Signature, carries the HMAC-SHA256 of the body alone, in uppercase hex. It is there for handlers written before the timestamp existed. Check X-Shoply-Signature in anything new.

When your server fails

The buyer is told their item is still being prepared, and Shoply asks again: after 2 minutes, then 10, 30, an hour, 2 hours, 4, and 8, eight tries in all. You can ask again yourself with Retry on the order’s page, or with the API, up to 150 times in ten minutes for the store.

What your address has to be

https, reachable from the internet, on port 443, 80, 8080 or 8443. An address inside a private network is refused, and so is a redirect to one.