Incoming orders
Receive and verify every new order with the order.created event.
When an order comes in, your server receives a POST with the
order.created event, verifies the signature, returns 2xx, and reads the
full order from the Admin API.
order.created is sent when the order is created, before payment is confirmed.
To receive only paid orders, subscribe to order.confirmed.
Requirements
- An Admin token with the
api_adminscope. See ERP integration. - A public HTTPS URL. It cannot resolve to a private or local network.
- Node.js, for the JavaScript examples.
Verify the signature
Generate a random secret and keep it on your server as
ECOMIQ_WEBHOOK_SECRET. Each delivery carries sha256=<hmac> in
X-Ecomiq-Signature: the HMAC-SHA256 of the raw body with that secret.
openssl rand -hex 32import { createHmac, timingSafeEqual } from "node:crypto";
export function isValidSignature(rawBody, header, secret) {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
const received = header.replace(/^sha256=/, "");
const a = Buffer.from(expected, "hex");
const b = Buffer.from(received, "hex");
return a.length === b.length && timingSafeEqual(a, b);
}Compute the signature over the body exactly as it arrives, before parsing the JSON, and drop the event if it doesn't match.
Return 2xx
You have 15 seconds to respond. Any 2xx closes the delivery; any other status
or a timeout is retried. Store the delivery, respond, and process it
afterwards.
import { createServer } from "node:http";
import { isValidSignature } from "./signature.js";
createServer(async (req, res) => {
const chunks = [];
for await (const chunk of req) chunks.push(chunk);
const rawBody = Buffer.concat(chunks).toString("utf8");
const signature = req.headers["x-ecomiq-signature"] ?? "";
if (
!isValidSignature(rawBody, signature, process.env.ECOMIQ_WEBHOOK_SECRET)
) {
res.writeHead(401).end();
return;
}
await saveDelivery({
deliveryId: req.headers["x-ecomiq-delivery"],
event: req.headers["x-ecomiq-event"],
body: rawBody,
});
res.writeHead(200).end();
}).listen(process.env.PORT);saveDelivery stores the delivery in your queue or database.
Register the endpoint
Register your URL for order.created with the secret from Verify the signature. On creation,
a webhook.endpoint.test event is sent, and the endpoint is saved only if your
server returns 2xx.
curl -X POST https://api.ecomiq.pe/api/v1/webhooks/endpoints \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Pedidos al ERP",
"url": "https://erp.example.com/webhooks/ecomiq",
"eventTypes": ["order.created"],
"secret": "whsec_replace_with_a_random_secret"
}'{
"id": "7204558912004325301"
}Store the id: you need it to re-enable the endpoint. getToken() comes from Request a token, in the ERP integration.
Read the order
The order.created body is an
OrderWebhookModel:
it has orderId, orderNumber, state, and the totals, without the lines. To
read them, get the order; the response includes items.
curl https://api.ecomiq.pe/api/v1/orders/7204558912004325301 \
-H "Authorization: Bearer $ECOMIQ_TOKEN"The same order can arrive more than once, and a manual resend carries a new
X-Ecomiq-Delivery. Deduplicate by orderId and mark it after your work
completes.
Recover failures
After 10 consecutive failures the endpoint is paused. Fix the receiver and
re-enable it; then list the failed deliveries and resend each one by its id.
curl -X POST https://api.ecomiq.pe/api/v1/webhooks/endpoints/<endpoint-id>/enable \
-H "Authorization: Bearer $ECOMIQ_TOKEN"
curl "https://api.ecomiq.pe/api/v1/webhooks/deliveries?status=failed&eventType=order.created" \
-H "Authorization: Bearer $ECOMIQ_TOKEN"
curl -X POST https://api.ecomiq.pe/api/v1/webhooks/deliveries/<delivery-id>/retry \
-H "Authorization: Bearer $ECOMIQ_TOKEN"A resend keeps the original body.
Next steps
Last updated: