Webhooks
Receive real-time order events via webhooks.
Overview
Webhooks let your system receive automatic notifications when events occur in YaVendio, such as a new order being created. Instead of polling the API, YaVendio sends an HTTP POST to the URL you configure.
Available events
| Event | Description |
|---|---|
order.created |
A new order is created |
order.status_changed |
Order status changes |
Set up a webhook
1. Register your URL
curl -X POST https://api.ya.onl/v1/webhooks \
-H "X-API-Key: yv_live_v1_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/yavendio",
"events": ["order.created"],
"description": "Order notifications"
}'Response:
{
"id": "ep_2bNzYPyBRuC1mMYXXAvgSSuz4Fz",
"url": "https://your-server.com/webhooks/yavendio",
"events": ["order.created"],
"is_active": true,
"description": "Order notifications",
"created_at": "2026-03-22T10:00:00Z",
"secret": "whsec_5LTSI03vOvKsLGbAibiB7GGgLDdJMtGk"
}The secret field is only shown once, when creating the webhook. Store it securely — you'll need it to verify signatures.
2. Verify the signature
Each delivery includes three headers for verification:
| Header | Description |
|---|---|
Svix-Id |
Unique message ID |
Svix-Timestamp |
UNIX timestamp of the signature |
Svix-Signature |
HMAC-SHA256 signature of the payload |
Verification example in Python:
import hmac
import hashlib
import base64
def verify_webhook(payload: bytes, headers: dict, secret: str) -> bool:
msg_id = headers["Svix-Id"]
timestamp = headers["Svix-Timestamp"]
signature = headers["Svix-Signature"]
# Build the signed message
to_sign = f"{msg_id}.{timestamp}.{payload.decode()}".encode()
# Decode the secret (strip "whsec_" prefix and base64 decode)
secret_bytes = base64.b64decode(secret.replace("whsec_", ""))
# Calculate the expected signature
expected = base64.b64encode(
hmac.new(secret_bytes, to_sign, hashlib.sha256).digest()
).decode()
# Compare with the received signature (format: "v1,<base64>")
received = signature.split(",")[1] if "," in signature else signature
return hmac.compare_digest(expected, received)You can also use the official Svix library:
pip install svixfrom svix.webhooks import Webhook
wh = Webhook("whsec_5LTSI03vOvKsLGbAibiB7GGgLDdJMtGk")
payload = wh.verify(request.body, request.headers)3. Payload format
The order.created payload contains the full order in JSON:
{
"id": 176,
"created_at": "2026-03-22T04:39:33.560884Z",
"merchant_id": 1113,
"currency": "PEN",
"total_amount": "205.0",
"delivery_fee": "10.0",
"status": "pending",
"payment_terms": "pending",
"payment_method": "yape",
"customer": {
"name": "Juan Perez",
"phone_number": "51999000111"
},
"variants": [
{
"id": 6110,
"name": "AZUL - S",
"quantity": 1,
"base_price": 205.0
}
]
}The payload uses YaVendio's internal schema. If the structure changes (e.g., a new field is added), it is the receiver's responsibility to adapt.
Manage webhooks
List registered webhooks
curl https://api.ya.onl/v1/webhooks -H "X-API-Key: yv_live_v1_your_api_key"Disable a webhook
curl -X PATCH https://api.ya.onl/v1/webhooks/{webhook_id} \
-H "X-API-Key: yv_live_v1_your_api_key" \
-H "Content-Type: application/json" \
-d '{"is_active": false}'Delete a webhook
curl -X DELETE https://api.ya.onl/v1/webhooks/{webhook_id} \
-H "X-API-Key: yv_live_v1_your_api_key"Check delivery attempts
curl https://api.ya.onl/v1/webhooks/{webhook_id}/deliveries/{message_id} \
-H "X-API-Key: yv_live_v1_your_api_key"Retries
If your server does not respond with a 2xx status code, YaVendio will automatically retry delivery with exponential backoff. After multiple consecutive failures, the webhook will be automatically disabled.
Limits
- Maximum 20 webhooks per merchant
- Delivery timeout: 30 seconds
- Events are delivered chronologically, but exactly-once delivery is not guaranteed — design your receiver to be idempotent
