Skip to main content

Overview

All webhook payloads from Modulus Labs are encrypted using JWE (JSON Web Encryption) to protect sensitive transaction data. This page provides a complete reference for the payload structure, encryption details, and all available fields.
Always decrypt and verify webhook payloads. Never trust webhook data without proper JWE decryption and validation. Unencrypted data could be forged or tampered with.

Webhook Request Structure

When Modulus Labs sends a webhook to your endpoint, the request looks like this:

HTTP Request

Request Body

The data field contains a JWE-encrypted string that you must decrypt to access the actual transaction details.

JWE Encryption Specification

Webhook payloads use JSON Web Encryption with the following algorithms:

Content Encryption

Algorithm: A256CBC-HS512AES-256-CBC with HMAC SHA-512 for authenticated encryption

Key Encryption

Algorithm: A256KWAES-256 Key Wrap for secure key encryption

Serialization Format

Format: Compact SerializationStandard JWE compact format (five base64url segments separated by dots)

Secret Key

Your Secret: Modulus Labs Secret KeySame key used for QR API authentication

JWE Structure

You don’t need to manually parse these segments. JWE libraries handle the decryption process automatically.

Decrypting the Payload

Use your secret key to decrypt the JWE payload.

Required Libraries

Decryption Implementation

Decrypted Payload Structure

After decryption, the webhook payload is a JSON object with the following structure:

Complete Field Reference

string
required
The webhook action that triggered this notification.Possible values:
  • QRPH_SUCCESS - Payment completed successfully
  • QRPH_DECLINED - Payment failed or was declined
Example: "QRPH_SUCCESS"
string
required
Unique reference number for this transaction. This matches the referenceNumber you provided when creating the Dynamic QR Ph code.Use this field to:
  • Match webhook to original QR creation request
  • Prevent duplicate processing (idempotency)
  • Look up order in your database
Format: Alphanumeric string, typically 1-50 charactersExample: "REF-20240115-ABC123"
integer
required
Transaction amount in the smallest currency unit.
  • For PHP: Amount in centavos (100 = ₱1.00)
  • For USD: Amount in cents (100 = $1.00)
Example: 100000 represents ₱1,000.00
string
required
Three-letter ISO 4217 currency code.Possible values: "PHP", "USD"Example: "PHP"
string
required
ISO 8601 timestamp indicating when the transaction was processed by the payment network.Format: YYYY-MM-DDTHH:mm:ssZExample: "2024-01-15T14:30:00Z"
string
required
Current transaction status.Possible values:
  • SUCCESS - Payment completed successfully
  • FAILED - Payment failed
  • PENDING - Payment processing (rare for webhooks)
  • REQUIRES_ACTION - Additional action needed (rare for webhooks)
Example: "SUCCESS"
string
required
Your merchant identifier assigned by Modulus Labs.Example: "MERCH12345"
string
Name of the customer who made the payment, as provided by their bank.Availability: May be null if the bank doesn’t provide this information.Example: "Juan Dela Cruz"
string
Name of the bank or payment provider the customer used to complete the payment.Availability: May be null if not provided by the payment network.Example: "BDO Unibank", "GCash", "Maya"
string
Bank’s internal reference number for this transaction.Availability: Present only for successful payments, may be null for declined payments.Use case: Reconciliation with bank statements, dispute resolutionExample: "BANK-REF-987654321"
string
Reason the payment was declined (only present when action is QRPH_DECLINED).Possible values:
  • "Insufficient funds"
  • "Invalid account"
  • "Transaction limit exceeded"
  • "Card expired"
  • "Declined by bank"
  • "Unknown error"
Example: "Insufficient funds"
object
Custom key-value pairs you included when creating the Dynamic QR Ph code. This is returned exactly as you sent it.Use case: Store order ID, customer ID, or other identifiers to link webhook to your systemExample:

Payload Examples

Successful Payment

Declined Payment

E-wallet Payment (GCash)

Field Validation

Validate the decrypted payload before processing:

Common Validation Patterns

Check that the referenceNumber matches a QR code you actually created:
Verify the payment amount matches what you expected:
Detect replayed or delayed webhooks:
Ensure action and status fields are consistent:

Security Considerations

Always Decrypt

Never trust the encrypted payload without decryption. An attacker could send fake webhook requests.

Verify Signature

JWE provides authenticated encryption - the decryption process validates data integrity.

Use HTTPS

Your webhook endpoint must use HTTPS to prevent man-in-the-middle attacks.

Rate Limiting

Implement rate limiting on your webhook endpoint to prevent abuse.

Log Everything

Log all webhook receipts, decryption attempts, and processing results.

Handle Errors Gracefully

Don’t expose sensitive information in error messages.

Troubleshooting Decryption Issues

Possible causes:
  • Wrong secret key
  • Secret key for different environment (sandbox vs production)
  • Secret key has extra whitespace or newline characters
Solutions:
Possible causes:
  • Decryption succeeded but JSON parsing failed
  • Empty payload
  • Incorrect plaintext handling
Solutions:
Possible causes:
  • JWE library doesn’t support A256CBC-HS512 or A256KW
  • Outdated library version
Solutions:
Possible causes:
  • Middleware modifying request body
  • Character encoding issues
  • Request body not properly buffered
Solutions:

Testing with Sample Payloads

Use the Simulate API to generate test webhooks with real encrypted payloads:
This sends a real encrypted webhook to your registered endpoint, allowing you to test decryption end-to-end.

Simulate API Reference

Complete documentation for testing webhooks

Best Practices

Load your secret key once at startup, not on every webhook:
Always validate payload structure before business logic:
Save the encrypted payload for audit and debugging:
Some fields like customerName or bankName may be null:

Next Steps

Receiving Webhooks

Complete guide to handling webhook requests

Setup Guide

Register webhook endpoints

Overview

Webhooks overview and requirements

Simulate API

Test your decryption implementation