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 handling: Copperx will automatically retry delivery if your server responds with a non-2xx status, following this schedule:

  • 1st retry after 1 second

  • 2nd retry after 2 seconds

  • 3rd retry after 4 seconds

✅ Log webhook events for debugging and auditing. ✅ Use HTTPS for secure communication.

Last updated