Events Reference
Complete reference of all webhook events, payloads, and real-world use cases for transactions and payment links.
Webhook Events
MyTPE Pay sends webhooks for two categories of events: Transaction events (payment status changes) and Pay Link events (link lifecycle changes).
Transaction Events
Triggered whenever a transaction's status changes.
| Event | Triggered When |
|---|---|
transaction.completed | Payment successful — funds confirmed |
transaction.failed | Payment failed or timed out (10 min) |
transaction.refused | Payment refused by the bank or admin |
transaction.pending | Transaction created, awaiting payment |
transaction.processing | Payment is being processed |
Transaction Payload
{
"delivery_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"event": "transaction.completed",
"timestamp": "2026-04-09T14:30:00.000000Z",
"data": {
"transaction": {
"id": "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d",
"order_number": "ORD-1712678400-ABC",
"order_id": "12345678",
"status": "completed",
"amount": 5000.00,
"payment_method": "online",
"environment": "production",
"approval_code": "ABC123",
"gateway_message": null,
"motif": null,
"customer": {
"name": "Karim Benali",
"email": "karim@example.com",
"phone": "+213555123456"
},
"metadata": {
"reference": "REF-2026-001"
},
"created_at": "2026-04-09T14:25:00.000000Z",
"updated_at": "2026-04-09T14:30:00.000000Z"
},
"pay_link": {
"id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"title": "Consultation Dr. Ahmed",
"details": "Consultation medicale",
"slug": "consultation-dr-ahmed",
"type": "dynamic",
"amount": 5000.00,
"status": "active",
"payment_mode": "reusable",
"max_payments": null,
"successful_payments_count": 12,
"remaining_payments": null
},
"instance": {
"id": "abc123-def456",
"name": "Cabinet Dr. Ahmed"
}
}
}Transaction Field Reference
| Field | Type | Description |
|---|---|---|
data.transaction.id | string (UUID) | Unique transaction ID |
data.transaction.order_number | string | Order reference |
data.transaction.order_id | string|null | Gateway order ID |
data.transaction.status | string | completed, failed, refused, pending, processing |
data.transaction.amount | number | Amount in DZD |
data.transaction.payment_method | string | online, cheque, bank_transfer |
data.transaction.environment | string | production or development |
data.transaction.approval_code | string|null | Bank approval code |
data.transaction.gateway_message | string|null | Gateway response message |
data.transaction.motif | string|null | Refusal reason (if refused) |
data.transaction.customer | object | Customer details |
data.transaction.metadata | object | UDFs and extra data |
data.transaction.created_at | string (ISO 8601) | When created |
data.transaction.updated_at | string (ISO 8601) | When last updated |
data.pay_link | object|null | Associated payment link (null for instance-level transactions) |
data.instance | object | MyTPE Pay instance |
Pay Link Events
Triggered whenever a payment link is created, updated, or its status changes.
| Event | Triggered When |
|---|---|
pay_link.created | New payment link created |
pay_link.updated | Link details changed (title, amount, etc.) |
pay_link.activated | Link set to active |
pay_link.deactivated | Link manually deactivated |
pay_link.closed | Link closed (max_payments reached or one-shot used) |
pay_link.expired | Link auto-expired by the inactivity sweeper — no successful payment within effective_inactivity_timeout_minutes. Terminal: expired links cannot be reactivated. Only one_shot and limited modes can fire this event. See Inactivity Expiry for the resolution chain. |
pay_link.deleted | Link deleted |
Pay Link Payload
{
"delivery_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event": "pay_link.closed",
"timestamp": "2026-04-09T15:00:00.000000Z",
"data": {
"pay_link": {
"id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"title": "Ticket Conference Tech 2026",
"details": "Billet d'entree pour la conference",
"slug": "ticket-conf-tech-2026",
"type": "dynamic",
"amount": 2000.00,
"status": "closed",
"payment_mode": "limited",
"max_payments": 100,
"successful_payments_count": 100,
"remaining_payments": 0,
"metadata": {},
"settings": {
"show_retry_button": true
},
"created_at": "2026-04-01T10:00:00.000000Z",
"updated_at": "2026-04-09T15:00:00.000000Z"
},
"instance": {
"id": "abc123-def456",
"name": "Cabinet Dr. Ahmed"
}
}
}Pay Link Field Reference
| Field | Type | Description |
|---|---|---|
data.pay_link.id | string (UUID) | Unique link ID |
data.pay_link.title | string | Link title |
data.pay_link.details | string | Link description |
data.pay_link.slug | string | URL slug |
data.pay_link.type | string | static or dynamic |
data.pay_link.amount | number|null | Fixed amount (null for static) |
data.pay_link.status | string | active, inactive, closed, expired |
data.pay_link.payment_mode | string | reusable, one_shot, limited |
data.pay_link.max_payments | integer|null | Max payments allowed (null = unlimited) |
data.pay_link.successful_payments_count | integer | Total successful payments |
data.pay_link.remaining_payments | integer|null | Remaining quota (null = unlimited) |
data.pay_link.metadata | object | Extra metadata |
data.pay_link.settings | object | Link settings (e.g., retry button) |
data.pay_link.created_at | string (ISO 8601) | When created |
data.pay_link.updated_at | string (ISO 8601) | When last updated |
data.instance | object | MyTPE Pay instance |
Transaction Use Cases
1. Payment Completed
Event: transaction.completed
A customer successfully paid via your payment link.
What to do:
- Mark the order as paid in your system
- Send a confirmation email/SMS to the customer
- Update inventory or grant access to a service
- Generate an invoice
2. Payment Failed / Timed Out
Event: transaction.failed
The payment failed or the customer didn't complete payment within 10 minutes.
What to do:
- Mark the order as failed
- Notify the customer to retry
- Release reserved inventory
- Log the failure for analytics
3. Payment Refused
Event: transaction.refused
The bank or admin refused the payment. Check data.transaction.motif for the reason.
What to do:
- Notify the customer with the refusal reason
- Suggest an alternative payment method
- Log for dispute resolution
4. Payment Pending
Event: transaction.pending
A new transaction was created — the customer has 10 minutes to complete payment.
What to do:
- Create a pending order in your system
- Reserve inventory temporarily
- Show a "waiting for payment" status
5. Payment Processing
Event: transaction.processing
The payment is being verified by the bank.
What to do:
- Update order status to "processing"
- Show a "verifying payment" status to the customer
Pay Link Use Cases
6. Link Created
Event: pay_link.created
A new payment link was created on the instance.
What to do:
- Sync the link to your product catalog
- Auto-distribute the link URL to customers
7. Link Closed (Quota Reached)
Event: pay_link.closed
The payment link reached its max_payments limit and was automatically closed.
What to do:
- Mark the product/event as sold out
- Stop showing the link to customers
- Generate a summary report
8. Link Deactivated
Event: pay_link.deactivated
The merchant manually deactivated the link.
What to do:
- Hide the payment option from your site
- Show "temporarily unavailable" to customers
9. Link Expired
Event: pay_link.expired
A one_shot or limited link was auto-closed by the inactivity sweeper because no successful payment arrived within its configured effective_inactivity_timeout_minutes window. The status is now expired and cannot be reactivated — expired is a terminal state by policy.
The sweeper runs every 5 minutes. The activity clock resets only on successful payments (not on pending/failed/refused), and starts at link creation. The applied timeout is resolved per-link via the fallback chain: link override → instance default → no expiry. See Inactivity Expiry and Update Instance for the full configuration model.
What to do:
- Release any reserved resources (held inventory, seat reservations, etc.)
- Notify the customer that the payment window has closed
- Generate a new link if the merchant wants to retry the same transaction (expired links cannot be reopened)
- Log for analytics — high expired-rate may signal that the configured window is too short for your customer base
Real-World Scenarios
E-commerce with Full Lifecycle
1. Merchant creates payment link → you receive: pay_link.created
2. Customer clicks "Pay" → you receive: transaction.pending
3. Bank processes → you receive: transaction.completed
4. After 100 sales → you receive: pay_link.closed
5. Product automatically marked as sold outSubscription / Recurring Service
1. Create a payment link for monthly fee
2. Send link to customer
3. Customer pays → transaction.completed → extend subscription
4. If payment fails → transaction.failed → send reminder
5. Merchant deactivates link → pay_link.deactivated → pause billingEvent Registration with Limited Tickets
1. Create limited link (max_payments: 200) → pay_link.created
2. Each ticket purchase → transaction.completed
3. Track remaining_payments in real-time
4. When sold out → pay_link.closed → show "SOLD OUT"
5. If event cancelled → merchant deactivates → pay_link.deactivatedDonation / Zakat Collection
1. Create reusable link → pay_link.created
2. Each donation → transaction.completed → record donor
3. Send thank-you receipt automatically
4. Track total collected via successful_payments_count
5. Campaign ends → merchant deactivates → pay_link.deactivatedMulti-Product Store
1. Create one link per product → multiple pay_link.created events
2. Monitor transactions across all links
3. Use pay_link.id in webhook to identify which product was purchased
4. When a product sells out → pay_link.closed → update stock
5. Merchant updates price → pay_link.updated → sync to storefront