Webhooks
Subscribe HTTPS endpoints to real-time events, verify signatures, and inspect deliveries.
Webhooks push events to your server as they happen — a payment succeeds, a link is exhausted, a KYC resource is approved. Register one or more HTTPS endpoints, each subscribing to the events it cares about.
Statuses reference
The values inside webhook payloads (transaction status, link status, KYC status, etc.) are the same enums documented in Statuses & enums. The list of event types is in Statuses & enums → Webhook events.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /webhooks | List your webhooks (paginated). |
POST | /webhooks | Create a webhook. Returns the secret once. |
GET | /webhooks/events | List available event types. |
GET | /webhooks/{id} | Retrieve a webhook. |
PATCH | /webhooks/{id} | Update a webhook. |
DELETE | /webhooks/{id} | Delete a webhook (204). |
POST | /webhooks/{id}/regenerate-secret | Rotate the signing secret. |
GET | /webhooks/{id}/deliveries | List delivery attempts. |
POST | /webhooks/{id}/deliveries/{deliveryId}/redeliver | Retry a delivery. |
The webhook object
| Field | Type | Description |
|---|---|---|
id | string (uuid) | Unique identifier. |
url | string | Your HTTPS endpoint. |
description | string | null | Optional label. |
events | array | Subscribed event types. Empty array = all events. |
is_active | boolean | Whether deliveries are sent. |
secret | string | Signing secret (whsec_…). Returned only on create and regenerate. |
created_at / updated_at | string (ISO 8601) | Timestamps. |
List webhooks
curl "https://api.mytpe.appp/api/ext/webhooks?per_page=15" \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET"{
"data": [
{
"id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e",
"url": "https://example.com/webhooks/mytpe",
"description": "Production",
"events": ["transaction.paid", "payment_link.exhausted"],
"is_active": true,
"created_at": "2026-06-09T12:00:00.000Z",
"updated_at": "2026-06-09T12:00:00.000Z"
}
],
"links": { "first": "...?page=1", "last": "...?page=1", "prev": null, "next": null },
"meta": { "current_page": 1, "from": 1, "to": 1, "per_page": 15, "last_page": 1, "total": 1 }
}Create a webhook
| Field | Type | Required | Notes |
|---|---|---|---|
url | string | yes | Must be https://, max 2048. |
description | string | no | Max 255. |
events | array | no | Subset of valid event values. Omit/empty = all. |
is_active | boolean | no | Defaults to active. |
curl -X POST https://api.mytpe.appp/api/ext/webhooks \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/mytpe",
"events": ["transaction.paid", "payment_link.exhausted"]
}'{
"data": {
"id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e",
"url": "https://example.com/webhooks/mytpe",
"description": null,
"events": ["transaction.paid", "payment_link.exhausted"],
"is_active": true,
"secret": "whsec_3f9a2b1c8d7e6f5a4b3c2d1e0f9a8b7c",
"created_at": "2026-06-09T12:00:00.000Z",
"updated_at": "2026-06-09T12:00:00.000Z"
}
}Store the secret now — it is not returned again. Use regenerate-secret to rotate it.
List event types
curl https://api.mytpe.appp/api/ext/webhooks/events \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET"{
"data": [
{ "value": "transaction.paid", "label": "Transaction paid" },
{ "value": "transaction.failed", "label": "Transaction failed" },
{ "value": "payment_link.exhausted", "label": "Payment link exhausted" }
]
}Retrieve a webhook
curl https://api.mytpe.appp/api/ext/webhooks/6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET"{
"data": {
"id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e",
"url": "https://example.com/webhooks/mytpe",
"description": "Production",
"events": ["transaction.paid", "payment_link.exhausted"],
"is_active": true,
"created_at": "2026-06-09T12:00:00.000Z",
"updated_at": "2026-06-09T12:00:00.000Z"
}
}Update a webhook
Accepts the same fields as create (url, description, events, is_active).
curl -X PATCH https://api.mytpe.appp/api/ext/webhooks/6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET" \
-H "Content-Type: application/json" \
-d '{ "events": ["transaction.paid", "transaction.failed"], "is_active": false }'{
"data": {
"id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e",
"url": "https://example.com/webhooks/mytpe",
"description": "Production",
"events": ["transaction.paid", "transaction.failed"],
"is_active": false,
"created_at": "2026-06-09T12:00:00.000Z",
"updated_at": "2026-06-09T13:00:00.000Z"
}
}Delete a webhook
curl -X DELETE https://api.mytpe.appp/api/ext/webhooks/6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET"(empty body)Regenerate the secret
curl -X POST https://api.mytpe.appp/api/ext/webhooks/6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e/regenerate-secret \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET"{ "secret": "whsec_a1b2c3d4e5f6071829304a5b6c7d8e9f" }The previous secret stops validating immediately. Update your endpoint before rotating in production.
List deliveries
Each delivery records one attempt to call your endpoint.
Query parameters: event_type, per_page.
curl "https://api.mytpe.appp/api/ext/webhooks/6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e/deliveries?per_page=15" \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET"{
"data": [
{
"id": "ab12cd34-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"webhook_id": "6b7c8d9e-0f1a-2b3c-4d5e-6f7a8b9c0d1e",
"event_type": "transaction.paid",
"payload": { "event": "transaction.paid", "data": { "id": "8e7d...", "status": "paid" } },
"attempt": 1,
"http_status": 200,
"response_body": "OK",
"delivered_at": "2026-06-09T12:34:57.000Z",
"failed_at": null,
"created_at": "2026-06-09T12:34:56.000Z"
}
],
"links": { "first": "...?page=1", "last": "...?page=1", "prev": null, "next": null },
"meta": { "current_page": 1, "from": 1, "to": 1, "per_page": 15, "last_page": 1, "total": 1 }
}Redeliver
Queue a fresh attempt for a past delivery.
curl -X POST https://api.mytpe.appp/api/ext/webhooks/6b7c8d9e.../deliveries/ab12cd34.../redeliver \
-H "X-Api-Key: $MYTPE_API_KEY" \
-H "X-Api-Secret: $MYTPE_API_SECRET"{ "queued": true }Events
The taxonomy covers transactions, payment instances, payment links, forms, and KYC. See the full list with descriptions in Statuses & enums → Webhook events.
Delivery payload
Every delivery is a JSON POST to your url:
{
"event": "transaction.paid",
"created_at": "2026-06-09T12:34:56.000000Z",
"data": {
"id": "8e7d6c5b-4a39-2817-0f6e-5d4c3b2a1908",
"status": "paid",
"amount": "4500.00",
"currency": "DZD",
"payable_type": "payment_link",
"payable_id": "5a6b7c8d-9e0f-1a2b-3c4d-5e6f7a8b9c0d",
"metadata": { "order_id": "10428" }
}
}Payloads never include PANs or raw gateway data.
Verifying signatures
Each delivery includes an X-Mytpe-Signature header:
X-Mytpe-Signature: t=1733745296,v1=5257a869e7ec...c12dv1 is HMAC_SHA256("{t}.{rawBody}", secret). Recompute it with your webhook's secret and compare
in constant time. Reject if it does not match, or if t is too old (guards against replay).
[$t, $v1] = sscanf($_SERVER['HTTP_X_MYTPE_SIGNATURE'], 't=%d,v1=%s');
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', "{$t}." . $body, $webhookSecret);
if (!hash_equals($expected, $v1) || abs(time() - $t) > 300) {
http_response_code(400);
exit;
}Respond 2xx quickly. Non‑2xx responses are retried; inspect attempts at GET /webhooks/{id}/deliveries and replay with the redeliver endpoint.