Webhooks

Webhooks allow your server to respond instantly to notifications from Asyncpay's servers when events happen in your business.

Introduction

In certain instances, actions on Asyncpay may not occur instantly. This can be due to asynchronous processes like customer payments or actions that involve longer processing times. While regular API requests might not effectively capture these events, one approach is polling—repeatedly making requests at intervals to check for changes.

However, Asyncpay offers a more efficient alternative through webhooks. With our webhooks, your server is alerted promptly when events or actions conclude, allowing immediate reactions. Here's how it works: When an event or process is completed, Asyncpay sends an HTTP POST request to your server, containing all the necessary data to describe the event. This empowers your server to respond effectively and take appropriate actions based on the event.

Enabling webhooks

The initial step in configuring webhooks involves creating a designated endpoint on your server. Asyncpay will send requests to this endpoint whenever specific events occur. This endpoint should include the necessary code to handle the relevant Asyncpay webhooks

Once your server's endpoint is established, you'll need to register it within your Asyncpay dashboard, as illustrated in the video above. After registration, Asyncpay will be able to communicate event notifications to your server.

It is crucial for your server to respond with either a 200 or 201 HTTP status code upon processing a webhook notification. This response informs Asyncpay's servers that the notification has been successfully handled, preventing further redundant requests. This is the protocol for Asyncpay's webhook transmission:

  1. Initial webhook attempts are sent every 5 minutes for the first four tries.

  2. If a positive response is not received, attempts switch to every 6 hours for the next four tries.

  3. If all attempts fail, Asyncpay ceases sending webhooks and notifies you via email.

Ensuring webhook security

As webhook URLs are publicly accessible, verifying the authenticity of requests to your webhook endpoints is paramount. To achieve this, Asyncpay offers a webhook secret that accompanies each webhook request, enabling verification.

Locating the webhook secret is straightforward, as it's available on the same configuration page where the webhook URL is set up, as shown in the video above. Asyncpay sends this secret within a designated header called AsyncPay-Secret with each webhook. All that's required is to compare the value of the secret received with the one stored on your dashboard for verification.

Debugging Webhooks

At Asyncpay, we offer a comprehensive log of every webhook attempt made to your server. This log includes the request's body, the response received from your server, and the status of the request—whether it succeeded or encountered an issue.

View webhook attempts on your dashboard

Our user-friendly webhook interface allows you to review all sent requests and promptly reattempt any webhook that may have failed. This streamlined process significantly enhances the efficiency of your development workflows.

Available events

Asyncpay's webhooks play a crucial role in keeping you informed about various events occurring during a payment's lifecycle. When sending out webhooks, Asyncpay carefully curates relevant information that remains consistent across different payment providers. Additionally, the original payment provider structure is preserved in the webhook data, ensuring the integrity and specificity of the information shared.

Below is a list of the various webhooks that Asyncpay sends in response to specific events, enriching your payment processing experience and keeping you well-informed throughout the payment journey:

1. payment.completed.successfully

This webhook is sent out when a payment has been completed and verified from any payment channel.

payment.completed.successfully
{
  "event_type": "payment.completed.successfully",
  "data": {
    "payment_request_uuid": "eric-934b2d48-f9fb-11ef-a015-0242ac120006",
    "payment_request_ref": "AsP-d9131f643a90d",
    "payment_request_status": "successful",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "e524cdf5-e026-11ef-9cda-0242ac120006",
    "amount": "100",
    "currency": "NGN"
  }
}

2. payment.expired

This webhook is sent out if a payment request is initiated and no successful payment is made after 24 hours.

payment.expired
{
  "event_type": "payment.expired",
  "data": {
    "payment_request_uuid": "eric-77344b88-f9fd-11ef-a015-0242ac120006",
    "payment_request_ref": "AsP-19a9160806004",
    "payment_request_status": "expired",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "e524cdf5-e026-11ef-9cda-0242ac120006",
    "amount": "100",
    "currency": "NGN"
  }
}

3. customer.created

This webhook is sent out after a customer is created.

customer.created
{
  "event_type": "customer.created",
  "data": {
    "customer_uuid": "e097274b-6518-11f0-8f93-0242ac120006",
    "email": "[email protected]"
  }
}

4. customer.updated

This webhook is sent out after a customer is updated.

customer.updated
{
  "event_type": "customer.updated",
  "data": {
    "customer_uuid": "e097274b-6518-11f0-8f93-0242ac120006",
    "email": "[email protected]"
  }
}

5. customer_payment_method.created

This webhook is sent out after a customer payment method is created.

This could be initiated at the point of initiating a payment request, saving a payment method, or subscribing a customer to a plan.

customer_payment_method.created
{
  "event_type": "customer_payment_method.created",
  "data": {
    "customer_payment_method_uuid": "17886a99-651f-11f0-8f93-0242ac120006",
    "customer_uuid": "e097274b-6518-11f0-8f93-0242ac120006",
    "payment_channel": "paystack"
  }
}

6. customer_payment_method.default.updated

This webhook is sent out after the default customer payment method is updated.

customer_payment_method.default.updated
{
  "event_type": "customer_payment_method.default.updated",
  "data": {
    "customer_payment_method_uuid": "17886a99-651f-11f0-8f93-0242ac120006",
    "customer_uuid": "e097274b-6518-11f0-8f93-0242ac120006",
    "payment_channel": "paystack"
  }
}

7. customer_payment_method.deleted

This webhook is sent out after the default customer payment method is deleted.

customer_payment_method.deleted
{
  "event_type": "customer_payment_method.deleted",
  "data": {
    "customer_payment_method_uuid": "1f5ae2f2-e027-11ef-9cda-0242ac120006",
    "customer_uuid": "e524cdf5-e026-11ef-9cda-0242ac120006",
    "payment_channel": "paystack"
  }
}

8. payout.completed.successfully

This webhook is sent out after a payout (bank transfer) is completed successfully.

payout.completed.successfully
{
  "event_type": "payout.completed.successfully",
  "data": {
    "payout_uuid": "03452695-fa2b-11ef-a015-0242ac120006",
    "payout_ref": "AsPR-1f0a6377197baPMCKDU_1",
    "payout_status": "successful",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "beneficiary_uuid": "f14bbecc-fa26-11ef-a015-0242ac120006",
    "amount": "100",
    "currency": "NGN"
  }
}

9. payout.error

This webhook is sent out after a payout (bank transfer) fails.

payout.error
{
  "event_type": "payout.error",
  "data": {
    "payout_uuid": "46b3f50d-0846-11f0-ab99-0242ac120006",
    "payout_ref": "AsPR-706130140e768PMCKDU_1",
    "payout_status": "failed",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "beneficiary_uuid": "c904b6b0-fcb2-11ef-a015-0242ac120006",
    "amount": "100",
    "currency": "NGN"
  }
}

10. payout.expired

This webhook is sent out after a payout expires. Payouts expire if they are not successful after 48 hours.

payout.expired
{
  "event_type": "payout.expired",
  "data": {
    "payout_uuid": "add61d49-0851-11f0-ab99-0242ac120006",
    "payout_ref": "AsPR-3836298689f85PMCKDU_1",
    "payout_status": "expired",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "beneficiary_uuid": "c904b6b0-fcb2-11ef-a015-0242ac120006",
    "amount": "100",
    "currency": "NGN"
  }
}

11. subscription.initiated

This webhook is sent the first time a customer subscribes to your subscription plan.

subscription.initiated
{
  "event_type": "subscription.initiated",
  "data": {
    "subscription_uuid": "599eaeb9-085f-11f0-ab99-0242ac120006",
    "subscription_plan_uuid": "f9e74a00-e029-11ef-9cda-0242ac120006",
    "customer_payment_method_uuid": "54b59d45-0852-11f0-ab99-0242ac120006",
    "subscription_status": "active",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "234a31a3-0852-11f0-ab99-0242ac120006"
  }
}

12. subscription.renewal.successful

This webhook is sent whenever Asyncpay successfully charges a customer for a subscription at the end of the subscription period.

subscription.renewal.successful
{
  "event_type": "subscription.renewal.successful",
  "data": {
    "subscription_uuid": "6cb25071-e2e3-11ef-b6cb-0242ac130005",
    "subscription_plan_uuid": "f9e74a00-e029-11ef-9cda-0242ac120006",
    "customer_payment_method_uuid": "1f5ae2f2-e027-11ef-9cda-0242ac120006",
    "subscription_status": "active",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "e524cdf5-e026-11ef-9cda-0242ac120006"
  }
}

13. subscription.renewal.error

This webhook is sent whenever Asyncpay unsuccessfully attempts to charge a customer for a subscription at the end of the subscription period.

subscription.renewal.successful
{
  "event_type": "subscription.renewal.error",
  "data": {
    "subscription_uuid": "6cb25071-e2e3-11ef-b6cb-0242ac130005",
    "subscription_plan_uuid": "f9e74a00-e029-11ef-9cda-0242ac120006",
    "customer_payment_method_uuid": "1f5ae2f2-e027-11ef-9cda-0242ac120006",
    "subscription_status": "active",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "e524cdf5-e026-11ef-9cda-0242ac120006"
  }
}

14. subscription.cancelled

This webhook is sent out whenever a subscription is canceled.

A canceled subscription is not automatically terminated. It just means that the subscription will be active until the next billing period (when the subscription expires) and then it will be terminated.

subscription.cancelled
{
  "event_type": "subscription.cancelled",
  "data": {
    "subscription_uuid": "6cb25071-e2e3-11ef-b6cb-0242ac130005",
    "subscription_plan_uuid": "f9e74a00-e029-11ef-9cda-0242ac120006",
    "customer_payment_method_uuid": "1f5ae2f2-e027-11ef-9cda-0242ac120006",
    "subscription_status": "active",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "e524cdf5-e026-11ef-9cda-0242ac120006"
  }
}

15. subscription.terminated

This webhook is sent out whenever a subscription is terminated. A terminated subscription is one that is no longer active.

A subscription could be terminated for several reasons such as:

  1. A subscription is terminated if, at the end of the subscription period (or at the next billing period), Asyncpay is unable to charge the payment method after four attempts (or no payment method is saved for the customer).

  2. The subscription is canceled when the next billing period arrives

  3. The subscription is terminated via API with the terminate endpoint

subscription.terminated
{
  "event_type": "subscription.terminated",
  "data": {
    "subscription_uuid": "54c01737-0852-11f0-ab99-0242ac120006",
    "subscription_plan_uuid": "f9e74a00-e029-11ef-9cda-0242ac120006",
    "customer_payment_method_uuid": "54b59d45-0852-11f0-ab99-0242ac120006",
    "subscription_status": "terminated",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "234a31a3-0852-11f0-ab99-0242ac120006"
  }
}

16. subscription.renewal.impending

This webhook is sent out when the customer’s subscription period is more than 80% and the next billing period is approaching.

You can listen for this webhook and send your customer emails instead of building a cronjob yourself

subscription.renewal.impending
{
  "event_type": "subscription.renewal.impending",
  "data": {
    "subscription_uuid": "20516649-0861-11f0-ab99-0242ac120006",
    "subscription_plan_uuid": "ec210147-0860-11f0-ab99-0242ac120006",
    "customer_payment_method_uuid": "54b59d45-0852-11f0-ab99-0242ac120006",
    "subscription_status": "active",
    "payment_channel": "paystack",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "customer_uuid": "234a31a3-0852-11f0-ab99-0242ac120006"
  }
}

17. bulk_payout.initiated

This webhook is sent out when a bulk payout is successfully initiated in a business.

bulk_payout.initiated
{
  "event_type": "bulk_payout.initiated",
  "data": {
    "bulk_payout_uuid": "20516649-0861-11f0-ab99-0242ac120006",
    "bulk_payout_initiated_from": "API",
		"total_requested_payouts": "15",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf"
  }
}

18. bulk_payout.processing.completed

This webhook is sent out when all the payouts in a bulk payout have been successfully processed

bulk_payout.processing.completed
{
  "event_type": "bulk_payout.processing.completed",
  "data": {
    "bulk_payout_uuid": "20516649-0861-11f0-ab99-0242ac120006",
    "bulk_payout_initiated_from": "API",
		"total_requested_payouts": "15",
    "business_uuid": "a264ee84-9a0b-4434-b997-ce716dbf7cdf",
    "payout_uuids": [
	    "a264ee84-9a0b-4434-b997-ce716dbf7cdf"
    ]
  }
}

Deprecated Events

The webhooks listed below are deprecated and maintained only for backward compatibility. While you may still receive these events with this event_type in your system, they will be removed soon. We recommend ignoring them and migrating to the newer, more concise webhook formats listed above.

Event
Description

payment_request.initiated

This is sent when a new payment request is created. This usually happens when a new checkout is initiated either via our SDK or API.

payment_request.relayed

This is sent when a payment request is relayed to a different payment channel.

payment_request.successful

This is sent when a payment request has been completed and verified

payment_request.expired

This is sent when a payment request has been initiated but no successful payment has been made after 24 hours.

transaction.initiated

This is sent when a transaction was just created. This usually happens when a payment request is relayed to a payment provider.

transaction.verified

This is sent when a payment has been completed and verified from a payment provider.

transaction.verification.failed

This is sent when a transaction verification attempt failed

customer.cancelled.subscription

This is sent when a customer cancels their subscription

customer.subscribed.to.plan.successfully

This is sent when a customer is subscribed to a plan successfully

customer.subscription.charged.successfully

This is sent when a customer's payment method is successfully charged at the end of the subscription period

customer.subscription.charge.failed

This is sent when a customer's payment method is unsuccessfully charged at the end of the subscription period

payout.successful

This is sent when a payout is successsful

payout.failed

This is sent when a payout fails

Last updated