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

# Webhook Endpoints API — manage event subscriptions

> Create, update, list, and delete webhook endpoints to receive real-time event notifications. View delivery history and retry failed deliveries.

Webhook endpoints receive HTTP POST notifications from Borga when events occur in your account — for example, when a payment succeeds or a subscription is canceled. Register an endpoint with a list of event types to subscribe to, and Borga will deliver a signed payload to your URL each time a matching event occurs.

<Note>
  Every delivery is signed using your endpoint's `secret`. Verify the `Borga-Signature` header on each incoming request by computing an HMAC-SHA256 of the raw request body using the signing secret. Reject any request that does not match.
</Note>

**Supported events**

| Event                   | Description                           |
| ----------------------- | ------------------------------------- |
| `payment.succeeded`     | A payment was collected successfully. |
| `payment.failed`        | A payment attempt failed.             |
| `invoice.paid`          | An invoice was paid in full.          |
| `subscription.created`  | A new subscription was created.       |
| `subscription.canceled` | A subscription was canceled.          |

***

## Create a webhook endpoint

`POST /v1/webhook_endpoints`

Registers a new webhook endpoint.

### Request parameters

<ParamField body="url" type="string" required>
  The HTTPS URL to which Borga will send event payloads.
</ParamField>

<ParamField body="events" type="string[]" required>
  Array of event type strings to subscribe to (e.g. `["payment.succeeded", "invoice.paid"]`). Pass `["*"]` to subscribe to all events.
</ParamField>

<ParamField body="enabled" type="boolean">
  Whether the endpoint should receive deliveries. Defaults to `true`.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.borga.is/v1/webhook_endpoints \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx" \
    --header "Content-Type: application/json" \
    --data '{
      "url": "https://your-server.example.com/webhooks/borga",
      "events": [
        "payment.succeeded",
        "payment.failed",
        "invoice.paid",
        "subscription.created",
        "subscription.canceled"
      ]
    }'
  ```
</RequestExample>

### Response fields

<ResponseField name="id" type="string" required>
  Unique endpoint identifier.
</ResponseField>

<ResponseField name="url" type="string" required>
  The registered HTTPS URL.
</ResponseField>

<ResponseField name="events" type="string[]" required>
  Array of subscribed event types.
</ResponseField>

<ResponseField name="enabled" type="boolean" required>
  Whether the endpoint is currently active.
</ResponseField>

<ResponseField name="secret" type="string" required>
  Signing secret for verifying delivery payloads. This value is only returned at creation — store it securely.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of when the endpoint was created.
</ResponseField>

<ResponseExample>
  ```json 201 theme={null}
  {
    "id": "we_01hx9z3k2mfq7nbvd4cw8ej5rt",
    "url": "https://your-server.example.com/webhooks/borga",
    "events": [
      "payment.succeeded",
      "payment.failed",
      "invoice.paid",
      "subscription.created",
      "subscription.canceled"
    ],
    "enabled": true,
    "secret": "whsec_...",
    "created_at": "2026-04-29T10:15:00Z"
  }
  ```
</ResponseExample>

***

## List webhook endpoints

`GET /v1/webhook_endpoints`

Returns a list of all registered webhook endpoints.

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.borga.is/v1/webhook_endpoints \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx"
  ```
</RequestExample>

### Response fields

<ResponseField name="data" type="object[]" required>
  Array of webhook endpoint objects.

  <Expandable title="endpoint fields">
    <ResponseField name="id" type="string" required>
      Unique endpoint identifier.
    </ResponseField>

    <ResponseField name="url" type="string" required>
      The registered HTTPS URL.
    </ResponseField>

    <ResponseField name="events" type="string[]" required>
      Subscribed event types.
    </ResponseField>

    <ResponseField name="enabled" type="boolean" required>
      Whether the endpoint is active.
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      ISO 8601 creation timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": [
      {
        "id": "we_01hx9z3k2mfq7nbvd4cw8ej5rt",
        "url": "https://your-server.example.com/webhooks/borga",
        "events": ["payment.succeeded", "invoice.paid"],
        "enabled": true,
        "created_at": "2026-04-29T10:15:00Z"
      }
    ]
  }
  ```
</ResponseExample>

***

## Retrieve a webhook endpoint

`GET /v1/webhook_endpoints/{id}`

Retrieves an existing webhook endpoint. The `secret` is not returned after initial creation.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the endpoint to retrieve.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.borga.is/v1/webhook_endpoints/we_01hx9z3k2mfq7nbvd4cw8ej5rt \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx"
  ```
</RequestExample>

### Response fields

<ResponseField name="id" type="string" required>
  Unique endpoint identifier.
</ResponseField>

<ResponseField name="url" type="string" required>
  The registered HTTPS URL.
</ResponseField>

<ResponseField name="events" type="string[]" required>
  Array of subscribed event types.
</ResponseField>

<ResponseField name="enabled" type="boolean" required>
  Whether the endpoint is active.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of when the endpoint was created.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "we_01hx9z3k2mfq7nbvd4cw8ej5rt",
    "url": "https://your-server.example.com/webhooks/borga",
    "events": ["payment.succeeded", "invoice.paid"],
    "enabled": true,
    "created_at": "2026-04-29T10:15:00Z"
  }
  ```
</ResponseExample>

***

## Update a webhook endpoint

`PATCH /v1/webhook_endpoints/{id}`

Updates an existing webhook endpoint. Only the fields you provide are changed.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the endpoint to update.
</ParamField>

### Request parameters

<ParamField body="url" type="string">
  Updated HTTPS URL.
</ParamField>

<ParamField body="events" type="string[]">
  Updated array of event types. Replaces the existing list entirely.
</ParamField>

<ParamField body="enabled" type="boolean">
  Set to `false` to pause deliveries to this endpoint.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url https://api.borga.is/v1/webhook_endpoints/we_01hx9z3k2mfq7nbvd4cw8ej5rt \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx" \
    --header "Content-Type: application/json" \
    --data '{
      "enabled": false
    }'
  ```
</RequestExample>

### Response fields

Returns the updated endpoint object. See [retrieve a webhook endpoint](#retrieve-a-webhook-endpoint) for the full field reference.

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "we_01hx9z3k2mfq7nbvd4cw8ej5rt",
    "url": "https://your-server.example.com/webhooks/borga",
    "events": ["payment.succeeded", "invoice.paid"],
    "enabled": false,
    "created_at": "2026-04-29T10:15:00Z"
  }
  ```
</ResponseExample>

***

## Delete a webhook endpoint

`DELETE /v1/webhook_endpoints/{id}`

Permanently deletes a webhook endpoint. Borga will stop delivering events to this URL immediately.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the endpoint to delete.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request DELETE \
    --url https://api.borga.is/v1/webhook_endpoints/we_01hx9z3k2mfq7nbvd4cw8ej5rt \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx"
  ```
</RequestExample>

### Response fields

Returns an empty body with a `204 No Content` status on success.

<ResponseExample>
  ```json 204 theme={null}
  {}
  ```
</ResponseExample>

***

## List webhook deliveries

`GET /v1/webhook_deliveries`

Returns a paginated list of delivery attempts for a webhook endpoint, ordered by creation date descending. Use this to audit which events were received and identify failures.

### Query parameters

<ParamField query="endpoint" type="string">
  Filter by endpoint ID.
</ParamField>

<ParamField query="limit" type="number">
  Maximum number of deliveries to return per page.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url "https://api.borga.is/v1/webhook_deliveries?endpoint=we_01hx9z3k2mfq7nbvd4cw8ej5rt&limit=20" \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx"
  ```
</RequestExample>

### Response fields

<ResponseField name="data" type="object[]" required>
  Array of delivery objects.

  <Expandable title="delivery fields">
    <ResponseField name="id" type="string" required>
      Unique delivery identifier.
    </ResponseField>

    <ResponseField name="endpoint" type="string" required>
      ID of the webhook endpoint this delivery was sent to.
    </ResponseField>

    <ResponseField name="event_type" type="string" required>
      The event type that triggered the delivery.
    </ResponseField>

    <ResponseField name="status" type="string" required>
      Delivery status. One of `delivered` or `failed`.
    </ResponseField>

    <ResponseField name="response_code" type="number">
      HTTP status code returned by your endpoint.
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      ISO 8601 timestamp of the delivery attempt.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="has_more" type="boolean" required>
  Whether more deliveries exist beyond this page.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": [
      {
        "id": "wd_01hx9z3k2mfq7nbvd4cw8ej5rt",
        "endpoint": "we_01hx9z3k2mfq7nbvd4cw8ej5rt",
        "event_type": "payment.succeeded",
        "status": "delivered",
        "response_code": 200,
        "created_at": "2026-04-29T10:15:05Z"
      }
    ],
    "has_more": false
  }
  ```
</ResponseExample>

***

## Retry a webhook delivery

`POST /v1/webhook_deliveries/{id}/retry`

Retries a previously failed delivery. Borga re-sends the original event payload to the registered endpoint URL.

### Path parameters

<ParamField path="id" type="string" required>
  The ID of the delivery to retry.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.borga.is/v1/webhook_deliveries/wd_01hx9z3k2mfq7nbvd4cw8ej5rt/retry \
    --header "Authorization: Bearer sk_live_..." \
    --header "X-Merchant-Id: mer_xxx"
  ```
</RequestExample>

### Response fields

Returns the new delivery attempt object.

<ResponseField name="id" type="string" required>
  Unique identifier for this retry delivery attempt.
</ResponseField>

<ResponseField name="endpoint" type="string" required>
  ID of the webhook endpoint.
</ResponseField>

<ResponseField name="event_type" type="string" required>
  The event type that was retried.
</ResponseField>

<ResponseField name="status" type="string" required>
  Delivery status of the retry attempt.
</ResponseField>

<ResponseField name="response_code" type="number">
  HTTP status code returned by your endpoint.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of the retry attempt.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "wd_01hx9z3k2mfq7nbvd4cw8ej5rt2",
    "endpoint": "we_01hx9z3k2mfq7nbvd4cw8ej5rt",
    "event_type": "payment.succeeded",
    "status": "delivered",
    "response_code": 200,
    "created_at": "2026-04-29T11:00:00Z"
  }
  ```
</ResponseExample>
