Webhooks logo

Send custom orders to your fulfilment backend

Each order submission is posted to your orders API, which records the items and starts fulfilment with nothing rekeyed by hand.

When this happens

New submission on your order form

Do this

POST the order payload to your orders API, which records the line items, raises the charge through your own payment system and triggers a shipping label

One-directional. A submission triggers the action — nothing is written back into your form.

A shop taking custom orders through a form usually has a backend already — an orders table, a label printer, a payment processor it has used for years. What is missing is the hop between the two, and that hop is normally a person retyping an address.

This flow removes it. Each order is posted as JSON to your orders API, which persists the line items and starts fulfilment. Use hosted checkout for fixed products and priced options, or let your backend raise the charge when pricing depends on its catalogue.

Setting it up

  1. 1

    Publish your order form with Shipping Address and Delivery Method required — a label cannot be produced from a partial address.

  2. 2

    Add a POST route on your orders API, /webhooks/orders, that accepts a JSON body and does not sit behind your admin session cookie.

  3. 3

    Turn on the outgoing webhook in the form's settings, paste the route URL, and save the form.

  4. 4

    Submit a test order and log the raw body, checking the keys for Item Name or Product, Quantity and Color, Variant, or Size.

  5. 5

    Cast Quantity to an integer at the boundary and reject a zero or a negative with a 4xx, rather than letting it reach the pricing code.

  6. 6

    Resolve Item Name or Product together with the variant to a SKU in your catalogue, and fail the request when that pair does not exist instead of guessing.

  7. 7

    Persist the order first, then raise the charge through your backend when it needs to work the amount out from SKU and Quantity. For fixed prices, use hosted checkout instead.

  8. 8

    Request the shipping label for the chosen Delivery Method only after the order commits, and return 2xx last, so a failure anywhere in that chain is recorded as a failed delivery.

What maps where

Using the Product Order Form as the starting point. These are its real fields — swap in your own and the mapping works the same way.

Form fieldWebhooks
Item Name or ProductSKU lookup in your catalogue
Quantityline item quantity, cast to an integer
Color, Variant, or Sizevariant on the resolved SKU
Shipping Addressship-to address on the order record
Delivery Methodshipping service used when the label is requested
Special Instructionsnotes on the order, printed on the pick list

Variations worth knowing

Hold custom work for a human quote

When Special Instructions is not empty, write the order with a pending status and skip the label request. Custom work rarely prices itself, and an order that needs a quote should not print a label before someone has read the note. Standard orders run through untouched.

Split collection from delivery in the handler

Branch on Delivery Method: collections get a pick ticket and no carrier call, deliveries get a label. Doing it in the route rather than in the form means adding a carrier is a code change instead of a republished form, and the shop keeps one order form for both.

If something isn't arriving

Orders arrive with a quantity of 1 no matter what was typed.

The value is arriving as a string and your code is defaulting when the cast fails. Log the raw Quantity from a real submission before parsing, handle a value like "2 boxes" explicitly, and constrain the question to a number on the form so the payload stops being ambiguous.

The same order is created twice.

A retry or a double tap on submit can post twice, and nothing is written back to the form to mark an order as handled. Derive an idempotency key from the submission id in the payload, store it on the order row with a unique constraint, and return 2xx for a repeat you already have.

Frequently asked questions

Can the form take payment for the order?

Yes. Add products and priced options to the form, then collect payment through secure hosted checkout with Stripe, PayPal, or Square. Payment status is tracked alongside the response.

Can I show the customer an order number after they submit?

Not one your API generated. The webhook fires after the submission and nothing comes back into the form, so the confirmation page cannot know the id. Email the order number from your backend once the row commits, which is where the authoritative number lives anyway.

How do I test the endpoint without placing real orders?

Point the form's webhook URL at a staging copy of your orders API and submit through the published form the way a customer would. Real submissions against staging give you the exact payload shape, and you can clear the test rows afterwards.

Related automations

Build the form first

The automation needs somewhere to fire from. Publish a form, connect it once, and every submission from then on runs this flow.

Start free