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

# Webhooks

> Webhook configuration, inbound webhook payloads (Stripe, Resend), and outbound webhook event types.

PlaneConnection uses webhooks in two directions:

1. **Inbound webhooks** -- receive events from third-party services (Stripe, Resend)
2. **Outbound webhooks** -- send events to your own endpoints when things happen in the platform

## Inbound Webhooks

Inbound webhooks use signature verification instead of session tokens.

### Stripe Webhooks

**Endpoint:** `POST /api/webhooks/stripe`

Receives Stripe payment events. Signature is verified using the `stripe-signature` header and a shared signing secret.

**Events handled:**

| Event                           | Action                              |
| ------------------------------- | ----------------------------------- |
| `checkout.session.completed`    | Marks invoices as paid              |
| `payment_intent.succeeded`      | Updates payment status              |
| `customer.subscription.created` | Syncs subscription status           |
| `customer.subscription.updated` | Syncs subscription changes          |
| `customer.subscription.deleted` | Marks subscription as cancelled     |
| `invoice.paid`                  | Updates subscription billing status |
| `invoice.payment_failed`        | Flags failed billing                |

### Stripe Connect Webhooks

**Endpoint:** `POST /api/webhooks/stripe-connect`

Receives events for Stripe Connect (multi-party payments, FBO onboarding, trip payment splits).

### Resend Webhooks

**Endpoint:** `POST /api/webhooks/resend`

Receives email delivery events from [Resend](https://resend.com/) for deliverability monitoring and email analytics. Signature is verified using the webhook signing secret.

**Events handled:**

| Event                    | Description                                  |
| ------------------------ | -------------------------------------------- |
| `email.sent`             | Email accepted by Resend for delivery        |
| `email.delivered`        | Email successfully delivered to inbox        |
| `email.bounced`          | Email bounced (hard or soft)                 |
| `email.complained`       | Recipient marked email as spam               |
| `email.clicked`          | Recipient clicked a link in the email        |
| `email.opened`           | Recipient opened the email                   |
| `email.delivery_delayed` | Email delivery is delayed                    |
| `email.suppressed`       | Email suppressed (previous bounce/complaint) |

***

## Outbound Webhooks

You can configure outbound webhooks to receive notifications when events occur in your PlaneConnection workspace. Webhooks are managed via the API and require admin permissions.

### Managing Webhooks

**Base path:** `/api/v1/webhooks`

| Method   | Path                 | Description                    | Required Role |
| -------- | -------------------- | ------------------------------ | ------------- |
| `GET`    | `/webhooks`          | List webhooks                  | Admin/Manager |
| `GET`    | `/webhooks/:id`      | Get a webhook with recent logs | Admin/Manager |
| `POST`   | `/webhooks`          | Create a webhook               | Admin         |
| `PUT`    | `/webhooks/:id`      | Update a webhook               | Admin         |
| `DELETE` | `/webhooks/:id`      | Delete a webhook and its logs  | Admin         |
| `POST`   | `/webhooks/:id/test` | Send a test event              | Admin/Manager |

### Create Webhook

```bash theme={}
curl -X POST "https://api.planeconnection.com/api/v1/webhooks" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Flight notifications",
    "url": "https://your-app.example.com/webhooks/planeconnection",
    "secret": "whsec_your_signing_secret",
    "events": ["flight.scheduled", "flight.departed", "flight.arrived"],
    "active": true,
    "retry_count": 3,
    "timeout_ms": 10000
  }'
```

<Warning>
  Webhook URLs targeting private/internal networks (RFC 1918, loopback, link-local, metadata
  endpoints) are blocked to prevent SSRF attacks.
</Warning>

### Webhook Configuration

| Field         | Type      | Required | Description                                      |
| ------------- | --------- | :------: | ------------------------------------------------ |
| `name`        | string    |    Yes   | Human-readable name (max 100 chars)              |
| `url`         | string    |    Yes   | HTTPS endpoint to receive events                 |
| `secret`      | string    |    No    | Signing secret for HMAC-SHA256 verification      |
| `events`      | string\[] |    Yes   | Event types to subscribe to                      |
| `active`      | boolean   |    No    | Enable/disable (default: `true`)                 |
| `headers`     | object    |    No    | Custom headers to include in deliveries          |
| `retry_count` | integer   |    No    | Max retry attempts, 0-10 (default: `3`)          |
| `timeout_ms`  | integer   |    No    | Request timeout, 1000-30000ms (default: `10000`) |

### Signature Verification

When a `secret` is configured, each delivery includes an `X-Webhook-Signature` header containing an HMAC-SHA256 signature of the payload:

```
X-Webhook-Signature: sha256=a1b2c3d4e5f6...
```

Verify the signature in your handler:

```javascript theme={}
const crypto = require("crypto");

function verifyWebhook(payload, signature, secret) {
  const expected = crypto.createHmac("sha256", secret).update(payload).digest("hex");
  return `sha256=${expected}` === signature;
}
```

### Delivery Headers

Every webhook delivery includes these headers:

| Header                | Description                                  |
| --------------------- | -------------------------------------------- |
| `Content-Type`        | `application/json`                           |
| `X-Webhook-Event`     | Event type (e.g., `flight.departed`)         |
| `X-Webhook-Timestamp` | ISO 8601 delivery timestamp                  |
| `X-Webhook-ID`        | Webhook configuration ID                     |
| `X-Webhook-Signature` | HMAC-SHA256 signature (if secret configured) |

***

## Available Event Types

Query available event types at `GET /api/v1/webhooks/events`.

### Reservations

| Event                     | Description                 |
| ------------------------- | --------------------------- |
| `reservation.created`     | New reservation created     |
| `reservation.updated`     | Reservation details updated |
| `reservation.cancelled`   | Reservation cancelled       |
| `reservation.checked_in`  | Guest checked in            |
| `reservation.checked_out` | Guest checked out           |

### Billing

| Event             | Description              |
| ----------------- | ------------------------ |
| `invoice.created` | Invoice generated        |
| `invoice.paid`    | Invoice payment received |
| `invoice.overdue` | Invoice past due date    |

### Flights

| Event              | Description      |
| ------------------ | ---------------- |
| `flight.scheduled` | Flight scheduled |
| `flight.departed`  | Flight departed  |
| `flight.arrived`   | Flight arrived   |
| `flight.cancelled` | Flight cancelled |

### Maintenance

| Event                   | Description                   |
| ----------------------- | ----------------------------- |
| `maintenance.due`       | Maintenance item becoming due |
| `maintenance.completed` | Maintenance completed         |

### Customers

| Event              | Description                  |
| ------------------ | ---------------------------- |
| `customer.created` | New customer profile created |
| `customer.updated` | Customer profile updated     |

***

## Delivery Logs

View webhook delivery history and troubleshoot failures.

**Endpoint:** `GET /api/v1/webhooks/logs`

| Parameter    | Type    | Description                                      |
| ------------ | ------- | ------------------------------------------------ |
| `webhook_id` | string  | Filter by webhook ID                             |
| `event_type` | string  | Filter by event type                             |
| `status`     | string  | Filter by status: `pending`, `success`, `failed` |
| `date_from`  | string  | Start date filter                                |
| `date_to`    | string  | End date filter                                  |
| `limit`      | integer | Max results (default: 50, max: 100)              |
| `offset`     | integer | Pagination offset                                |

### Test a Webhook

Send a test event to verify your endpoint is receiving deliveries:

```bash theme={}
curl -X POST "https://api.planeconnection.com/api/v1/webhooks/wh_abc123/test" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "flight.scheduled",
    "payload": {
      "id": "flt_test",
      "departure": "KJFK",
      "arrival": "KLAX"
    }
  }'
```
