Build payments into your product with MyTPE Pay. Start integrating →
Logo
API reference

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

MethodPathDescription
GET/webhooksList your webhooks (paginated).
POST/webhooksCreate a webhook. Returns the secret once.
GET/webhooks/eventsList 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-secretRotate the signing secret.
GET/webhooks/{id}/deliveriesList delivery attempts.
POST/webhooks/{id}/deliveries/{deliveryId}/redeliverRetry a delivery.

The webhook object

FieldTypeDescription
idstring (uuid)Unique identifier.
urlstringYour HTTPS endpoint.
descriptionstring | nullOptional label.
eventsarraySubscribed event types. Empty array = all events.
is_activebooleanWhether deliveries are sent.
secretstringSigning secret (whsec_…). Returned only on create and regenerate.
created_at / updated_atstring (ISO 8601)Timestamps.

List webhooks

Request
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"
200 OK
{
  "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

FieldTypeRequiredNotes
urlstringyesMust be https://, max 2048.
descriptionstringnoMax 255.
eventsarraynoSubset of valid event values. Omit/empty = all.
is_activebooleannoDefaults to active.
Request
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"]
  }'
201 Created
{
  "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

Request
curl https://api.mytpe.appp/api/ext/webhooks/events \
  -H "X-Api-Key: $MYTPE_API_KEY" \
  -H "X-Api-Secret: $MYTPE_API_SECRET"
200 OK
{
  "data": [
    { "value": "transaction.paid", "label": "Transaction paid" },
    { "value": "transaction.failed", "label": "Transaction failed" },
    { "value": "payment_link.exhausted", "label": "Payment link exhausted" }
  ]
}

Retrieve a webhook

Request
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"
200 OK
{
  "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).

Request
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 }'
200 OK
{
  "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

Request
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"
204 No Content
(empty body)

Regenerate the secret

Request
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"
200 OK
{ "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.

Request
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"
200 OK
{
  "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.

Request
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"
200 OK
{ "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...c12d

v1 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).

PHP
[$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.

On this page