Webhooks
Create and manage webhook endpoints.
Webhooks API
The Webhooks API allows you to create, manage, and test webhook endpoints that receive event notifications from PayGate.
The Webhook Endpoint Object
{
"id": "we_abc123def456",
"object": "webhook_endpoint",
"url": "https://yoursite.com/webhooks",
"description": "Production webhook",
"status": "enabled",
"events": [
"payment.succeeded",
"payment.failed",
"subscription.created"
],
"secret": "whsec_...",
"created_at": "2024-01-15T10:00:00Z"
}Attributes
| Attribute | Type | Description |
|---|---|---|
id | string | Unique identifier |
object | string | Always "webhook_endpoint" |
url | string | The endpoint URL |
description | string | Description |
status | string | enabled or disabled |
events | array | Events to subscribe to |
secret | string | Signing secret (only shown once) |
created_at | string | Creation timestamp |
Create a Webhook Endpoint
Creates a new webhook endpoint.
POST /v1/webhooksRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Endpoint URL (must be HTTPS) |
events | array | Yes | Events to subscribe to |
description | string | No | Description |
curl -X POST https://api.44.200.142.19.nip.io/v1/webhooks \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://yoursite.com/webhooks",
"events": [
"payment.succeeded",
"payment.failed",
"subscription.created",
"subscription.canceled"
],
"description": "Production webhook"
}'const endpoint = await paygate.webhooks.endpoints.create({
url: 'https://yoursite.com/webhooks',
events: [
'payment.succeeded',
'payment.failed',
'subscription.created',
'subscription.canceled'
],
description: 'Production webhook'
})
// Save the secret! It's only shown once
console.log(endpoint.secret) // whsec_...endpoint = client.webhooks.endpoints.create(
url='https://yoursite.com/webhooks',
events=[
'payment.succeeded',
'payment.failed',
'subscription.created',
'subscription.canceled'
],
description='Production webhook'
)
# Save the secret! It's only shown once
print(endpoint.secret) # whsec_...$endpoint = $paygate->webhooks->endpoints->create([
'url' => 'https://yoursite.com/webhooks',
'events' => [
'payment.succeeded',
'payment.failed',
'subscription.created',
'subscription.canceled'
],
'description' => 'Production webhook'
]);
// Save the secret! It's only shown once
echo $endpoint->secret; // whsec_...Save the webhook secret immediately. It's only shown once when the endpoint is created.
Retrieve a Webhook Endpoint
Retrieves a webhook endpoint by ID.
GET /v1/webhooks/:idcurl https://api.44.200.142.19.nip.io/v1/webhooks/we_abc123def456 \
-H "Authorization: Bearer sk_test_..."const endpoint = await paygate.webhooks.endpoints.retrieve('we_abc123def456')endpoint = client.webhooks.endpoints.retrieve('we_abc123def456')Update a Webhook Endpoint
Updates a webhook endpoint.
PATCH /v1/webhooks/:idRequest Body
| Parameter | Type | Description |
|---|---|---|
url | string | Endpoint URL |
events | array | Events to subscribe to |
description | string | Description |
status | string | enabled or disabled |
curl -X PATCH https://api.44.200.142.19.nip.io/v1/webhooks/we_abc123def456 \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"events": ["payment.succeeded", "payment.failed"],
"status": "enabled"
}'const endpoint = await paygate.webhooks.endpoints.update('we_abc123def456', {
events: ['payment.succeeded', 'payment.failed'],
status: 'enabled'
})endpoint = client.webhooks.endpoints.update('we_abc123def456',
events=['payment.succeeded', 'payment.failed'],
status='enabled'
)Delete a Webhook Endpoint
Deletes a webhook endpoint.
DELETE /v1/webhooks/:idcurl -X DELETE https://api.44.200.142.19.nip.io/v1/webhooks/we_abc123def456 \
-H "Authorization: Bearer sk_test_..."await paygate.webhooks.endpoints.delete('we_abc123def456')client.webhooks.endpoints.delete('we_abc123def456')List Webhook Endpoints
Returns a list of webhook endpoints.
GET /v1/webhookscurl https://api.44.200.142.19.nip.io/v1/webhooks \
-H "Authorization: Bearer sk_test_..."const endpoints = await paygate.webhooks.endpoints.list()endpoints = client.webhooks.endpoints.list()Available Events
Payment Events
| Event | Description |
|---|---|
payment.created | A payment was created |
payment.pending | Payment is pending authorization |
payment.processing | Payment is being processed |
payment.succeeded | Payment completed successfully |
payment.failed | Payment failed |
payment.canceled | Payment was canceled |
Subscription Events
| Event | Description |
|---|---|
subscription.created | Subscription was created |
subscription.updated | Subscription was updated |
subscription.canceled | Subscription was canceled |
subscription.paused | Subscription was paused |
subscription.resumed | Subscription was resumed |
subscription.trial_will_end | Trial ending in 3 days |
subscription.payment_succeeded | Recurring payment succeeded |
subscription.payment_failed | Recurring payment failed |
Payout Events
| Event | Description |
|---|---|
payout.created | Payout was created |
payout.processing | Payout is being processed |
payout.completed | Payout was successful |
payout.failed | Payout failed |
payout.canceled | Payout was canceled |
Refund Events
| Event | Description |
|---|---|
refund.created | Refund was created |
refund.completed | Refund was successful |
refund.failed | Refund failed |
Checkout Events
| Event | Description |
|---|---|
checkout.session.completed | Checkout session completed |
checkout.session.expired | Checkout session expired |
Webhook Event Object
{
"id": "evt_abc123def456",
"object": "event",
"type": "payment.succeeded",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"object": {
"id": "pay_xyz789",
"object": "payment",
"amount": 5000,
"currency": "GHS",
"status": "succeeded",
...
}
}
}Verifying Signatures
Always verify webhook signatures to ensure requests came from PayGate:
import { Webhook } from '@paygate/node'
const endpointSecret = 'whsec_...'
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-paygate-signature']
try {
const event = Webhook.constructEvent(
req.body,
signature,
endpointSecret
)
// Handle the event
console.log(`Received: ${event.type}`)
res.json({ received: true })
} catch (err) {
console.error('Signature verification failed:', err.message)
res.status(400).send('Invalid signature')
}
})import paygate
endpoint_secret = 'whsec_...'
@app.route('/webhooks', methods=['POST'])
def webhook():
payload = request.data
signature = request.headers.get('X-PayGate-Signature')
try:
event = paygate.Webhook.construct_event(
payload, signature, endpoint_secret
)
except paygate.SignatureVerificationError as e:
return 'Invalid signature', 400
print(f'Received: {event["type"]}')
return {'received': True}$endpointSecret = 'whsec_...';
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_PAYGATE_SIGNATURE'];
try {
$event = \PayGate\Webhook::constructEvent(
$payload,
$signature,
$endpointSecret
);
} catch (\Exception $e) {
http_response_code(400);
exit('Invalid signature');
}
echo "Received: " . $event->type;
http_response_code(200);Never skip signature verification in production. Unsigned webhooks could be spoofed.