Webhook Security
Webhook security is optional
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 /v2/createWebhookSigningKey
Code Example - Request
curl --request POST \
--url https://api.sandbox-pay.aero.inc/v2/createWebhookSigningKey \
--header 'accept: application/json' \
--header 'authorization: Bearer {merchant-token}' \
--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": "transaction_completed",
"payloadVersion": "2.0",
"data": {
"uuid": "8bc20976-2e18-4c5c-93b4-20fd853d78a4",
"id": "231933",
"status": "completed"
},
"date": "2024-04-12 20:42:35"
}
}Step 3: Validating the Webhook
Cross-Language JSON Serialization
Different languages serialize JSON differently (key ordering, whitespace, number formatting). We strongly recommend thorough testing of your HMAC implementation with real webhook payloads from sandbox before deploying to production.
How Aeropay Signs Webhooks
Aeropay computes the signature by:
- Taking all fields from the webhook body (including
topic,data,date,payloadVersion, etc.) - Adding a
urlfield containing your registered webhook callback URL - Serializing to JSON with specific formatting (spaces after colons and commas)
- Computing an HMAC-SHA256 hash using your signing key
Important: JSON Formatting RequirementsThe signature is sensitive to JSON formatting. You must match Aeropay's exact serialization:
- Spacing: Use
', 'after commas and': 'after colons (with spaces)- All fields: Include every field from the webhook body, not just a subset
- Add URL: Append your registered webhook callback URL to the payload as a
urlfield
Critical Notes
1. Use Your Registered Webhook URL
The url field must match exactly what you passed when calling POST /v2/webhook to subscribe. This includes:
- Protocol (
http://vshttps://) - Trailing slashes
- Port numbers (if applicable)
- Subdomain
Example: If you registered https://api.example.com/webhooks/aeropay, use that exact string, not https://api.example.com/webhooks/aeropay/
2. Include All Body Fields
Don't manually select specific fields. Include everything from the webhook body. These should be:
topicdatadatepayloadVersion
3. Signing Key Timing
Only webhooks sent after creating the signing key will have valid signatures. If you:
- Set up webhook subscriptions
- Then create a signing key
- Webhooks sent before step 2 won't have valid signatures
You'll need to trigger new events (create transactions, etc.) to test validation.
4. One Key Per Merchant Account
All webhook subscriptions for your merchant account use the same signing key, regardless of:
- Webhook topic (
transaction_completed,user_suspended, etc.) - Callback URL
- Number of subscriptions
Creating a new signing key replaces the old one for all webhooks.
5. Replacing Your Signing Key
If you need to replace your signingKey (due to misplacing it, security concerns, or periodic rotation), call POST /v2/createWebhookSigningKey again. This will:
- Generate a new signing key
- Invalidate the old signing key immediately
- Apply to all future webhooks
There is no grace period where both keys work simultaneously.
Testing Your Implementation
Before going to production:
- Create a signing key in sandbox
- Subscribe to a webhook (e.g.,
transaction_completed) - Trigger a test transaction in sandbox
- Capture the webhook and verify your code produces a matching signature
- Test with multiple webhook topics to ensure consistency
Updated 11 days ago
See common language examples of webhook security implementation:
