Support

Help and documentation

API & webhooks

Setting up the PayPal webhook

Overview

A webhook is PayPal's way of reporting back to Kyvento: whenever something happens in PayPal that Kyvento needs to know about – a payment arrives, an amount is refunded, PayPal reverses a payment or a customer opens a dispute –, PayPal sends a message to a fixed address in Kyvento. Without this return channel, Kyvento only sees the immediate payment, but none of these follow-up events. The result: invoices stay marked as "paid" even though the money has long since flowed back. This article walks you through setting up the webhook step by step – it is a two-way setup: you enter the Kyvento webhook URL in your PayPal app and then transfer the webhook ID generated by PayPal back into Kyvento.

Live or sandbox – don't mix them up: PayPal webhooks always hang on a specific app, and live and sandbox apps are completely separate. Set up the webhook in the same environment you run PayPal in within Kyvento, and transfer the webhook ID from exactly that app. A sandbox webhook ID does not verify live events – and vice versa.

Before you start

  • A PayPal business account and access to the PayPal Developer Dashboard (developer.paypal.com).
  • PayPal is set up in Kyvento (client ID and secret stored) – Settings → Payments → PayPal.
  • In Kyvento, permission to manage settings (e.g. the "Administrator" or "Full access" system role).
  • You know whether you run PayPal in Kyvento in live or sandbox mode.

Step 1: Copy the webhook URL from Kyvento

  1. In Kyvento, open Settings → Payments → PayPal.
  2. Find the "Webhook URL" card. It shows your personal, account-bound address – it ends with your Kyvento account number and looks something like: https://app.kyvento.com/api/webhooks/paypal/123.
  3. Click the copy icon to put the full URL on your clipboard.

Important: Always copy the URL in full, including the number at the end. That number assigns the events to your account – without it the webhook goes nowhere.

Step 2: Open the correct app in the PayPal Developer Dashboard

  1. Sign in at developer.paypal.com and open Apps & Credentials.
  2. Switch to the right environment at the top: Live or Sandbox – the same one you use in Kyvento.
  3. Open the app whose client ID and secret you stored in Kyvento.

Step 3: Create the webhook and select events

  1. In the app, scroll to the "Webhooks" section and click "Add Webhook".
  2. Paste the Kyvento URL you copied in step 1 into "Webhook URL".
  3. Under "Event types", select the following events. Kyvento processes only these – a missing event means the corresponding action never reaches Kyvento:
  • PAYMENT.CAPTURE.COMPLETED – payment received successfully (invoice set to "paid")
  • PAYMENT.CAPTURE.DENIED – payment denied/failed
  • PAYMENT.CAPTURE.REFUNDED – amount refunded
  • PAYMENT.CAPTURE.REVERSED – forced reversal (e.g. by the bank), even without a formal dispute
  • CUSTOMER.DISPUTE.CREATED – customer opens a dispute/buyer-protection case
  • CUSTOMER.DISPUTE.RESOLVED – dispute closed (in your favor or not)

The six events above are required for complete accounting. In addition, you may optionally enable VAULT.PAYMENT-TOKEN.CREATED and VAULT.PAYMENT-TOKEN.DELETED – they only provide an extra control signal for stored payment methods and are not required for payments, refunds and disputes.

  1. Save the webhook with "Save".

If selecting each event feels too granular, "All events" works too – Kyvento simply ignores anything not in the list above. Selecting specific events does, however, keep the event log tidier.

Step 4: Transfer the webhook ID back to Kyvento

So that Kyvento can be sure a message really comes from your PayPal app, it verifies every delivery against the webhook ID. Without this ID, Kyvento rejects all events.

  1. After saving, PayPal shows the newly generated webhook ID (a string such as 5GP028356R811364S). Copy this ID.
  2. Switch back to Kyvento: Settings → Payments → PayPal.
  3. Paste the copied ID into the "Webhook ID" field.
  4. Save the settings.

Verifying success

Finally, check that the connection actually works:

  1. In the PayPal app, open the webhook you created and – where available – use the option to send a test/mock event (e.g. PAYMENT.CAPTURE.COMPLETED).
  2. In the webhook's event log, the delivery must appear with status HTTP 200. Status 200 only confirms that Kyvento accepted the delivery – the authenticity check against the webhook ID runs immediately afterwards.

The real cross-check is therefore what matters: trigger a test payment – it appears in Kyvento as "paid". Then refund that payment directly in PayPal; in Kyvento the corresponding payment then shows as "Refunded" (in the invoice's payment overview).

If it doesn't work

  • Status 403 in the PayPal log: The webhook ID (or client ID/secret) is missing in Kyvento – step 4 has not been completed. Paste the webhook ID into the "Webhook ID" field and save.
  • Deliveries show status 200, but nothing arrives in Kyvento: The stored webhook ID doesn't match the sending app. Most common cause: the ID comes from the wrong environment (live instead of sandbox or vice versa) or from a different app. Kyvento accepts the delivery but discards it during the subsequent authenticity check. Transfer the webhook ID from exactly the app whose client ID is stored in Kyvento.
  • Status 404: The webhook URL is incomplete – usually the account number at the end is missing. Copy the URL again from the "Webhook URL" card.
  • Refunds/disputes don't arrive, but payments do: The PAYMENT.CAPTURE.REFUNDED / CUSTOMER.DISPUTE.* types are missing from the event selection. Add them in the PayPal app.

Next steps

  • Set up the Stripe webhook – see "Setting up the Stripe webhook"
  • Enable PayPal as a payment method – see "Integrating PayPal"
  • Record a refund triggered directly in PayPal by hand – see "Recording a PayPal refund manually in Kyvento"