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.
New submission on your order form
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
Publish your order form with Shipping Address and Delivery Method required — a label cannot be produced from a partial address.
- 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
Turn on the outgoing webhook in the form's settings, paste the route URL, and save the form.
- 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
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
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
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
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 field | Webhooks |
|---|---|
| Item Name or Product | SKU lookup in your catalogue |
| Quantity | line item quantity, cast to an integer |
| Color, Variant, or Size | variant on the resolved SKU |
| Shipping Address | ship-to address on the order record |
| Delivery Method | shipping service used when the label is requested |
| Special Instructions | notes on the order, printed on the pick list |
Variations worth knowing
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.
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
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.
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
- Deliver job applications to your hiring service
Every application is posted as JSON to your applicant tracking service, which validates the fields before it creates a candidate.
- Fan event sign-ups out to your own services
One POST per RSVP writes the attendee to your database and publishes a message the rest of your services can listen for.
- Push support requests onto your own job queue
Every support submission is posted to an endpoint that enqueues the request and sets its priority from the answer on the form.
- Stream feedback scores into your analytics pipeline
Each NPS response is posted to an ingestion endpoint that normalises the score and streams the record into your warehouse.
- Write new leads straight into your own database
Each lead capture submission reaches your endpoint as JSON and becomes a row in your own leads table, seconds after it is sent.
- Add buyers to a customers list after each order
Each order form submission adds the buyer to a Customers list in Constant Contact for updates and repeat-purchase emails.
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