With webhooks in Picqer, you can get push notifications when certain events happen in your Picqer account. With these webhooks, you do not need to poll the API anymore to see if a picklist is closed. You can just 'subscribe' to this event with our webhooks.

New to webhooks?

Receiving and processing webhooks is really simple. To give you a head start as a beginner, view our PHP example of a 4-line script that receives and processes a webhook.

If you are using the PHP Client, you can use the Webhook helper to easily receive webhooks.

Available events

We have a couple of events you can subscribe to. If you need an event we do not support yet, please let us know.

orders.created Triggered when an order is created
orders.allocated Triggered when an order is allocated
orders.closed Triggered when you process an order
orders.status_changed Triggered when the status of an order changes, e.g. from concept to processing or from completed to cancelled
orders.completed Triggered when an order is completed, this is when all products are shipped to the customer
orders.notes.created Triggered when a note is added to an order.
picklists.created Triggered when a picklist is created
picklists.closed Triggered when a picklist is closed
picklists.shipments.created Triggered when a shipment is created on a picklist (can happen 0, 1 or multiple times per picklist)
picklists.snoozed Triggered when a picklist is snoozed
picklists.unsnoozed Triggered when a picklist is unsnoozed, either automatically or manually
products.changed Triggered when a product is added or edited
products.free_stock_changed Triggered when the free stock of a normal product is changed.
products.stock_changed Triggered when the real stock of a normal product is changed. (Do not use this for tracking of free stock changes. Use free_stock_changed for that information.)
products.assembled_stock_changed Triggered when the virtual stock of a virtual assembled product is changed.
Purchase orders
purchase_orders.created Triggered when a purchase order is created
purchase_orders.changed Triggered when a purchase order is changed, like added or removed products
purchase_orders.purchased Triggered when a purchase order is marked as purchased
purchase_orders.receipts.created Triggered when a purchase order receipt is created
returns.created Triggered when a return is created
returns.changed Triggered when a return is edited, products or replacements are added
returns.status_changed Triggered when the status of a return is changed, or when a comment/note is added
returns.products_received Triggered when returned products for a return are received
movements.moved Triggered when a movement is moved and the stock is changed


When an event is triggered, you get a POST request on the given address. In the POST data we give information about the trigger and all data about the object involved. An example of the request we send you:

View examples of all webhook types

POST http(s)://example.com/your-endpoint
{ "idhook":228, "name":"Stock change notifications", "event":"products.free_stock_changed", "event_triggered_at":"2018-12-01 02:09:12", "data": { "idproduct":138, "idvatgroup":18, "idsupplier":null, "productcode": "6531-RB-7-9", "name": "Hyperkewl Evaporative Cooling Vest Ultra Blue 7-9yr", "price": 54.46, "fixedstockprice": 0, "productcode_supplier": "", "deliverytime": null, "description": "", "barcode": "857825001442", "type": "normal", "unlimitedstock": false, "weight": 200, "minimum_purchase_quantity": 0, "purchase_in_quantities_of": 0, "hs_code": null, "country_of_origin": null, "active": true, "tags": {}, "productfields": [], "images": [ "/files/2/cb594f30-25d0-43a6-88f2-d93e193ea316/original.jpg" ], "stock": [ { "idwarehouse":18, "stock":35, "reserved":0, "reservedbackorders":0, "reservedpicklists":0, "freestock":35, "freepickablestock":35 } ] } }
HTTP/1.1 200 OK

We expect you to give a 200 OK status code as a response. We ignore the content you send us. You have a maximum of 10 seconds to process the request, otherwise we also see it as a failure and we will retry.

Failures and retries

When we do not get a 200 OK status back from you, we consider the call as failed. We will retry to send the message 15 times in 24 hours. After 15 retries we delete the call from our queues.

Important: If a webhook fails too many times, we inactivate the hook. You can only reactivate the hook by registering a new one with the steps below. So make sure you handle possible errors on your side properly. Perhaps ignore a call and give a 200 state if you cannot process the request after multiple tries.

Registering your hooks

Adding and removing your subscriptions to these events, or 'hooks' as we call them, is only possible via the API. Below you find the documentation for managing your hooks.

Debug logging

For easier debugging, you can see details about recent deliveries for registered webhooks in your Picqer account. Go to Settings > Webhooks to see the webhooks. On the details page you see the recent deliveries Picqer made for this webhook.


Name Type Required Description
idhook integer generated Unique Picqer reference
name string required Your own reference for this hook
event string required The event you want subscribe to
address string required Your full endpoint for this hook, for example http://www.example.com/triggers/picqer-stock-change
secret string optional If you provide a secret key with your webhook, we will use it to sign every request so you can check the sender, see "Validating webhooks"

Get all hooks

GET https://example.picqer.com/api/v1/hooks
HTTP/1.1 200 OK [ { "idhook": 727, "name": "When picklists are created", "event": "picklists.created", "address": "http://requestb.in/1llnmzl71", "active": true, "secret": false }, { "idhook": 1922, "name": "Stock is changed", "event": "products.free_stock_changed", "address": "http://requestb.in/y7wgw6ny7", "active": true, "secret": false } ]
This endpoint uses pagination.

Get single hook

GET https://example.picqer.com/api/v1/hooks/{idhook}
HTTP/1.1 200 OK { "idhook": 1922, "name": "Stock is changed", "event": "products.free_stock_changed", "address": "http://requestb.in/y7wgw6ny7", "active": true, "secret": false }

Create new hook

POST https://example.picqer.com/api/v1/hooks
{ "name": "Stock is changed", "event": "products.free_stock_changed", "address": "http://requestb.in/y7wgw6ny7", "secret": "my-secret-key-for-hooks" }
HTTP/1.1 201 Created { "idhook": 1922, "name": "Stock is changed", "event": "products.free_stock_changed", "address": "http://requestb.in/y7wgw6ny7", "active": true, "secret": true }

Deactivate a hook

To deactivate a hook you can use this delete call. This call will not actually delete the webhook, but it will deactivate the webhook.

DELETE https://example.picqer.com/api/v1/hooks/{idhook}
HTTP/1.1 204 No Content

Validating webhooks

If you provide a secret while registering the webhook, we will sign deliveries of the webhook with a X-Picqer-Signature header.

The signature is created with an HMAC hash, using SHA256. We use the whole body of the request as the signed content.

For example, in PHP you can check the signature as follows:

$webhookPayloadRaw = file_get_contents('php://input');
$checkingSignature = base64_encode(
        hash_hmac('sha256', $webhookPayloadRaw, 'your-provided-secret', true)

$isSignatureValid = hash_equals($checkingSignature, $_SERVER['HTTP_X_PICQER_SIGNATURE']);

If you are using the PHP Client, you can use the Webhook helper to easily check the webhook signature.