Webhooks

Webhooks allow you to build or set up integrations that subscribe to certain Polar events. When one of those events is triggered, we'll send an HTTP POST payload to the webhook's configured URL.

Our implementation follow the Standard Webhooks specification.

Out-of-the-box, we also support to send notifications suitable for Discord or Slack. This is the purpose of the Format parameter.

Tunneling Webhook events to your localhostCopied!

If you're developing locally, you can use a tool like ngrok to tunnel webhook events to your local development environment. This will allow you to test your webhook handlers without deploying them to a live server.

Run the following command to start an ngrok tunnel:

ngrok http 3000

Configuring a WebhookCopied!

Head over to your organization's settings page and click on the "Add Endpoint" button to create a new webhook.

URLCopied!

In the dialog that appears, enter the URL to which the webhook events should be sent.

FormatCopied!

For standard, custom integrations, leave this parameter on Raw. This will send a payload in a JSON format.

If you wish to send notifications to a Discord or Slack channel, you can select the corresponding format here. Polar will then adapt the payload so properly formatted messages are sent to your channel.

If you paste a Discord or Slack Webhook URL, the format will be automatically selected.

SecretCopied!

In order to verify that requests are legitimate webhook payload coming from Polar, we cryptographically sign the requests using a secret key. You can set your own or generate a random one.

EventsCopied!

Finally, select the events you want to be notified about. You can learn more about the different events we offer in the API Reference

Webhook DeliveryCopied!

Once a webhook is configured, you will have access to a delivery overview page. This page shows you all the webhook events that have been sent to the configured URL. You can easily see the status of each delivery and the data which was sent.

RetriesCopied!

If we hit an error while trying to reach your endpoint, whether it is a temporary network error or a bug, we'll retry to send the event up to 10 times with an exponential backoff.

TimeoutsCopied!

We expect your endpoint to answer under 20 seconds. Past this delay, the delivery will error and we'll enter the retry cycle described above. We recommend you to avoid too long processing while receiving the webhook. The good practice if you have long logic to run is to queue the event and respond to the webhook immediately. Your logic is then run in a background by a worker.

Verify signatureCopied!

Requests sent to your webhook endpoint will include a signature so you can verify that the request is truly coming from Polar.

Our Python and JavaScript SDK provide a function to validate and parse the webhook event.

Python example

from flask import Flask, request
from polar_sdk.webhooks import validate_event, WebhookVerificationError

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    try:
        event = validate_event(
            payload=request.data,
            headers=request.headers,
            secret='<YOUR_WEBHOOK_SECRET>',
        )

        # Process the event

        return "", 202
    except WebhookVerificationError as e:
        return "", 403

Node.js example

import express, { Request, Response } from 'express'
import { validateEvent, WebhookVerificationError } from '@polar-sh/sdk/webhooks'

const app = express()

app.post(
  '/webhook',
  express.raw({ type: 'application/json' }),
  (req: Request, res: Response) => {
    try {
      const event = validateEvent(
        req.body,
        req.headers,
        process.env['POLAR_WEBHOOK_SECRET'] ?? '',
      )

      // Process the event

      res.status(202).send('')
    } catch (error) {
      if (error instanceof WebhookVerificationError) {
        res.status(403).send('')
      }
      throw error
    }
  },
)

For other languages, as we follow the Standard Webhooks specification, you can use one of their libraries to verify the signature: https://github.com/standard-webhooks/standard-webhooks/tree/main/libraries

When using the Standard Webhooks libraries. They expect your secret to be encoded in Base64.

Handling Subscription EventsCopied!

In order to properly implement logic for handling subscriptions, you should look into the following events.

subscription.created

Fired when a new subscription has been created.

subscription.updated

Use this event if you want to handle cancellations, un-cancellations, etc. The updated event is a catch-all event for subscription.active , subscription.canceled , subscription.uncanceled & subscription.revoked

order.created

In case you want to do logic when a subscription is renewed, you should listen to order.created and the billing_reason field. It can be purchase , subscription_create , subscription_cycle & subscription_update . subscription_cycle is used when subscriptions renew.