About Aeropay Webhooks

Aeropay allows you to subscribe to a number of webhooks which will send information about transactions when they update. These webhooks allow you to understand in real-time when transactions are created, succeed, decline, or are refunded.

Webhook Topics

Topic NameDescription
transaction_completedThis topic will send a payload of a transaction object when the transaction is completed.
transaction_declinedThis topic will send a payload of a transaction object when the transaction declines.
transaction_refundedThis topic will send a payload of a transaction object when the transaction is refunded.
transaction_voidedThis topic will send a payload of a transaction object when the transaction is voided.
preauthorized_transaction_createdThis topic will send a payload of a preauthorized transaction object when the preauthorized transaction is created.
user_suspendedThis topic will send a payload of a userid when a user is suspended.
user_activeThis topic will send a payload of a userid when a previously suspended user has been reactivated.
merchant_reputation_updatedThis topic will send a payload of a users whose reputations have been updated after a successful call to POST /merchantReputation.

Subscribing to a webhook

HTTP request

Sandbox - POST https://staging-api.aeropay.com/webhook

Production - POST https://api.aeropay.com/webhook

Code Example - Request

curl --request POST \
     --url https://staging-api.aeropay.com/webhook \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "topic": "transaction_declined",
  "url": "https://your-callback-url.com"
}
'

Code Example - Payload from Webhook

{
  "topic": "transaction_declined",
  "data": {
    "locationId": "794",
    "paymentType": "payment+",
    "createdDate": "1694787546",
    "amount": "15.00",
    "merchantId": "582",
    "status": "declined",
    "uuid": "8bc20976-2e18-4c5c-93b4-20fd853d78a4",
    "attributes": [{ "value": "3.00", "name": "tip", "description": "flat" }],
    "id": "231933",
    "userId": "12695",
    "title": "Online Transaction",
    "apFee": "0.28",
    "returnCode": "R01"
  },
  "date": "2024-04-05 15:25:49"
}
{ 
  "topic" :  "user_suspended",
  "data" :  { "userid" :  "12695" },
  "date": "2024-04-05 15:25:49"
}

Webhook Security

In order to secure and validate your webhook subscriptions, Aeropay provides the option to generate a signing key that can be used to validate the payload sent from Aeropay. Once a signing key has been generated, ensure it is stored in a safe place. The same signingKey will be used for all webhook topics you subscribe to.

Step 1: Generate a Signing Key

Begin by generating a signing key by calling POST /createWebhookSigningKey

Code Example - Request

curl --request POST \
     --url https://staging-api.aeropay.com/createWebhookSigningKey \
     --header 'accept: application/json' \
     --header 'content-type: application/json'

Code Example - Response

{
    "success": true,
    "message": "This is your signingKey used to validate any Webhooks you are subscribed to. Please store this key for future use, as it will not be displayed at any point afterwards.",
    "signingKey": "8a001072f14546d95c861ef77b6bb6899f4c7f0f8c275978e1bd3edcdacf34da"
}

Step 2: Using your signingKey

Once you've created a signingKey and stored the key securely, all webhooks sent to you from Aeropay will include a signature token in the header labeled ap-signature.

Example webhook from Aeropay:

{
    "headers": {
        "ap-signature": "c46f292ed0a1b308cf55c3af6de926a8ff8a738cbcf575e9650222955d6477bf"
    },
    "body": {
        "topic": "user_suspended",
        "data": {
            "userid": "12695"
        },
    "date": "2024-04-12 20:42:35"
    }
}

Step 3: Validating the Webhook

Now that you have generated a signingKey and received the ap-signature token in the webhook response, you can now hash the webhook using the payload body and signingKey. You will need to generate the webhook signature via a SHA256 hash of the webhook payload body, and the URL the webhook was sent to. Example below:

body = {
  "topic": "user_suspended",
  "data": {
    "userid": "12695"
  },
  "date": "2024-04-12 20:42:35",
  "url": "https://webhook.site/d5948a80-0c4e-481b-b497-cfe90422562a"
}
webhook_signature = "c46f292ed0a1b308cf55c3af6de926a8ff8a738cbcf575e9650222955d6477bf"
// Hash payload in SHA256 with signingKey, then pass in header
if signingKey:
    payload_str = json.dumps({'topic': body.get('topic'), 'data': body.get('data'), 'date': body.get('date'), 'url': body.get('url')})
    webhook_signature = hmac.new(signingKey.encode('utf-8'), payload_str.encode('utf-8'), digestmod=sha256).hexdigest()
    webhook_headers['AP-Signature'] = webhook_signature

If the generated hash matches the ‘AP-Signature’ header, the webhook is successfully validated.
If the generated hash does not match, the webhook is unsafe or an input was incorrect when generating the original token or the compared hash.

Webhook Responses

WebhookWebhook response
transaction_refunded{
"topic": "transaction_refunded",
"data": {
"uuid": "5e571b4b-f182-48ef-8c5a-abc624e04f56",
"title": "1658388",
"attributes": [],
"id": "1658636",
"amount": "5.00",
"status": "pending",
"paymentType": "reversal",
"userId": "1102575",
"locationId": "2985",
"merchantId": "1602",
"createdDate": "1723735777",
"apFee": "0.25"
},
"date": "2024-08-15 15:29:40"
}
transaction_voided{
"topic": "transaction_voided",
"data": {
"merchantId": "1602",
"userId": "1102575",
"paymentType": "payment",
"status": "pending",
"apFee": "0.75",
"id": "1658635",
"title": "test void webhook",
"uuid": "e15db623-6727-4d56-a9a6-74af861ee75a",
"createdDate": "1723735128",
"locationId": "2985",
"amount": "25.00",
"attributes": []
},
"date": "2024-08-15 15:19:02"
}
preauthorized_transaction_created{
"topic": "preauthorized_transaction_created",
"data": {
"id": "24141",
"transactionId": "None",
"merchantId": "1602",
"merchantAccountId": "1190",
"merchantLocationId": "2985",
"userId": "1102575",
"userAccountId": "749960",
"userName": "Brett Neibarger",
"userEmail": "[email protected] ",
"amount": "1500",
"dollarAmount": "15.00",
"originalAmount": "1500",
"description": "Online Transaction",
"merchantReputationStatus": "0",
"userReputationStatus": "5",
"uuid": "5dd8af88-8284-4a8a-aac1-058fbe40d85a",
"createdDate": "1723735276",
"expiryDate": "1723994476",
"cancellationDate": null,
"creditPartnerId": null,
"status": "live"
},
"date": "2024-08-15 15:21:16"
}
user_suspended{
"topic": "user_suspended",
"data": {
"userid": "1102575"
},
"date": "2024-08-15 15:41:33"
}
user_active{
"topic": "user_active",
"data": {
"userid": "1102575"
},
"date": "2024-08-15 15:42:17"
}
merchant_reputation_updated{
"topic": "merchant_reputation_updated",
"data": {
"totalUsersUpdated": 3,
"totalFailures": 0,
"totalNotEligibleUsers": 0,
"failedReputationUpdates": [],
"notEligibleUsers": [],
"successfulReputationUpdates": [
{"userId": 12695, "previousReputation": null, "currentReputation": 1},
{"userId": 1103154, "previousReputation": 1, "currentReputation": 0},
{"userId": 13055, "previousReputation": 2, "currentReputation": 0}
]
},
"date": "2024-07-31 21:36:16"
}

🚧

Replacing your SigningKey

If you need to replace your signingKey (due to misplacing, security concerns, periodic rotations, etc), you can generate a new key by calling POST /createWebhookSigningKey again. Doing so will replace the old signingKey for all future webhooks.