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

# Webhooks

> Register, manage, and test webhook endpoints to receive real-time event notifications for your entities.

Webhooks let you subscribe to Nuvion events and receive HTTP POST notifications when those events occur. Each webhook is scoped to the authenticated entity and can subscribe to specific event types or all events. See [Webhooks overview](/webhooks/overview) for the delivery model, retries, and signature verification.

***

## The Webhook object

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

<ResponseField name="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ResponseField>

<ResponseField name="url" type="string">
  The HTTPS endpoint Nuvion delivers events to. Must use the `https` protocol.
</ResponseField>

<ResponseField name="expires_in" type="number">
  Duration in seconds until the webhook expires. After expiry, no further events are delivered and the webhook status becomes `inactive`.
</ResponseField>

<ResponseField name="enabled_events" type="object">
  The set of events this webhook is subscribed to.

  <Expandable title="enabled_events fields">
    <ResponseField name="all" type="boolean">
      When `true`, subscribes to every event type. Overrides all other selections in this object.
    </ResponseField>

    <ResponseField name="entities" type="object">
      Entity lifecycle events.

      <Expandable title="entities fields">
        <ResponseField name="created" type="boolean">Fires when a new entity is created.</ResponseField>
        <ResponseField name="updated" type="boolean">Fires when an entity is updated, for example when its status changes.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="accounts" type="object">
      Account lifecycle events.

      <Expandable title="accounts fields">
        <ResponseField name="created" type="boolean">Fires when a new account is created.</ResponseField>
        <ResponseField name="updated" type="boolean">Fires when an account is updated.</ResponseField>
        <ResponseField name="deleted" type="boolean">Fires when an account is deleted.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="account_details" type="object">
      Account details lifecycle events (bank account numbers, wallet addresses).

      <Expandable title="account_details fields">
        <ResponseField name="created" type="boolean">Fires when account details are created.</ResponseField>
        <ResponseField name="updated" type="boolean">Fires when account details are updated.</ResponseField>
        <ResponseField name="deleted" type="boolean">Fires when account details are deleted.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="inflows" type="object">
      Incoming payment events.

      <Expandable title="inflows fields">
        <ResponseField name="completed" type="boolean">Fires when an inflow settles successfully.</ResponseField>
        <ResponseField name="failed" type="boolean">Fires when an inflow fails.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="outflows" type="object">
      Outgoing payment events.

      <Expandable title="outflows fields">
        <ResponseField name="created" type="boolean">Fires when an outflow is initiated.</ResponseField>
        <ResponseField name="completed" type="boolean">Fires when an outflow settles successfully.</ResponseField>
        <ResponseField name="failed" type="boolean">Fires when an outflow fails.</ResponseField>
        <ResponseField name="cancelled" type="boolean">Fires when an outflow is cancelled.</ResponseField>
        <ResponseField name="refunded" type="boolean">Fires when an outflow is refunded.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="funding_sessions" type="object">
      Funding session events.

      <Expandable title="funding_sessions fields">
        <ResponseField name="updated" type="boolean">Fires when a funding session is updated.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="payment_intent" type="object">
      Payment intent events.

      <Expandable title="payment_intent fields">
        <ResponseField name="completed" type="boolean">Fires when a payment intent is completed.</ResponseField>
        <ResponseField name="failed" type="boolean">Fires when a payment intent fails.</ResponseField>
        <ResponseField name="cancelled" type="boolean">Fires when a payment intent is cancelled.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="payment_dispute" type="object">
      Payment dispute events.

      <Expandable title="payment_dispute fields">
        <ResponseField name="created" type="boolean">Fires when a payment dispute is opened.</ResponseField>
        <ResponseField name="completed" type="boolean">Fires when a payment dispute is resolved.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="payment_refund" type="object">
      Payment refund events.

      <Expandable title="payment_refund fields">
        <ResponseField name="completed" type="boolean">Fires when a payment refund settles successfully.</ResponseField>
        <ResponseField name="failed" type="boolean">Fires when a payment refund fails.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="cards" type="object">
      Card lifecycle events.

      <Expandable title="cards fields">
        <ResponseField name="created" type="boolean">Fires when a new card is issued.</ResponseField>
        <ResponseField name="frozen" type="boolean">Fires when a card is frozen.</ResponseField>
        <ResponseField name="unfrozen" type="boolean">Fires when a card is unfrozen.</ResponseField>
        <ResponseField name="deleted" type="boolean">Fires when a card is deleted.</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="preferred_events" type="string[]">
  Read-only. A flattened summary of the enabled events, using `group.all` where every event in a group is enabled. e.g. `["accounts.all", "outflows.all"]`.
</ResponseField>

<ResponseField name="secret" type="string">
  System-generated signing secret. Nuvion derives an HMAC from this value to sign each delivery. Returned once, at creation or when rotated via `rotate_secret`: store it securely before leaving the page. It is never returned on subsequent requests. See [Verifying signatures](/webhooks/overview#verifying-webhook-signatures) for how to validate incoming requests.
</ResponseField>

<ResponseField name="description" type="string">
  Optional short description to identify the webhook in the dashboard.
</ResponseField>

<ResponseField name="tags" type="string[]">
  Optional list of tags for organizing webhooks.
</ResponseField>

<ResponseField name="status" type="string">
  Webhook status. One of `active` or `inactive`. Defaults to `active` at creation.
</ResponseField>

<ResponseField name="created" type="number">
  Unix timestamp in milliseconds when the webhook was created.
</ResponseField>

<ResponseField name="updated" type="number">
  Unix timestamp in milliseconds when the webhook was last updated.
</ResponseField>

<ResponseField name="deleted" type="number">
  `0` if the webhook is active. Non-zero if the webhook has been deleted.
</ResponseField>

<ResponseField name="stats" type="object">
  Read-only delivery statistics for this webhook.

  <Expandable title="stats fields">
    <ResponseField name="total_webhooks_sent" type="number">
      Total number of delivery attempts made for this webhook.
    </ResponseField>

    <ResponseField name="total_webhooks_successful" type="number">
      Number of deliveries that received a `2xx` response.
    </ResponseField>

    <ResponseField name="total_webhooks_failed" type="number">
      Number of deliveries that did not receive a `2xx` response after all retries.
    </ResponseField>

    <ResponseField name="last_webhook_event" type="number">
      Unix timestamp in milliseconds of the most recent delivery attempt.
    </ResponseField>
  </Expandable>
</ResponseField>

```json Example theme={null}
{
  "status": "success",
  "message": "Webhook fetched successfully",
  "data": {
    "id": "01HXYZ9001ABCDEFGHJKMNPQRS",
    "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
    "url": "https://webhooks.example.com/nuvion",
    "expires_in": 31536000,
    "enabled_events": {
      "all": false,
      "entities": {
        "created": false,
        "updated": false
      },
      "accounts": {
        "created": true,
        "updated": true,
        "deleted": true
      },
      "account_details": {
        "created": true,
        "updated": true,
        "deleted": true
      },
      "inflows": {
        "completed": true,
        "failed": true
      },
      "outflows": {
        "created": true,
        "completed": true,
        "failed": true,
        "cancelled": false,
        "refunded": false
      },
      "funding_sessions": {
        "updated": true
      },
      "payment_intent": {
        "completed": true,
        "failed": true,
        "cancelled": false
      },
      "payment_dispute": {
        "created": true,
        "completed": true
      },
      "payment_refund": {
        "completed": true,
        "failed": true
      },
      "cards": {
        "created": true,
        "frozen": true,
        "unfrozen": true,
        "deleted": true
      }
    },
    "preferred_events": [
      "accounts.all",
      "account_details.all",
      "inflows.all",
      "funding_sessions.all",
      "payment_dispute.all",
      "payment_refund.all",
      "cards.all"
    ],
    "description": "Production payment notifications",
    "tags": ["payments", "production"],
    "status": "active",
    "created": 1744056000000,
    "updated": 1744056000000,
    "deleted": 0,
    "stats": {
      "total_webhooks_sent": 1482,
      "total_webhooks_successful": 1479,
      "total_webhooks_failed": 3,
      "last_webhook_event": 1744056000000
    }
  }
}
```

***

## Create a webhook

`POST /entity-webhooks`

Registers a new webhook endpoint for the authenticated entity.

<CodeGroup>
  ```bash Minimum fields theme={null}
  curl -X POST https://api.nuvion.dev/entity-webhooks \
    -H "Authorization: Bearer $NUVION_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://nuvion-web.vercel.app/put",
      "description": "Payout tracking webhook",
      "expires_in": 2592000,
      "enabled_events": {
          "account_details": {
              "created": true,
              "deleted": true,
              "updated": true
          },
          "outflows": {
              "failed": true,
              "cancelled": true,
              "refunded": true,
              "created": true,
              "completed": true
          }
      },
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS"
    }'
  ```

  ```bash All events theme={null}
  curl -X POST https://api.nuvion.dev/entity-webhooks \
    -H "Authorization: Bearer $NUVION_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://webhooks.example.com/nuvion",
      "expires_in": 31536000,
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
      "enabled_events": {
        "all": true
      },
      "description": "Production payment notifications",
      "tags": ["payments", "production"]
    }'
  ```
</CodeGroup>

### Request parameters

<ParamField body="url" type="string" required>
  The HTTPS endpoint Nuvion posts events to. Must begin with `https://`. Invalid URLs or non-HTTPS URLs are rejected.
</ParamField>

<ParamField body="expires_in" type="number" required>
  Duration in seconds until the webhook expires. After expiry, deliveries stop and the webhook status becomes `inactive`.
</ParamField>

<ParamField body="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ParamField>

<ParamField body="enabled_events" type="object" required>
  The events to subscribe to. Set `all` to subscribe to every event, or enable specific events within one or more groups. See [enabled\_events fields](#the-webhook-object) for the full group structure.

  <ParamField body="all" type="boolean">
    When `true`, subscribes to every event type. Overrides all other selections in this object.
  </ParamField>

  <Expandable title="entities">
    The entity events to subscribe to.

    <ParamField body="created" type="boolean">
      Fires when a new entity is created.
    </ParamField>

    <ParamField body="updated" type="boolean">
      Fires when an entity is updated, for example when its status changes.
    </ParamField>
  </Expandable>

  <Expandable title="accounts">
    The account events to subscribe to.

    <ParamField body="created" type="boolean">
      Fires when a new account is created.
    </ParamField>

    <ParamField body="updated" type="boolean">
      Fires when an account is updated.
    </ParamField>

    <ParamField body="deleted" type="boolean">
      Fires when an account is deleted.
    </ParamField>
  </Expandable>

  <Expandable title="account_details">
    The account details events to subscribe to.

    <ParamField body="created" type="boolean">
      Fires when account details are created.
    </ParamField>

    <ParamField body="updated" type="boolean">
      Fires when account details are updated.
    </ParamField>

    <ParamField body="deleted" type="boolean">
      Fires when account details are deleted.
    </ParamField>
  </Expandable>

  <Expandable title="inflows">
    The inflow events to subscribe to.

    <ParamField body="completed" type="boolean">
      Fires when an inflow settles successfully.
    </ParamField>

    <ParamField body="failed" type="boolean">
      Fires when an inflow fails.
    </ParamField>
  </Expandable>

  <Expandable title="outflows">
    The outflow events to subscribe to.

    <ParamField body="created" type="boolean">
      Fires when an outflow is initiated.
    </ParamField>

    <ParamField body="completed" type="boolean">
      Fires when an outflow settles successfully.
    </ParamField>

    <ParamField body="failed" type="boolean">
      Fires when an outflow fails.
    </ParamField>

    <ParamField body="cancelled" type="boolean">
      Fires when an outflow is cancelled.
    </ParamField>

    <ParamField body="refunded" type="boolean">
      Fires when an outflow is refunded.
    </ParamField>
  </Expandable>

  <Expandable title="funding_sessions">
    The funding session events to subscribe to.

    <ParamField body="updated" type="boolean">
      Fires when a funding session is updated.
    </ParamField>
  </Expandable>

  <Expandable title="payment_intent">
    The payment intent events to subscribe to.

    <ParamField body="completed" type="boolean">
      Fires when a payment intent is completed.
    </ParamField>

    <ParamField body="failed" type="boolean">
      Fires when a payment intent fails.
    </ParamField>

    <ParamField body="cancelled" type="boolean">
      Fires when a payment intent is cancelled.
    </ParamField>
  </Expandable>

  <Expandable title="payment_dispute">
    The payment dispute events to subscribe to.

    <ParamField body="created" type="boolean">
      Fires when a payment dispute is opened.
    </ParamField>

    <ParamField body="completed" type="boolean">
      Fires when a payment dispute is resolved.
    </ParamField>
  </Expandable>

  <Expandable title="payment_refund">
    The payment refund events to subscribe to.

    <ParamField body="completed" type="boolean">
      Fires when a payment refund settles successfully.
    </ParamField>

    <ParamField body="failed" type="boolean">
      Fires when a payment refund fails.
    </ParamField>
  </Expandable>

  <Expandable title="cards">
    The card events to subscribe to.

    <ParamField body="created" type="boolean">
      Fires when a new card is issued.
    </ParamField>

    <ParamField body="frozen" type="boolean">
      Fires when a card is frozen.
    </ParamField>

    <ParamField body="unfrozen" type="boolean">
      Fires when a card is unfrozen.
    </ParamField>

    <ParamField body="deleted" type="boolean">
      Fires when a card is deleted.
    </ParamField>
  </Expandable>
</ParamField>

### Response

Returns `201 Created` with the new webhook object.

<CodeGroup>
  ```json Minimum fields theme={null}
  {
    "status": "success",
    "message": "Webhook created successfully",
    "data": {
      "id": "01HXYZ9006ABCDEFGHJKMNPQRS",
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
      "url": "https://nuvion-web.vercel.app/put",
      "expires_in": 2592000,
      "enabled_events": {
        "all": false,
        "entities": {
          "created": false,
          "updated": false
        },
        "accounts": {
          "created": false,
          "updated": false,
          "deleted": false
        },
        "account_details": {
          "created": true,
          "updated": true,
          "deleted": true
        },
        "inflows": {
          "completed": false,
          "failed": false
        },
        "outflows": {
          "created": true,
          "completed": true,
          "failed": true,
          "cancelled": true,
          "refunded": true
        },
        "funding_sessions": {
          "updated": false
        },
        "payment_intent": {
          "completed": false,
          "failed": false,
          "cancelled": false
        },
        "payment_dispute": {
          "created": false,
          "completed": false
        },
        "payment_refund": {
          "completed": false,
          "failed": false
        },
        "cards": {
          "created": false,
          "frozen": false,
          "unfrozen": false,
          "deleted": false
        }
      },
      "preferred_events": [
        "account_details.all",
        "outflows.all"
      ],
      "secret": "7f3a91c4e8b2d5f60a1c7e9b3d8f2a4c6e0b5d9f1a3c7e2b4d6f8a0c2e4b6d81",
      "description": "Payout tracking webhook",
      "tags": [],
      "status": "active",
      "created": 1787286828480,
      "updated": 1787286828480,
      "deleted": 0,
      "stats": {
        "total_webhooks_sent": 0,
        "total_webhooks_successful": 0,
        "total_webhooks_failed": 0,
        "last_webhook_event": 0
      }
    }
  }
  ```

  ```json All events theme={null}
  {
    "status": "success",
    "message": "Webhook created successfully",
    "data": {
      "id": "01HXYZ9007ABCDEFGHJKMNPQRS",
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
      "url": "https://webhooks.example.com/nuvion",
      "expires_in": 31536000,
      "enabled_events": {
        "all": true,
        "entities": {
          "created": false,
          "updated": false
        },
        "accounts": {
          "created": false,
          "updated": false,
          "deleted": false
        },
        "account_details": {
          "created": false,
          "updated": false,
          "deleted": false
        },
        "inflows": {
          "completed": false,
          "failed": false
        },
        "outflows": {
          "created": false,
          "completed": false,
          "failed": false,
          "cancelled": false,
          "refunded": false
        },
        "funding_sessions": {
          "updated": false
        },
        "payment_intent": {
          "completed": false,
          "failed": false,
          "cancelled": false
        },
        "payment_dispute": {
          "created": false,
          "completed": false
        },
        "payment_refund": {
          "completed": false,
          "failed": false
        },
        "cards": {
          "created": false,
          "frozen": false,
          "unfrozen": false,
          "deleted": false
        }
      },
      "preferred_events": [
        "all"
      ],
      "secret": "7f3a91c4e8b2d5f60a1c7e9b3d8f2a4c6e0b5d9f1a3c7e2b4d6f8a0c2e4b6d81",
      "description": "Production payment notifications",
      "tags": ["payments", "production"],
      "status": "active",
      "created": 1787286900000,
      "updated": 1787286900000,
      "deleted": 0,
      "stats": {
        "total_webhooks_sent": 0,
        "total_webhooks_successful": 0,
        "total_webhooks_failed": 0,
        "last_webhook_event": 0
      }
    }
  }
  ```
</CodeGroup>

<Warning>
  Copy and store the `secret` immediately after creating the webhook.
</Warning>

***

## Update a webhook

`PATCH /entity-webhooks/:id`

Updates an existing webhook. Only the fields you include are changed; omitted fields retain their current values.

<CodeGroup>
  ```bash Rotate secret theme={null}
  curl -X PATCH https://api.nuvion.dev/entity-webhooks/:id \
    -H "Authorization: Bearer $NUVION_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://nuvion-web.vercel.app/put-request",
      "rotate_secret": true
    }'
  ```

  ```bash Keep secret theme={null}
  curl -X PATCH https://api.nuvion.dev/entity-webhooks/:id \
    -H "Authorization: Bearer $NUVION_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://nuvion-web.vercel.app/patchh"
    }'
  ```
</CodeGroup>

### Path parameters

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

### Request parameters

<ParamField body="url" type="string">
  New HTTPS delivery URL. Must begin with `https://`.
</ParamField>

<ParamField body="rotate_secret" type="boolean">
  Whether to rotate the webhook's signing secret. Defaults to `false`.
</ParamField>

<ParamField body="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ParamField>

<Note>
  Set `rotate_secret` to `true` if you're rotating your secret key. The new value is returned once in the response, the same as at creation; it isn't returned on later requests.
</Note>

### Response

Returns `200 OK` with the updated webhook object.

<CodeGroup>
  ```json Rotate secret theme={null}
  {
    "status": "success",
    "message": "Webhook updated successfully",
    "data": {
      "id": "01HXYZ9005ABCDEFGHJKMNPQRS",
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
      "url": "https://nuvion-web.vercel.app/put-request",
      "expires_in": 2592000,
      "enabled_events": {
        "all": false,
        "entities": {
          "created": false,
          "updated": false
        },
        "accounts": {
          "created": false,
          "updated": false,
          "deleted": false
        },
        "account_details": {
          "created": true,
          "updated": true,
          "deleted": true
        },
        "inflows": {
          "completed": false,
          "failed": false
        },
        "outflows": {
          "created": true,
          "completed": true,
          "failed": true,
          "cancelled": true,
          "refunded": true
        },
        "funding_sessions": {
          "updated": false
        },
        "payment_intent": {
          "completed": false,
          "failed": false,
          "cancelled": false
        },
        "payment_dispute": {
          "created": false,
          "completed": false
        },
        "payment_refund": {
          "completed": false,
          "failed": false
        },
        "cards": {
          "created": false,
          "frozen": false,
          "unfrozen": false,
          "deleted": false
        }
      },
      "preferred_events": [
        "account_details.all",
        "outflows.all"
      ],
      "secret": "7f3a91c4e8b2d5f60a1c7e9b3d8f2a4c6e0b5d9f1a3c7e2b4d6f8a0c2e4b6d81",
      "description": "Payout tracking webhook",
      "tags": [],
      "status": "active",
      "created": 1781872625218,
      "updated": 1781872792881,
      "deleted": 0,
      "stats": {
        "total_webhooks_sent": 0,
        "total_webhooks_successful": 0,
        "total_webhooks_failed": 0,
        "last_webhook_event": 0
      }
    }
  }
  ```

  ```json Keep secret theme={null}
  {
    "status": "success",
    "message": "Webhook updated successfully",
    "data": {
      "id": "01HXYZ9004ABCDEFGHJKMNPQRS",
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
      "url": "https://nuvion-web.vercel.app/patchh",
      "expires_in": 2592000,
      "enabled_events": {
        "all": true,
        "entities": {
          "created": false,
          "updated": false
        },
        "accounts": {
          "created": false,
          "updated": false,
          "deleted": false
        },
        "account_details": {
          "created": false,
          "updated": false,
          "deleted": false
        },
        "inflows": {
          "completed": false,
          "failed": false
        },
        "outflows": {
          "created": false,
          "completed": false,
          "failed": false,
          "cancelled": false,
          "refunded": false
        },
        "funding_sessions": {
          "updated": false
        },
        "payment_intent": {
          "completed": false,
          "failed": false,
          "cancelled": false
        },
        "payment_dispute": {
          "created": false,
          "completed": false
        },
        "payment_refund": {
          "completed": false,
          "failed": false
        },
        "cards": {
          "created": false,
          "frozen": false,
          "unfrozen": false,
          "deleted": false
        }
      },
      "preferred_events": [
        "all"
      ],
      "description": "General event notifications",
      "tags": [],
      "status": "active",
      "created": 1781871959611,
      "updated": 1781872978628,
      "deleted": 0,
      "stats": {
        "total_webhooks_sent": 0,
        "total_webhooks_successful": 0,
        "total_webhooks_failed": 0,
        "last_webhook_event": 0
      }
    }
  }
  ```
</CodeGroup>

***

## Get a webhook

`GET /entity-webhooks/:webhookId`

Retrieves a single webhook by ID.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.nuvion.dev/entity-webhooks/01HXYZ9001ABCDEFGHJKMNPQRS?entity_id=01HXYZ1234ABCDEFGHJKMNPQRS" \
    -H "Authorization: Bearer $NUVION_API_KEY"
  ```
</CodeGroup>

### Path parameters

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

### Query parameters

<ParamField query="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ParamField>

### Response

Returns `200 OK` with the webhook object.

```json Response theme={null}
{
  "status": "success",
  "message": "Webhook fetched successfully",
  "data": {
    "id": "01HXYZ9001ABCDEFGHJKMNPQRS",
    "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
    "url": "https://webhooks.example.com/nuvion",
    "expires_in": 31536000,
    "enabled_events": {
      "all": false,
      "entities": {
        "created": false,
        "updated": false
      },
      "accounts": {
        "created": true,
        "updated": true,
        "deleted": true
      },
      "account_details": {
        "created": true,
        "updated": true,
        "deleted": true
      },
      "inflows": {
        "completed": true,
        "failed": true
      },
      "outflows": {
        "created": true,
        "completed": true,
        "failed": true,
        "cancelled": false,
        "refunded": false
      },
      "funding_sessions": {
        "updated": true
      },
      "payment_intent": {
        "completed": true,
        "failed": true,
        "cancelled": false
      },
      "payment_dispute": {
        "created": true,
        "completed": true
      },
      "payment_refund": {
        "completed": true,
        "failed": true
      },
      "cards": {
        "created": true,
        "frozen": true,
        "unfrozen": true,
        "deleted": true
      }
    },
    "preferred_events": [
      "accounts.all",
      "account_details.all",
      "inflows.all",
      "funding_sessions.all",
      "payment_dispute.all",
      "payment_refund.all",
      "cards.all"
    ],
    "description": "Production payment notifications",
    "tags": ["payments", "production"],
    "status": "active",
    "created": 1744056000000,
    "updated": 1744056000000,
    "deleted": 0,
    "stats": {
      "total_webhooks_sent": 1482,
      "total_webhooks_successful": 1479,
      "total_webhooks_failed": 3,
      "last_webhook_event": 1744056000000
    }
  }
}
```

***

## List webhooks

`GET /entity-webhooks`

Returns a paginated list of all webhooks for the authenticated entity.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.nuvion.dev/entity-webhooks?limit=20&entity_id=01HXYZ1234ABCDEFGHJKMNPQRS" \
    -H "Authorization: Bearer $NUVION_API_KEY"
  ```
</CodeGroup>

### Query parameters

<ParamField query="limit" type="integer">
  Number of results per page. Between `1` and `100`. Defaults to `20`.
</ParamField>

<ParamField query="cursor" type="string">
  ULID pagination cursor from a previous response. Omit for the first page.
</ParamField>

<ParamField query="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ParamField>

### Response

Returns `200 OK` with a paginated list of webhook objects.

```json Response theme={null}
{
  "status": "success",
  "message": "Webhooks fetched successfully",
  "data": {
    "data": [
      {
        "id": "01HXYZ9009ABCDEFGHJKMNPQRS",
        "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
        "url": "https://webhooks.example.com/nuvion",
        "expires_in": 3155695200000,
        "enabled_events": {
          "all": true,
          "entities": {
            "created": false,
            "updated": false
          },
          "accounts": {
            "created": false,
            "updated": false,
            "deleted": false
          },
          "account_details": {
            "created": false,
            "updated": false,
            "deleted": false
          },
          "inflows": {
            "completed": false,
            "failed": false
          },
          "outflows": {
            "created": false,
            "completed": false,
            "failed": false,
            "cancelled": false,
            "refunded": false
          },
          "funding_sessions": {
            "updated": false
          },
          "payment_intent": {
            "completed": false,
            "failed": false,
            "cancelled": false
          },
          "payment_dispute": {
            "created": false,
            "completed": false
          },
          "payment_refund": {
            "completed": false,
            "failed": false
          },
          "cards": {
            "created": false,
            "frozen": false,
            "unfrozen": false,
            "deleted": false
          }
        },
        "preferred_events": [
          "all"
        ],
        "tags": [],
        "status": "active",
        "created": 1787673119614,
        "updated": 1787673119614,
        "deleted": 0,
        "stats": {
          "total_webhooks_sent": 29,
          "total_webhooks_successful": 29,
          "total_webhooks_failed": 0,
          "last_webhook_event": 1787855480062
        }
      }
    ],
    "meta": {
      "pagination": {
        "order": "desc",
        "has_next": false,
        "limit": 20,
        "has_previous": false,
        "next_cursor": null,
        "previous_cursor": null
      },
      "filters_applied": {
        "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
        "sort": {
          "field": "_id",
          "order": "desc"
        }
      }
    }
  }
}
```

***

## Delete a webhook

`DELETE /entity-webhooks/:webhookId`

Permanently deletes a webhook. Nuvion stops delivering events to the endpoint immediately.

<CodeGroup>
  ```bash curl theme={null}
  curl -X DELETE https://api.nuvion.dev/entity-webhooks/01HXYZ9001ABCDEFGHJKMNPQRS \
    -H "Authorization: Bearer $NUVION_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS"
    }'
  ```
</CodeGroup>

### Path parameters

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

### Request parameters

<ParamField body="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ParamField>

### Response

Returns `200 OK` confirming deletion.

```json Response theme={null}
{
  "status": "success",
  "message": "Webhook deleted successfully",
  "data": {
    "id": "01HXYZ9001ABCDEFGHJKMNPQRS"
  }
}
```

<Warning>
  Deletion is irreversible. All delivery history is retained in logs, but the webhook configuration and endpoint registration are permanently removed.
</Warning>

***

## The Webhook Log object

Each delivery attempt is recorded as a log entry. Logs are immutable and retained regardless of delivery outcome.

<ResponseField name="id" type="string">
  Unique log entry identifier.
</ResponseField>

<ResponseField name="entity_id" type="string">
  The ID of the entity this log belongs to.
</ResponseField>

<ResponseField name="event_id" type="string">
  The ID of the event that triggered this delivery.
</ResponseField>

<ResponseField name="entity_webhook_id" type="string">
  The ID of the webhook that triggered this delivery.
</ResponseField>

<ResponseField name="url" type="string">
  The URL this delivery was sent to at the time of the attempt.
</ResponseField>

<ResponseField name="request" type="object">
  The request Nuvion sent to the webhook endpoint.

  <Expandable title="request fields">
    <ResponseField name="headers" type="object">
      Headers sent with the delivery, including `Content-Type`, `X-Nuvion-Event-Id`, `X-Nuvion-Event-Signature`, and `X-Nuvion-Event-Timestamp`. See [Verifying signatures](/webhooks/overview#verifying-webhook-signatures) for how to validate `X-Nuvion-Event-Signature`.
    </ResponseField>

    <ResponseField name="body" type="object">
      The payload delivered to the endpoint. For live events, matches the `event` and `data` shape of the triggering event; see [Event types](/webhooks/event-types) for the full payload schema per event. For deliveries triggered by [Send a test event](#send-a-test-event), this is `{event_group, event_name}` instead.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="response" type="object">
  The response received from the webhook endpoint.

  <Expandable title="response fields">
    <ResponseField name="data" type="string">
      Raw response body returned by the endpoint.
    </ResponseField>

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

<ResponseField name="duration" type="object">
  Timestamps for the delivery lifecycle.

  <Expandable title="duration fields">
    <ResponseField name="request_sent" type="number">
      Unix timestamp in milliseconds when Nuvion sent the delivery.
    </ResponseField>

    <ResponseField name="response_received" type="number">
      Unix timestamp in milliseconds when the endpoint responded.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="created" type="number">
  Unix timestamp in milliseconds when the log entry was created.
</ResponseField>

<ResponseField name="updated" type="number">
  Unix timestamp in milliseconds when the log entry was last updated.
</ResponseField>

<ResponseField name="deleted" type="number">
  `0` for all log entries. Logs are immutable and never deleted.
</ResponseField>

***

## List webhook logs

`GET /webhook-logs`

Returns a paginated list of delivery log entries for the authenticated entity.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.nuvion.dev/webhook-logs?limit=20&entity_id=01HXYZ1234ABCDEFGHJKMNPQRS" \
    -H "Authorization: Bearer $NUVION_API_KEY"
  ```
</CodeGroup>

### Query parameters

<ParamField query="limit" type="integer">
  Number of results per page. Between `1` and `100`. Defaults to `20`.
</ParamField>

<ParamField query="cursor" type="string">
  ULID pagination cursor from a previous response. Omit for the first page.
</ParamField>

<ParamField query="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ParamField>

### Response

Returns `200 OK` with a paginated list of log objects.

```json Response theme={null}
{
  "status": "success",
  "message": "Webhook logs fetched successfully",
  "data": {
    "data": [
      {
        "id": "01HXYZ9002ABCDEFGHJKMNPQRS",
        "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
        "event_id": "01HXYZ9008ABCDEFGHJKMNPQRS",
        "entity_webhook_id": "01HXYZ9001ABCDEFGHJKMNPQRS",
        "url": "https://webhooks.example.com/nuvion",
        "request": {
          "headers": {
            "Content-Type": "application/json",
            "X-Nuvion-Event-Id": "01HXYZ9008ABCDEFGHJKMNPQRS",
            "X-Nuvion-Event-Signature": "a8492a0d21bd5fd16bef2454bf305029ea205e5e331341b25a8231fff75edc43",
            "X-Nuvion-Event-Timestamp": "2026-08-27T18:31:19.719Z"
          },
          "body": {
            "event": "inflows.completed",
            "data": {
              "id": "01HXYZ9003ABCDEFGHJKMNPQRS"
            }
          }
        },
        "response": {
          "data": "OK",
          "status": 200
        },
        "duration": {
          "request_sent": 1744056000000,
          "response_received": 1744056000312
        },
        "created": 1744056000312,
        "updated": 1744056000312,
        "deleted": 0
      }
    ],
    "meta": {
      "pagination": {
        "order": "desc",
        "has_next": false,
        "limit": 20,
        "has_previous": false,
        "next_cursor": null,
        "previous_cursor": null
      },
      "filters_applied": {
        "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS",
        "sort": {
          "field": "_id",
          "order": "desc"
        }
      }
    }
  }
}
```

<Note>
  `X-Nuvion-Event-Signature` and the other delivery headers are recorded as sent. See [Verifying signatures](/webhooks/overview#verifying-webhook-signatures) for how to validate them.
</Note>

***

## Send a test event

`POST /webhook-tests`

Sends a test delivery to an existing webhook endpoint, so you can verify it's reachable and correctly signs and receives deliveries without waiting for a real event.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.nuvion.dev/webhook-tests \
    -H "Authorization: Bearer $NUVION_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "entity_webhook_id": "01HXYZ9001ABCDEFGHJKMNPQRS",
      "event_group": "inflows",
      "event_name": "completed",
      "entity_id": "01HXYZ1234ABCDEFGHJKMNPQRS"
    }'
  ```
</CodeGroup>

### Request parameters

<ParamField body="entity_webhook_id" type="string" required>
  The ID of the webhook to send the test event to.
</ParamField>

<ParamField body="event_group" type="string" required>
  The event group to simulate. One of `entities`, `accounts`, `account_details`, `inflows`, `outflows`, `funding_sessions`, `payment_intent`, `payment_dispute`, `payment_refund`, or `cards`.
</ParamField>

<ParamField body="event_name" type="string" required>
  The specific event to simulate within the group. One of `created`, `updated`, `deleted`, `completed`, `failed`, `cancelled`, `refunded`, `frozen`, or `unfrozen`.

  Not all combinations of `event_group` and `event_name` are valid. For example, `funding_sessions.created` does not exist. Refer to the [enabled\_events structure](#the-webhook-object) for supported combinations.
</ParamField>

<ParamField body="entity_id" type="string">
  The ID of the entity this webhook belongs to. Defaults to the authenticating entity when omitted. Required when acting on a child entity. See [Managing child entities](/core-concepts/entities#managing-child-entities) for details.
</ParamField>

### Response

Returns `201 Created` confirming the test was dispatched.

```json Response theme={null}
{
  "status": "success",
  "message": "Test Webhook sent successfully",
  "data": {}
}
```

<Note>
  The test delivery's body only contains `event_group` and `event_name`, not the full `event`/`data` shape a real event payload has:

  ```json theme={null}
  {
    "event_group": "inflows",
    "event_name": "completed"
  }
  ```

  Use this endpoint to confirm your webhook is reachable and that your signature verification works, not to test your handler's parsing logic against realistic event data. See [Event types](/webhooks/event-types) for real payload shapes.
</Note>

<Tip>
  Test events appear in [webhook logs](#list-webhook-logs) the same as live events. Check the logs to inspect the full request and response if your endpoint didn't receive the payload as expected.
</Tip>

***

## What's next

<CardGroup cols={2}>
  <Card title="Webhooks overview" icon="webhook" href="/webhooks/overview">
    Delivery model, retries, idempotency, and signature verification.
  </Card>

  <Card title="Event types" icon="list" href="/webhooks/event-types">
    Full payload schemas and examples for every event.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.