Webhooks & Events

Copperx uses webhooks to send real-time notifications to your server whenever important events occur in your account. This enables you to automate backend actions.

โœ… What is a Webhook?

A webhook is a POST request sent from Copperx to your serverโ€™s endpoint whenever a specific event occurs. It carries a JSON payload describing the event and its associated data.

  • Why Use Webhooks? Instead of continuously calling the API to check for payment status updates, Copperx sends real-time events to your backend. This reduces overhead and ensures your app stays in sync.

  • Typical Flow:

    1. User completes a payment (e.g., Checkout Session).

    2. Copperx sends a webhook event (checkout_session.completed) to your endpoint.

    3. Your backend verifies the webhook and updates the userโ€™s plan or access.


๐Ÿ” Webhook Security & Signature Verification

For security, Copperx signs every webhook payload using an HMAC-SHA256 signature.

  • Headers in the Webhook Request:

    Header
    Description

    x-webhook-signature

    HMAC-SHA256 signature of the raw payload

    x-webhook-token

    Your webhook secret key (from dashboard)

  • How to Verify the Signature:

    1. Retrieve the x-webhook-signature header from the request.

    2. Compute your own HMAC-SHA256 hash of the raw request body using your webhook secret key.

    3. Compare your hash with the x-webhook-signature. If they match, the webhook is valid.

You can find your webhook secret key in the Copperx dashboard settings.


๐Ÿ”— Common Webhook Events

Below are the most commonly used events in Copperxโ€™s payment flows:

Event
Description

checkout_session.completed

User successfully completed the checkout.

checkout_session.expired

Checkout session expired before payment completion.

checkout_session.canceled

User canceled the checkout session.

invoice.paid

An invoice was paid successfully.

invoice.finalized

An invoice was finalized (ready to be paid).

invoice.payment_failed

Payment for an invoice failed.

customer.subscription.created

A new subscription was created.

customer.subscription.started

Subscription started.

customer.subscription.deleted

Subscription was canceled/deleted.

customer.subscription.past_due

Subscription payment is past due.

customer.subscription.unpaid

Subscription payment is unpaid.

payment_intent.succeeded

PaymentIntent was successfully completed.

payment_intent.failed

PaymentIntent failed.


๐Ÿ“จ Example Webhook Payload: Checkout Session Completed

When a checkout session is completed, hereโ€™s an example of the JSON payload you will receive:

{
  "id": "00b6d1b6-93ce-4d6d-86b4-a7ab8fe14d87",
  "apiVersion": "2023-01-11",
  "created": 1748329965626,
  "object": "checkoutSession",
  "type": "checkout_session.completed",
  "data": {
    "object": {
      "id": "fe6b7b01-1c4b-4b35-a5a5-a23b0a089cc6",
      "createdAt": "2025-05-27T07:12:19.165Z",
      "updatedAt": "2025-05-27T07:12:45.582Z",
      "mode": "payment",
      "paymentMethodTypes": ["wallet"],
      "paymentSetting": {
        "allowedChains": [
          { "chainId": 137 },
          { "chainId": 8453 },
          { "chainId": 42161 }
        ],
        "paymentMethodTypes": ["wallet"],
        "preferredChainId": 137,
        "allowSwap": true
      },
      "currency": "usdc",
      "amountSubtotal": "10000000",
      "amountTotal": "10100000",
      "status": "complete",
      "paymentStatus": "paid",
      "paymentLinkId": "769a890b-5664-49f8-8f68-c9b688bcf60f",
      "url": "https://buy.copperx.tech/payment/checkout-session/fe6b7b01-1c4b-4b35-a5a5-a23b0a089cc6",
      "lineItems": {
        "object": "list",
        "data": [
          {
            "description": null,
            "quantity": 1,
            "price": {
              "id": "ebc48921-0171-4f37-9070-2906d0da2f51",
              "currency": "usdc",
              "productId": "b1d2476f-b5cf-47d7-99ee-3d8123ae9ab5",
              "type": "one_time",
              "unitAmount": "10000000",
              "product": {
                "id": "b1d2476f-b5cf-47d7-99ee-3d8123ae9ab5",
                "name": "Demo test",
                "isActive": true
              },
              "isActive": true
            },
            "amountTotal": "10000000",
            "currency": "usdc"
          }
        ]
      },
      "addresses": [/* ... multiple supported crypto assets and addresses ... */],
      "paymentIntent": {
        "id": "3b7bc615-a04d-49e1-98c4-8612f785484d",
        "amount": "10100000",
        "amountReceived": "10100000",
        "currency": "usdc",
        "status": "requires_payment_method",
        "paymentMethod": {
          "id": "88cbd77a-84f1-422a-8ac6-fa6f498142b1",
          "asset": {
            "id": "13056880-798b-4bd4-a555-c1c71de017fa",
            "name": "USDC.e",
            "chainId": 137,
            "address": "0x2791bca1f2de4661ed88a30c99a7a9449aa84174",
            "currency": "usdc"
          },
          "type": "wallet",
          "accountAddress": "0xd2b59f3a9575a90a44e5627cda4ed98ecb5e5d20",
          "options": {
            "frontend": {
              "transactionHash": "0x54d164f9807060445614ece882603fd4b2a7858ac1394451cf1f07715a183def"
            },
            "wallet": {
              "assetId": "13056880-798b-4bd4-a555-c1c71de017fa",
              "transactionHash": "0x54d164f9807060445614ece882603fd4b2a7858ac1394451cf1f07715a183def",
              "contractAddress": "0x146db67792092eaa92a51961946b50f89277a975"
            }
          }
        }
      },
      "amountDetails": {
        "amountTotal": "10100000",
        "amountSubtotal": "10000000",
        "amountFee": "100000",
        "currency": "usdc",
        "feePercentage": 1
      },
      "amountNet": "10000000"
    }
  }
}

๐Ÿ’ก How to Use This Event

When you receive this event: โœ… Verify the signature (for security). โœ… Check the paymentStatus (paid). โœ… Activate the userโ€™s plan, send a confirmation email, or update their account.

โš™๏ธ Best Practices for Webhooks

โœ… Always verify the signature to avoid spoofed requests. โœ… Respond quickly to webhook POST requests with a 200 OK to acknowledge receipt. โœ… Retry Behavior

  • Max Attempts: 10

  • Initial Delay: 30 seconds

  • Backoff Strategy: Exponential (delay doubles with each retry)

  • No Delay Cap: Delay continues to double up to the 10th attempt

  • Total Retry Window: ~4 hours 16 minutes from initial delivery attempt


๐Ÿ“Š Retry Schedule

Attempt
Delay (seconds)
Delay (minutes)
Cumulative Time

1st

30

0.5 min

0:00:30

2nd

60

1 min

0:01:30

3rd

120

2 min

0:03:30

4th

240

4 min

0:07:30

5th

480

8 min

0:15:30

6th

960

16 min

0:31:30

7th

1920

32 min

1:03:30

8th

3840

64 min

2:07:30

9th

7680

128 min

4:15:30

10th

15,360

256 min

8:31:30*

Notes:

  • A maximum of 10 retry attempts will be made.

  • If all retries fail, the webhook delivery is marked as unsuccessful.

โœ… Log webhook events for debugging and auditing. โœ… Use HTTPS for secure communication.

Last updated