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

# Handle VivaWallet Webhook Events with Full Type Safety

> Manage VivaWallet webhook subscriptions, retrieve verification keys, create ISV webhooks, and route incoming events to the SDK's webhook helper functions.

VivaWallet sends webhook events to your HTTPS endpoint when asynchronous payment, reporting, POS, marketplace, or connected-account events occur. The SDK separates webhook support into two surfaces:

* **Webhook API modules** — `vivawallet.webhooks`, `marketplace.webhooks`, and `vivaIsv.webhook` manage webhook subscriptions and verification keys.
* **Receiver helper functions** — package-root helpers build verification responses, verify Data Services signatures, extract identity/idempotency keys, and soft-validate event payloads.

<Card title="Webhook Helpers" icon="shield-check" href="/guides/webhook-helpers">
  Use the detailed helper guide when implementing your webhook receiver. It documents every exported helper and when to use it.
</Card>

<Note>
  A receiver should acknowledge Viva quickly. For slow work, return `200 OK` after basic checks and process the event asynchronously.
</Note>

## Manage Merchant and Marketplace Subscriptions

Use `vivawallet.webhooks` for standard merchant webhook subscriptions. The `Marketplace` client exposes the same `webhooks` module for platform credentials.

```typescript theme={null}
const result = await vivawallet.webhooks.addSubscription({
  url: 'https://yourdomain.com/webhooks/vivawallet',
  secret: process.env.VIVA_WEBHOOK_SECRET!,
  events: ['SaleTransactionsFileGenerated'],
});

if (result.success && result.data) {
  console.log('Subscription ID:', result.data.subscriptionId);
}
```

List existing subscriptions:

```typescript theme={null}
const subs = await vivawallet.webhooks.listSubscriptions();

if (subs.success && subs.data) {
  const subscriptions = Array.isArray(subs.data) ? subs.data : [subs.data];

  for (const sub of subscriptions) {
    console.log(sub.subscriptionId, sub.url, sub.events);
  }
}
```

Update or delete a subscription by ID:

```typescript theme={null}
await vivawallet.webhooks.updateSubscription('subscription-id', {
  url: 'https://yourdomain.com/webhooks/vivawallet',
  secret: process.env.VIVA_WEBHOOK_SECRET!,
  events: ['SaleTransactionsFileGenerated'],
});

await vivawallet.webhooks.deleteSubscription('subscription-id');
```

## Retrieve a Webhook Verification Key

Merchant and marketplace webhook verification uses a key returned by `retrieveWebhookKey()`.

```typescript theme={null}
const keyResult = await vivawallet.webhooks.retrieveWebhookKey();

if (!keyResult.success || !keyResult.data) {
  throw new Error(keyResult.message);
}

const key = keyResult.data;
```

For Marketplace integrations, call the same module on the platform client:

```typescript theme={null}
const keyResult = await marketplace.webhooks.retrieveWebhookKey();
```

Use the key with `buildVivaMerchantWebhookVerificationBody()` or `buildVivaMerchantWebhookVerificationResponse()` when Viva verifies your endpoint. See [Webhook Helpers](/guides/webhook-helpers#url-verification-helpers) for receiver examples.

## Create ISV Webhooks

`VivaISV` exposes `webhook.create(options)` for ISV webhook setup. The alias `webhooks` points to the same module.

```typescript theme={null}
const result = await vivaIsv.webhook.create({
  url: 'https://yourdomain.com/webhooks/viva-isv',
  eventTypeId: 1796,
});
```

Retrieve the ISV verification key separately:

```typescript theme={null}
const keyResult = await vivaIsv.webhook.retrieveWebhookKey();

if (keyResult.success && keyResult.data) {
  console.log(keyResult.data.key);
}
```

Use `buildVivaIsvWebhookVerificationBody()` or `buildVivaIsvWebhookVerificationResponse()` for ISV endpoint verification.

## Type Incoming Payloads

For lightweight payload typing, use `VivaWebhookDatas<T>` with a known event-data type.

```typescript theme={null}
import type {
  VivaWebhookDatas,
  SmartCheckoutWebhookEventDatas,
} from '@nkhind/vivawallet-sdk';

app.post('/webhooks/vivawallet', (req, res) => {
  const event: VivaWebhookDatas<SmartCheckoutWebhookEventDatas> = req.body;

  console.log(event.EventTypeId);
  console.log(event.EventData.TransactionId);

  res.sendStatus(200);
});
```

For new integrations, prefer the tolerant webhook types and helper functions documented in [Webhook Helpers](/guides/webhook-helpers). They cover more Viva event families than the older `SmartCheckoutWebhookEventDatas` and `ConnectedAccountWebhookEventDatas` aliases.

## Receiver Checklist

1. Answer Viva's endpoint verification challenge with the right helper: merchant/marketplace responses use `Key`, ISV responses use `key`.
2. For signed Data Services webhooks, verify `Viva-Signature-256` or `Viva-Signature` against the raw body before trusting the payload.
3. Extract identity and an idempotency key before processing so retries do not duplicate side effects.
4. Run the event-specific soft validator for the webhook family you are handling.
5. Persist the event or enqueue background work, then return `200 OK` quickly when the delivery is accepted.

## Official Webhook References

* [Webhook event index](https://developer.viva.com/webhooks-for-payments/)
* [Setting up webhooks](https://developer.viva.com/webhooks-for-payments/setting-up-webhooks/)
* [Sale Transactions signed webhook](https://developer.viva.com/webhooks-for-payments/sale-transactions/)
* [Transaction Payment Created](https://developer.viva.com/webhooks-for-payments/transaction-payment-created/)
* [Order Updated](https://developer.viva.com/webhooks-for-payments/order-updated/)
