Webhooks
Webhooks allow you to receive real-time notifications when events occur in OlaClick. Instead of polling, OlaClick sends a POST to your endpoint every time something relevant happens.
How it works
1. You register a URL via the API (with your merchant_id)
2. An event occurs in OlaClick (e.g. an order is created)
3. OlaClick sends a POST to your URL with the event payload
4. Your server responds with 2xx to confirm receipt
Integration flow
1. Register a webhook
What is
merchant_id? It's an identifier you define — not generated by OlaClick. Use any string that makes sense in your system (e.g., your internal restaurant ID, a store code, or an account reference). OlaClick stores it and includes it in every webhook delivery so your server knows which merchant the event belongs to. This is especially useful if you manage multiple OlaClick accounts from a single webhook endpoint.Examples:
"restaurant_042","store-lima-01","acc_7f3b2a"
curl -X POST https://public-api.olaclick.app/v1/webhooks \
-H "Authorization: Bearer olk_live_..." \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-server.com/webhooks/olaclick",
"merchant_id": "restaurant_042",
"ack_http_codes": [200, 201, 202],
"event_types": ["ORDER_CREATED", "ORDER_UPDATED"]
}'
Response:
{
"data": {
"company_id": "your-company-uuid",
"webhook_id": "webhook-uuid",
"webhook_url": "https://your-server.com/webhooks/olaclick",
"webhook_headers": {},
"is_active": true,
"max_retry": 3,
"ack_http_codes": [200, 201, 202],
"merchant_id": "restaurant_042",
"created_at": "2026-06-20T12:00:00.000Z",
"updated_at": "2026-06-20T12:00:00.000Z"
}
}
2. Receive events
When an event occurs, OlaClick sends a POST to your webhook_url with the following headers:
POST https://your-server.com/webhooks/olaclick
Content-Type: application/json
source: OlaClick
If you configured custom webhook_headers, they are included in every delivery.
Payload structure:
{
"event_type": "ORDER_CREATED",
"event_id": "unique-event-uuid",
"merchant_id": "restaurant_042",
"timestamp": "2026-06-20T15:30:00.000Z",
"data": {
"order_id": "order-uuid",
"public_id": "PE-1234567890",
"status": "PENDING",
"service_type": "DELIVERY",
"source": "INBOUND",
"payment_status": "UNPAID",
"delivered_by": "MERCHANT",
"total": 15000,
"currency": "COP",
"daily_id": 42,
"pending_at": "2026-06-20T15:30:00.000Z",
"created_at": "2026-06-20T15:30:00.000Z",
"updated_at": "2026-06-20T15:30:00.000Z"
}
}
| Field | Type | Description |
|---|---|---|
event_type | string | The event that occurred (ORDER_CREATED, ORDER_UPDATED, ORDER_DELETED) |
event_id | string | Unique identifier for this delivery (use for idempotency) |
merchant_id | string | Your merchant ID as you defined it when registering the webhook |
timestamp | string | ISO 8601 timestamp of when the event occurred |
data | object | The event payload (see below) |
data fields:
| Field | Type | Description |
|---|---|---|
order_id | string | Order UUID |
public_id | string | Public order ID (e.g. PE-1234567890) |
status | string | Order status: PENDING, PREPARING, READY, DELIVERED, FINALIZED, CANCELLED |
service_type | string | null | DELIVERY, ONSITE, TABLE, TAKEAWAY |
source | string | null | INBOUND, OUTBOUND, CHATBOT, IFOOD, RAPPI, DIDI, etc. |
payment_status | string | null | PAID, UNPAID, PARTIAL, OVERPAID |
delivered_by | string | null | MERCHANT, IFOOD, DIDI, RAPPI, PICKER, etc. |
total | number | Order total (in local currency) |
currency | string | null | ISO 4217 currency code (e.g. COP, BRL, PEN) |
daily_id | number | null | Sequential daily order number |
pending_at | string | null | When the order entered PENDING status (ISO 8601) |
created_at | string | Order creation timestamp (ISO 8601) |
updated_at | string | Last update timestamp (ISO 8601) |
3. Acknowledge receipt
Your server must respond with an HTTP status code within ack_http_codes (default: 200, 201, 202). If it doesn't respond or returns a different code, OlaClick retries.
// Express.js example
app.post('/webhooks/olaclick', (req, res) => {
const { event_type, event_id, data } = req.body;
// 1. Check the source header
if (req.headers['source'] !== 'OlaClick') {
return res.status(401).send('Unknown source');
}
// 2. Deduplicate by event_id
if (alreadyProcessed(event_id)) {
return res.status(200).send('Already processed');
}
// 3. Process the event
switch (event_type) {
case 'ORDER_CREATED':
handleNewOrder(data);
break;
case 'ORDER_UPDATED':
handleOrderUpdate(data);
break;
case 'ORDER_DELETED':
handleOrderDeleted(data);
break;
}
// 4. Acknowledge receipt
res.status(200).send('OK');
});
Available events
| Event | Description | Triggered when |
|---|---|---|
ORDER_CREATED | New order created | A customer completes an order |
ORDER_UPDATED | Order updated | Status change (confirmed, preparing, delivered, cancelled), payment update, rider assigned, etc. |
ORDER_DELETED | Order deleted | An order is permanently removed from the system |
Delivery headers
Every webhook delivery includes these headers:
| Header | Value | Description |
|---|---|---|
Content-Type | application/json | Always JSON |
source | OlaClick | Identifies the sender |
| (your custom headers) | (your values) | Any headers configured via webhook_headers |
Retries
If your endpoint doesn't respond with a success code (one of your ack_http_codes), OlaClick retries up to max_retry times (default: 3, max: 10) with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | 30 seconds |
| 2 | 60 seconds |
| 3 | 120 seconds |
If all retries are exhausted, the delivery is marked as failed.
Custom headers
You can add custom headers that OlaClick will include in every delivery. Useful for passing an auth token to your server:
curl -X POST https://public-api.olaclick.app/v1/webhooks \
-H "Authorization: Bearer olk_live_..." \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-server.com/webhooks/olaclick",
"merchant_id": "restaurant_042",
"webhook_headers": {
"Authorization": "Bearer my-secret-token"
}
}'
This way you can authenticate incoming webhook deliveries on your end using your own token.
Manage webhooks
| Operation | Method | Endpoint | Required scope |
|---|---|---|---|
| Create | POST | /v1/webhooks | webhooks:write |
| List | GET | /v1/webhooks | webhooks:read |
| Get | GET | /v1/webhooks/{id} | webhooks:read |
| Update | PATCH | /v1/webhooks/{id} | webhooks:write |
| Delete | DELETE | /v1/webhooks/{id} | webhooks:write |
Request body reference
Create (POST /v1/webhooks)
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
webhook_url | string | ✅ | — | HTTPS endpoint URL for deliveries |
merchant_id | string | ✅ | — | Your own identifier for this merchant (free-form, 1–64 chars). Included in every delivery payload for routing. |
webhook_headers | object | ❌ | {} | Custom headers included in every delivery |
max_retry | integer | ❌ | 3 | Max retries on failure (1–10) |
ack_http_codes | integer[] | ❌ | [200, 201, 202] | HTTP codes considered successful |
event_types | string[] | ❌ | all events | Event types to subscribe to. Values: ORDER_CREATED, ORDER_UPDATED, ORDER_DELETED |
Update (PATCH /v1/webhooks/{id})
All fields optional (at least one required):
| Field | Type | Description |
|---|---|---|
webhook_url | string | New HTTPS endpoint URL |
webhook_headers | object | New custom headers (replaces existing) |
is_active | boolean | Enable/disable the webhook |
max_retry | integer | New retry count (1–10) |
ack_http_codes | integer[] | New success HTTP codes |
event_types | string[] | Event types to subscribe to. Replaces existing list. Values: ORDER_CREATED, ORDER_UPDATED, ORDER_DELETED |
Best practices
- Use
event_typesto filter events — subscribe only to the events you need to reduce noise - Respond 200 immediately and process the event in background
- Store the raw event before processing — useful for debugging
- Deduplicate by
event_id— the same event may arrive more than once due to retries - Verify the
sourceheader — check that it equalsOlaClick - Use custom
webhook_headersto authenticate deliveries on your server - Monitor your endpoint — if it starts failing consistently, deliveries stop after max retries