Introduction
Webhooks allow your application to receive real-time notifications from Altitude Pay whenever specific events occur. Instead of polling APIs, you can set up a webhook endpoint to automatically receive updates when important activities happen.
Webhooks enable event-driven workflows, such as transaction status updates or system notifications, without the need for manual polling.
How Webhooks Work
When an event occurs (for example, a transaction is processed), Altitude Pay sends an HTTP POST request to your registered webhook URL. The request contains a JSON payload describing the event.
Each webhook request is signed using JWT (JSON Web Token) for security and integrity verification.
You must set up an endpoint on your server to receive, validate, and process these webhook notifications.
Configuring Webhooks
Currently, webhook configuration is not self-service.\ To configure webhook delivery for your account:
- Contact the Altitude Pay Support Team.
- Provide your webhook endpoint URL and any environment-specific details.
- Our team will configure your webhook subscriptions on your behalf.
Support contact information is available through your client portal or support@altitudepay.solutions.
Security and Signature Verification
Every webhook request from Altitude Pay includes a JWT token in the Authorization header, as Bearer <JWT>.\
The JWT is signed with RS256 and must be verified to ensure the authenticity of the webhook.
Signature details:
-
The JWT payload contains a
dataclaim:* The{ "SHA512": "<digest-value>" }<digest-value>is the SHA-512 hash of the webhook request body, encoded as lowercase hexadecimal (128 characters). It is not Base64. * Hash the raw request body exactly as you received it, before you parse or re-serialise the JSON. Your digest must match the one in the JWT payload. * The JWT must also be cryptographically verified using the correct public key: see Which key signs a webhook.
Which key signs a webhook
The key depends on the event, and the JWT's sub claim tells you which one was used:
| Events | Signed with | sub claim |
|---|---|---|
Every Transaction Processed event, for example transaction-svc:transaction:purchase:approvedtokenization-webhook:payment-method:tokenized |
Your merchant private key | Your merchant ID |
transaction-svc:transaction:createdtransaction-svc:account:transaction:createdtransaction-svc:account:transaction:updatedtransaction-svc:transaction:full:createdtransaction-svc:transaction:full:updated |
The Altitude Pay private key | The Altitude Pay tenant ID |
To choose the key, decode the JWT without verifying it and read sub:
- If
subis your merchant ID, verify with your merchant public key, the same key you use to encrypt card data. - If
subis the Altitude Pay tenant ID, verify with the Altitude Pay public key. Ask Altitude Pay support for this key and the tenant ID when you set up webhooks. - If
subis anything else, reject the webhook.
Delivery and Retry Policy
- If your webhook endpoint responds with a
2xxHTTP status code, the delivery is considered successful. - If your endpoint returns a
4xx/5xxerror or times out, Altitude Pay retries the webhook with exponential backoff. - Retry attempts continue for up to 24 hours.
- After the retry window expires without success, the event is marked as undeliverable.
Ensure that your webhook endpoint:
- Is highly available.
- Quickly responds to POST requests (recommended within 2 seconds).
Best Practices
- Always verify the JWT signature and the SHA-512 digest before processing the event.
- Log webhook payloads and headers for audit and troubleshooting purposes.
- Implement idempotency to safely handle duplicate webhook deliveries.
- Respond with an HTTP 2xx status as quickly as possible.
- Secure your webhook endpoints with HTTPS.
JWT Signature Verification – Flow Description
When your server receives a webhook request from Altitude Pay, you must:
- Extract the
Authorizationheader (which contains the JWT). - Split authorization header on two parts (Bearer and token)
- Decode the JWT header and payload (without verifying yet).
- Retrieve the "data" claim from the JWT payload, which contains the SHA-512 digest of the request body.
- Hash the raw request body yourself using SHA-512, and encode the result as lowercase hex.
- Compare your calculated hash to the
SHA512value inside thedataclaim. - Verify the JWT's signature using the public key that matches its
subclaim (see Which key signs a webhook). subis your merchant ID: use your merchant public key.subis the Altitude Pay tenant ID: use the Altitude Pay public key.- If the digest matches and the signature is valid → accept the webhook.
If any of these steps fail → reject the webhook (return 401 Unauthorized).
Verify a webhook
Check the digest, then the signature, and answer 2xx only when both pass. Any other answer is retried for up to 24 hours.
sequenceDiagram
participant Gateway
participant Server as Your webhook endpoint
Gateway->>Server: Webhook event, JWT in Authorization
Server->>Server: Decode the JWT without verifying it
Server->>Server: SHA-512 the raw body, compare with data.SHA512
Server->>Server: Verify the signature with the key for sub
alt Both checks pass
Server-->>Gateway: 2xx
Server->>Server: Process the event
else Either check fails
Server-->>Gateway: 401 Unauthorized
end
Summary
- The digest comparison ensures payload integrity (body wasn't tampered).
- The JWT signature ensures origin authenticity (Altitude Pay sent it, not someone else).
- Both must pass.