> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anyspend.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

Configure webhook endpoints for real-time event notifications

Webhooks let you receive real-time HTTP POST notifications when events happen in your AnySpend account. Configure endpoints, choose which events to subscribe to, and monitor delivery history.

All webhook management endpoints require **admin** permission unless noted. Read-only endpoints (list, get, deliveries) require **read** permission.

## Authentication

```bash
Authorization: Bearer asp_xxx
```

Base URL: `https://platform-api.anyspend.com/api/v1`

## Endpoints

### List Webhooks

Returns all webhook endpoints configured for your account.

**cURL**

```bash
    curl -X GET https://platform-api.anyspend.com/api/v1/webhooks \
      -H "Authorization: Bearer asp_xxx"
    ```
  **SDK**

```typescript
    import { AnySpendPlatformClient } from "@b3dotfun/sdk/anyspend/platform";

    const platform = new AnySpendPlatformClient(process.env.ANYSPEND_API_KEY!);
    const webhooks = await platform.webhooks.list();
    ```

**Response**

```json
{
  "success": true,
  "data": [
    {
      "id": "wh_abc123",
      "url": "https://myapp.com/webhooks/anyspend",
      "events": ["payment.completed", "payment.failed"],
      "is_active": true,
      "success_count": 142,
      "failure_count": 3,
      "last_triggered_at": "2026-02-27T10:30:00Z",
      "created_at": "2026-01-15T08:00:00Z",
      "updated_at": "2026-02-27T10:30:00Z"
    }
  ]
}
```

---

### Create Webhook

Create a new webhook endpoint. The response includes a `secret` field used to verify webhook signatures. Store this securely -- it is only returned once at creation time.

The HTTPS URL that will receive webhook POST requests.

Array of event types to subscribe to. See [Supported Events](#supported-events) below.

**cURL**

```bash
    curl -X POST https://platform-api.anyspend.com/api/v1/webhooks \
      -H "Authorization: Bearer asp_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "url": "https://myapp.com/webhooks/anyspend",
        "events": ["payment.completed", "payment.failed", "checkout.completed"]
      }'
    ```
  **SDK**

```typescript
    const webhook = await platform.webhooks.create({
      url: "https://myapp.com/webhooks/anyspend",
      events: ["payment.completed", "payment.failed", "checkout.completed"],
    });

    // Store webhook.secret securely -- only returned on create
    console.log("Signing secret:", webhook.secret);
    ```

**Response**

```json
{
  "success": true,
  "data": {
    "id": "wh_abc123",
    "url": "https://myapp.com/webhooks/anyspend",
    "events": ["payment.completed", "payment.failed", "checkout.completed"],
    "secret": "whsec_a1b2c3d4e5f6...",
    "is_active": true,
    "success_count": 0,
    "failure_count": 0,
    "last_triggered_at": null,
    "created_at": "2026-02-27T12:00:00Z",
    "updated_at": "2026-02-27T12:00:00Z"
  }
}
```

The `secret` field is only included in the create response. Copy it immediately and store it in your environment variables or secrets manager.

---

### Get Webhook

Retrieve a single webhook endpoint by ID.

**cURL**

```bash
    curl -X GET https://platform-api.anyspend.com/api/v1/webhooks/wh_abc123 \
      -H "Authorization: Bearer asp_xxx"
    ```
  **SDK**

```typescript
    const webhook = await platform.webhooks.get("wh_abc123");
    ```

---

### Update Webhook

Update an existing webhook endpoint. All fields are optional.

Updated HTTPS endpoint URL.

Updated list of subscribed event types. Replaces the existing list entirely.

Set to `false` to pause delivery without deleting the endpoint.

**cURL**

```bash
    curl -X PATCH https://platform-api.anyspend.com/api/v1/webhooks/wh_abc123 \
      -H "Authorization: Bearer asp_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "events": ["payment.completed", "checkout.completed"],
        "is_active": false
      }'
    ```
  **SDK**

```typescript
    const updated = await platform.webhooks.update("wh_abc123", {
      events: ["payment.completed", "checkout.completed"],
      is_active: false,
    });
    ```

---

### Delete Webhook

Permanently remove a webhook endpoint. Pending deliveries will be cancelled.

**cURL**

```bash
    curl -X DELETE https://platform-api.anyspend.com/api/v1/webhooks/wh_abc123 \
      -H "Authorization: Bearer asp_xxx"
    ```
  **SDK**

```typescript
    await platform.webhooks.delete("wh_abc123");
    ```

---

### Send Test Webhook

Sends a test event to the webhook URL so you can verify your endpoint is receiving and processing events correctly. The test payload uses a `test.ping` event type.

**cURL**

```bash
    curl -X POST https://platform-api.anyspend.com/api/v1/webhooks/wh_abc123/test \
      -H "Authorization: Bearer asp_xxx"
    ```
  **SDK**

```typescript
    const result = await platform.webhooks.test("wh_abc123");
    // result.delivery_id can be used to check the delivery status
    ```

**Response**

```json
{
  "success": true,
  "data": {
    "delivery_id": "del_xyz789",
    "status": "sent",
    "response_code": 200
  }
}
```

---

### List Delivery History

View the delivery log for a webhook endpoint. Returns recent delivery attempts with status codes and response times.

**cURL**

```bash
    curl -X GET https://platform-api.anyspend.com/api/v1/webhooks/wh_abc123/deliveries \
      -H "Authorization: Bearer asp_xxx"
    ```
  **SDK**

```typescript
    const deliveries = await platform.webhooks.deliveries("wh_abc123");
    ```

**Response**

```json
{
  "success": true,
  "data": [
    {
      "id": "del_xyz789",
      "event_type": "payment.completed",
      "status": "success",
      "response_code": 200,
      "response_time_ms": 245,
      "attempts": 1,
      "created_at": "2026-02-27T10:30:00Z"
    },
    {
      "id": "del_xyz790",
      "event_type": "payment.failed",
      "status": "failed",
      "response_code": 500,
      "response_time_ms": 3012,
      "attempts": 3,
      "created_at": "2026-02-27T09:15:00Z"
    }
  ]
}
```

---

### Retry a Failed Delivery

Manually retry a failed webhook delivery. The delivery must have a `failed` status.

**cURL**

```bash
    curl -X POST https://platform-api.anyspend.com/api/v1/webhooks/wh_abc123/deliveries/del_xyz790/retry \
      -H "Authorization: Bearer asp_xxx"
    ```
  **SDK**

```typescript
    const result = await platform.webhooks.retry("wh_abc123", "del_xyz790");
    ```

**Response**

```json
{
  "success": true,
  "data": {
    "delivery_id": "del_xyz790",
    "status": "sent",
    "response_code": 200,
    "attempts": 4
  }
}
```

---

## Webhook Object

| Field | Type | Description |
|-------|------|-------------|
| `id` | `string` | Unique webhook identifier (e.g., `wh_abc123`) |
| `url` | `string` | HTTPS endpoint URL |
| `events` | `string[]` | Subscribed event types |
| `secret` | `string` | Signing secret (only returned on create) |
| `is_active` | `boolean` | Whether the webhook is currently active |
| `success_count` | `number` | Total successful deliveries |
| `failure_count` | `number` | Total failed deliveries |
| `last_triggered_at` | `string \| null` | ISO 8601 timestamp of last delivery attempt |
| `created_at` | `string` | ISO 8601 creation timestamp |
| `updated_at` | `string` | ISO 8601 last update timestamp |

## Supported Events

| Event Type | Description |
|------------|-------------|
| `payment.completed` | A payment was successfully processed |
| `payment.failed` | A payment attempt failed |
| `checkout.completed` | A checkout session was completed (includes form data, shipping, discount info) |

## Verifying Webhook Signatures

Each webhook request includes a signature in the `X-AnySpend-Signature` header. Verify it using your webhook secret to ensure the request is authentic.

```typescript
import crypto from "crypto";

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(payload)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler
app.post("/webhooks/anyspend", (req, res) => {
  const signature = req.headers["x-anyspend-signature"];
  const isValid = verifyWebhookSignature(
    JSON.stringify(req.body),
    signature,
    process.env.ANYSPEND_WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  // Process the event
  const { type, data } = req.body;
  switch (type) {
    case "payment.completed":
      // Handle successful payment
      break;
    case "payment.failed":
      // Handle failed payment
      break;
  }

  res.status(200).json({ received: true });
});
```

Always return a `2xx` status code within 30 seconds. Failed deliveries are retried up to 3 times with exponential backoff.