# Webhooks

Receive real-time HTTP push notifications for payment events. Configure in the Peach Payments Dashboard or via API for reliable payment status tracking and automated workflows.

## Use cases

- Order fulfilment automation
- Payment status synchronization
- Dispute management
- Refund processing
- Mandate lifecycle tracking

## Steps

### 1. Create your webhook endpoint

Create an HTTPS endpoint on your server that:

• Accepts POST requests with Content-Type: application/json
• Returns a 2XX status code within 5 seconds to acknowledge receipt
• Processes the webhook payload asynchronously (don't block the response)

Example endpoint structure:
POST https://your-domain.com/webhooks/peach-orchestration

The endpoint will receive a JSON body containing:
- "event_id:" Unique identifier for deduplication
- "event_type:" for example, "payment_succeeded", "refund_created"
- "content:" The full payment/refund object
- "timestamp:" When the event occurred

Configure a webhook in the Peach Payments Dashboard:
Add a webhook as follows:
1. Log in to the Peach Payments Dashboard at https://dashboard.peachpayments.com.
2. In the left navigation menu, click **Peach Orchestration**.
3. In the **Webhooks** section, click **+ Add webhook URL**.
4. In the **Adding webhook URL** window, enter your webhook URL. **Ensure that your system responds with a 200 status response and that you have enabled HTTPS in your live environment**, then click **Add webhook URL**.
The webhook URL appears in the list.

Delete a webhook as follows:
1. Log in to the Peach Payments Dashboard at https://dashboard.peachpayments.com.
2. In the left navigation menu, click **Peach Orchestration**.
3. In the **Webhooks** section, click the more options icon next to the webhook that you want to delete, then click **Delete**.
4. In the confirmation window, click **Delete**.
Peach Payments removes the webhook.

### 2. Configure webhook via API — `POST /account/{account_id}/business_profile/{profile_id}`

Update your Business Profile to register your webhook endpoint. The webhook_details object specifies:

• webhook_url: Your HTTPS endpoint URL
• payment_statuses_enabled: Which payment events to receive
• refund_statuses_enabled: Which refund events to receive
• webhook_username/password: Optional basic auth credentials

The API will return a payment_response_hash_key - save this securely for signature verification.

Request body:

```json
{
  "webhook_details": {
    "webhook_url": "https://your-domain.com/webhooks/peach-orchestration",
    "webhook_username": null,
    "webhook_password": null,
    "payment_created_enabled": true,
    "payment_succeeded_enabled": true,
    "payment_failed_enabled": true,
    "payment_statuses_enabled": [
      "succeeded",
      "failed",
      "partially_captured",
      "requires_merchant_action"
    ],
    "refund_statuses_enabled": [
      "succeeded",
      "failed"
    ]
  },
  "outgoing_webhook_custom_http_headers": {
    "X-Custom-Header": "your-value"
  }
}
```

### 3. Implement signature verification

Every webhook includes an x-webhook-signature-512 header. Verify it to ensure authenticity:

1. Get the raw request body (as bytes, before parsing)
2. Compute HMAC-SHA512 using your payment_response_hash_key
3. Compare with the x-webhook-signature-512 header value

Node.js example:
const crypto = require('crypto');
const signature = crypto
  .createHmac('sha512', payment_response_hash_key)
  .update(rawBody)
  .digest('hex');
const isValid = signature === req.headers['x-webhook-signature-512'];

Reject webhooks with invalid signatures (return 401).

### 4. Handle webhook events

Process webhook events based on event_type. Common events include:

Payment Events:
• payment_succeeded - Payment completed successfully
• payment_failed - Payment attempt failed
• payment_processing - Payment is being processed
• payment_cancelled - Payment was cancelled

Refund Events:
• refund_succeeded - Refund completed
• refund_failed - Refund attempt failed

Dispute Events:
• dispute_opened - Customer disputed a charge
• dispute_won/lost - Dispute outcome

Best Practice: Return 200 OK immediately, then process asynchronously via a job queue.

### 5. Handle retries and duplicates

Orchestration retries failed webhook deliveries for up to 24 hours:

Retry Schedule: 1min → 5min → 10min → 1hr → 6hr → 24hr

To handle this reliably:

1. Deduplicate: Store processed event_ids and skip duplicates
2. Idempotency: Make your handlers safe to run multiple times
3. Ordering: Use timestamp to handle out-of-order events
4. Logging: Log all webhook receipts for debugging

Example deduplication:
if (await redis.exists('webhook:' + event_id)) {
  return res.status(200).send('Already processed');
}
await redis.setex('webhook:' + event_id, 86400, '1');
// Process webhook...

## Key parameters

- Configure via API or Dashboard
- webhook_details on Business Profile
- HMAC-SHA512 signature verification
- 18+ event types supported
- 24-hour retry with escalating intervals

## Flow diagram

```mermaid
flowchart LR
    subgraph Setup
    A[Create Endpoint] --> B[Configure Profile API]
    B --> C[Save Hash Key]
    end

    subgraph Runtime
    D[Payment Event] --> E[Orchestration]
    E --> F[POST to Your Endpoint]
    F --> G{Verify Signature}
    G -->|Valid| H[Process Event]
    G -->|Invalid| I[Reject 401]
    H --> J[Return 2XX]
    end

    subgraph Retry
    K[Failed Delivery] --> L[Retry: 1m, 5m, 10m...]
    end
```

## Payment state transitions

```mermaid
stateDiagram-v2
    [*] --> pending: Event Created
    pending --> retrying: Non-2XX/Timeout
    retrying --> failed: 24hr Exhausted
    retrying --> retrying: Continue Retrying
    pending --> delivered: 2XX Response
    retrying --> delivered: Retry Success
    failed --> [*]
    delivered --> [*]

    note left of retrying
        Retries: 1m, 5m, 10m, 1hr, 6hr
    end note
```

---

Interactive version: https://playground.peachpayments.com/flows/webhooks
