# Handle payment events with webhooks

How to use webhooks to respond to offline payment events.

A *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) is an HTTP endpoint that receives events from Stripe.

Webhooks allow you to be notified about payment events that happen outside of your payment flow such as:

- Successful payments (`payment_intent.succeeded`)
- Disputed payments (`charge.dispute.created`)
- Available balance in your Stripe account (`balance.available`)

You can use the Dashboard for one-off actions like refunding a payment or updating a customer’s information, while webhooks help you scale your payments integration and process large volumes of business-critical events.

## Build your own webhook

You can build a webhook handler on your own server to manage all your offline payment flows. Start by exposing an endpoint that can receive requests from Stripe and use the CLI to locally test your integration. Each request from Stripe contains an [Event](https://docs.stripe.com/api/events/object.md) object with a reference to the object on Stripe that was modified.

## Create a webhook endpoint

Add a new endpoint in your application. You can act on certain events by checking the `type` field of the event object sent in the request body. Then you can print to standard output to make sure your webhook is working.

Start your server after adding the new endpoint.

#### Node.js

```javascript

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
const stripe = require('stripe')('<<YOUR_SECRET_KEY>>');

// This example uses Express to receive webhooks
const app = require('express')();

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

// Match the raw body to content type application/json
app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
  const event = request.body;

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      const paymentIntent = event.data.object;
      console.log('PaymentIntent was successful!');
      break;
    case 'payment_method.attached':
      const paymentMethod = event.data.object;
      console.log('PaymentMethod was attached to a Customer!');
      break;
    // ... handle other event types
    default:
      console.log(`Unhandled event type ${event.type}`);
  }

  // Return a 200 response to acknowledge receipt of the event
  response.json({received: true});
});

app.listen(4242, () => console.log('Running on port 4242'));
```

## Install and set up the Stripe CLI
For additional install options, see [Get started with the Stripe CLI](https://docs.stripe.com/stripe-cli.md).
After you have the Stripe CLI installed, run `stripe login` in the command line to generate a pairing code to link to your Stripe account. Press **Enter** to launch your browser and log in to your Stripe account to allow access. The generated API key is valid for 90 days. You can modify or delete the key under [API Keys](https://dashboard.stripe.com/apikeys) in the Dashboard.

> You can create a project-specific configuration by including the [–project-name](https://docs.stripe.com/cli/login#login-project-name) flag when you log in and when you run commands for that project.

Test

```bash
stripe login
Your pairing code is: humour-nifty-finer-magic
Press Enter to open up the browser (^C to quit)
```

If you want to use an existing API key, use the `--api-key` flag:

```bash
stripe login --api-key <<YOUR_SECRET_KEY>>
Your pairing code is: humour-nifty-finer-magic
Press Enter to open up the browser (^C to quit)
```

## Test your webhook locally

Use the CLI to forward events to your local webhook endpoint using the `listen` command.

Assuming your application is running on port 4242, run:

```bash
stripe listen --forward-to http://localhost:4242/webhook
```

In a different terminal tab, use the `trigger` CLI command to trigger a mock webhook event.

```bash
stripe trigger payment_intent.succeeded
```

The following event appears in your `listen` tab:

```bash
[200 POST] OK payment_intent.succeeded
```

“PaymentIntent was successful!” appears in the terminal tab your server is running.

## Optional: Check webhook signature

Stripe includes a signature in each event’s `Stripe-Signature` header. This allows you to verify that the events were sent by Stripe, and not by a third party. You can verify signatures either using our official libraries, or [verify signatures manually](https://docs.stripe.com/webhooks.md#verify-manually) using your own solution.

First, find your webhook endpoint secret and add it to your webhook handler as `endpoint_secret`. Because you’re still using the Stripe CLI to develop your endpoint locally, use the `trigger` command to get the webhook endpoint secret from the CLI.

```bash
stripe listen
```

The webhook endpoint secret starts with `whsec_` followed by a series of numbers and letters. Keep this webhook endpoint secret safe and never expose it publicly.

#### Node.js

```javascript

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
const stripe = require('stripe')('<<YOUR_SECRET_KEY>>');

// If you are testing your webhook locally with the Stripe CLI you
// can find the endpoint's secret by running `stripe listen`
// Otherwise, find your endpoint's secret in your webhook settings in the Developer Dashboardconst endpointSecret = 'whsec_...';

// This example uses Express to receive webhooks
const express = require('express');

const app = express();

// Match the raw body to content type application/json
app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {const sig = request.headers['stripe-signature'];

  let event;

  try {event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
  }catch (err) {
    response.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      const paymentIntent = event.data.object;
      console.log('PaymentIntent was successful!');
      break;
    case 'payment_method.attached':
      const paymentMethod = event.data.object;
      console.log('PaymentMethod was attached to a Customer!');
      break;
    // ... handle other event types
    default:
      console.log(`Unhandled event type ${event.type}`);
  }

  // Return a response to acknowledge receipt of the event
  response.json({received: true});
});

app.listen(4242, () => console.log('Running on port 4242'));
```

## Deploy your webhook endpoint

When you’re ready to deploy your webhook endpoint to production you need to do the following:

1. Use your [live mode API keys](https://docs.stripe.com/keys.md#test-live-modes) and not your test keys.
1. Configure your webhook endpoint in [Workbench](https://docs.stripe.com/workbench.md) or with the API.
1. To configure your endpoint in Workbench, go to the [Webhooks tab](https://dashboard.stripe.com/workbench/webhooks).
1. Click **Add destination** and enter the Stripe API version and the specific events you want Stripe to send. Click **Continue** and select **Webhook endpoint** from the list of available destination types. Click **Continue** and enter the URL of your endpoint, optional name, and optional description. Click **Create destination**.
1. Replace the webhook endpoint secret in your application with the new secret shown in the destination details view in Workbench for your endpoint.

Your application is now ready to accept live events. For more information on configuring your webhook endpoint, see the [Webhook Endpoint](https://docs.stripe.com/api/webhook_endpoints.md) API. For testing in a sandbox, [see our Development guide](https://docs.stripe.com/webhooks.md).
