Webhooks: pushing orders in and getting statuses back
A webhook tells a system the moment something happens. How to push orders into a COD platform, receive delivery status events, and verify a signature properly.
The essentials
- What is it?
- A webhook is an automatic notification between two systems. On CODFamilia it works both ways: an incoming webhook lets your store or tool tell us about an order, and an outgoing webhook lets us tell you that a lead has been confirmed or a parcel delivered.
- Who is it for?
- For the incoming direction: any seller whose tool can call a URL on every order, even with no ready-made integration. For the outgoing direction: any seller keeping their own dashboard or books, or wanting to trigger a message to the customer on delivery.
- How does it work?
- You register an address on one side, and the other side calls it on every event, handing over the details as JSON. Every call is signed so the recipient can check it really comes from the stated sender, and retried later if it does not get through.
- What is it for?
- To remove waiting and pointless load. Without a webhook, the only way to know what is happening is to poll the other system in a loop: slow for whoever is waiting for the information, and expensive for whoever answers "nothing new" thousands of times.
- How do you use it?
- On the incoming side, create a connection, copy its address into the source tool, and paste the same secret on both sides. On the outgoing side, register a public HTTPS address and choose the events you want. The rest is signature verification.
A webhook is an address one system calls as soon as an event occurs, so the other system is told straight away instead of having to come and ask.
A webhook, explained without technical vocabulary
Imagine you are waiting to find out whether a parcel has arrived. First method: you ring the warehouse every ten minutes to ask. You get the information, but you spend your day on the phone and the warehouse spends its day answering "not yet". Second method: you leave your number, and the warehouse rings you when the parcel arrives. That is exactly what a webhook is: you leave an address, and the other system calls you when it has something to say.
Technically, the "address" is a URL on your site and the "call" is a web request carrying the event's details. That is all. There is no further magic, which is why a webhook works with any language and any hosting: if your site can receive a form, it can receive a webhook.
Two consequences follow from that simplicity, and they explain the rest of this page. First: since anyone can call an address, there has to be a way of proving the call comes from who it claims — that is the signature. Second: since a call can fail, there has to be a way of replaying it — those are the retries.
Inbound: your orders reach us
This is the route in for tools that appear on no integration list. You create a connection, the platform gives you a unique address, and your tool calls it on every order. The expected format is the same as the API's: customer name, phone number, city, address, total to collect, items with their SKU and quantity, and your order reference.
If your tool sends a different format — common with a custom site or an automation tool — the platform guesses nothing. The first delivery is kept as a sample, it offers to link each of your fields to the matching one, and orders received in the meantime are replayed in arrival order once the mapping is saved. It is the same mechanism as for a connected store.
Once the order has been read, it goes through the same checks as everything else: phone number normalised, city matched, SKU verified, total compared with the sum of the prices. An incomplete order becomes a damaged lead rather than being refused. And an order already received, because your tool retried, does not create a second lead: its identifier is remembered per connection.
Outbound: the order's stages reach you
In the other direction, you register your system's address and choose what you want to be told. Every time one of your orders passes a stage, your address is called with the order's details: its reference, yours, the customer, the total, the seller profit, the statuses and the tracking number where there is one.
| Event | What has just happened |
|---|---|
| lead.created | A lead has come in, whatever its source |
| lead.confirmed | An agent has confirmed the order with the customer by phone |
| lead.canceled | The lead is lost: cancelled, wrong number, duplicate, not serious |
| order.shipped | The parcel has left for the courier |
| order.delivered | The parcel is delivered and the cash collected by the courier |
| order.returned | The parcel is coming back: refused or customer unreachable |
| order.paid | The order has been paid out to the seller |
The signature, and why a secret address is not enough
The natural assumption is that an address nobody knows works as a password. It does not, for a simple reason: addresses travel. They turn up in a server log, a screenshot, a message to a contractor, the history of an automation tool. Anyone who has seen it can send a fake "parcel delivered" to your system, and your books will believe it.
The signature settles that. On every delivery, the sender computes a digest of the contents using a secret known to the two sides only, and puts it in a header. The recipient recomputes the same digest and compares. Since the secret never travels, nobody can forge a valid digest — not knowing the address, not even knowing the exact contents to imitate.
Outgoing deliveries from the platform are signed over the timestamp and the raw body together, and the timestamp is sent in a header of its own. That pair lets you refuse two different things: altered contents, because the digest will no longer match, and authentic contents replayed hours later, because the timestamp will be too old. The secret is shown only once, when the address is created.
Inbound, the same principle applies in mirror: you choose a secret, put it on both sides, and sign the body of your deliveries. If you set no secret, the secret address is your only protection — acceptable to begin with, and insufficient as soon as the address has been shared once.
Failures, retries and deactivation
Outgoing deliveries are not sent during the request that produces the event. That is a deliberate choice: your server may be slow, switched off or behind a firewall, and an agent confirming an order must neither wait nor fail because of it. Events are queued, then sent separately.
A delivery succeeds when your server returns a success code. Otherwise it is retried later, with intervals growing further apart, over a few hours. A server switched off overnight therefore finds its events in the morning, without having been called a thousand times in between. Past a number of attempts, the delivery is given up and recorded as failed.
If your address fails repeatedly over a long run of deliveries, it is deactivated automatically: a server that has permanently disappeared must not be called forever. It is reactivated with one click once your server is fixed. In the meantime, the list of recent deliveries shows what went out, what failed, and with which response code — that list is what answers "why did my system receive nothing".
- Answer fast — Store the event, return a success, process afterwards. Processing before answering eventually exceeds the timeout.
- Tolerate repeats — The same event can arrive twice if your answer was lost on the way. Your code must be able to receive it twice without consequence.
- Refuse the rest — Invalid signature, old timestamp, unknown event: return an error and process nothing.
- A public HTTPS address — A local or private address is refused at registration: it would make us call a machine that is not yours.
When a webhook beats a connected store
If an official integration exists for your store, use it: it subscribes by itself, handles access renewal, and has a fallback re-read when a notification is lost. A webhook you build yourself has no such net, unless you write one.
- Your tool has no integration — The typical case: a custom site, a sales funnel, an internal management tool. The webhook is the most direct route.
- You are going through an automation tool — A connector in between can trigger on "new order" and send a request: you write no code at all.
- You want to be told about statuses — It is the only way to learn about a delivery without polling the API in a loop, and it has no equivalent on the connected-store side.
- You need to read something else — A webhook announces an event; it does not let you query the catalogue, the cities or past orders. For that, you need the API.
Setting up a webhook, one direction then the other
-
Create the incoming connection
In Applications, create a webhook connection. The platform produces an address specific to that connection, impossible to guess, and offers to generate a shared secret.
-
Paste the address into the source tool
In your store, your automation tool or your site, declare a "new order" subscription that sends a POST request to that address, and paste the same secret there.
-
Send the right contents
The expected body is the same as the API's: the customer's name, phone number, city and address, the total to collect, the list of items with their SKU and quantity, and your own order reference.
-
Map the fields if your format differs
If your tool sends its own format, nothing is lost: the first delivery received is kept as a sample, the platform proposes the field mapping, and the orders held in the meantime are replayed once it is saved.
-
Register the outgoing address
In Applications → API, add your system's HTTPS address and tick the events you care about, or take them all. The signing secret is shown once, at creation: copy it immediately.
-
Verify the signature on your side
On every delivery received, recompute the digest from the timestamp and the raw body, using your secret, and compare it with the one in the header. If it does not match, refuse the call. If the timestamp is old, refuse it too.
-
Answer fast, then process
Return a success code as soon as you have stored the event, and do the work afterwards. A server that processes before answering eventually exceeds the timeout and triggers pointless retries.
Frequently asked questions about webhooks
Do you need a developer to use a webhook?
What happens if my server is down?
Can I receive only some events?
Why verify the signature if the address is secret?
Can the same event arrive twice?
Does a webhook replace the API?
Does my data go anywhere else?
Can I register several addresses?
Does a webhook work on shared hosting?
Also worth reading
- Integrations: getting orders in without retyping them Four ways to get an order into a COD platform: a connected store, a spreadsheet, a webhook or the API. Which …
- Connecting a YouCan store to your order management How to link a YouCan store to a COD platform: authorisation, orders arriving in real time, the role of the SK…
- Importing COD orders from a Google Sheets spreadsheet Using a spreadsheet as your order source: sharing, columns to map, how rows become leads, what happens to inc…
- The REST API: driving COD orders from your own code The seller API lets you create and track cash-on-delivery orders from your own code: API keys, reading the ca…
Wire your own systems at both ends
Orders pushed into the platform, delivery events pushed back to you: signed, retried and logged deliveries, for current records across 65 cities.
Sign up