> For the complete documentation index, see [llms.txt](https://docs.arcade.software/kb/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.arcade.software/kb/interactive-demo/leverage/advanced-features/webhooks.md).

# Webhooks

Webhooks allow you to receive real-time updates when viewers interact with your Arcades. Webhooks are ideal for connecting Arcade to your internal systems, CRMs, or automation workflows.

{% hint style="info" %}
Webhooks are available on the Enterprise plan only.
{% endhint %}

## What events does Arcade support via webhooks?

Currently, Arcade supports webhooks for **form submission events**:

* `formSubmission.created`
* `formSubmission.updated` (reserved for future use)

More events may be added in the future — let us know if there are others you'd like to see!

***

## How do I set up a webhook?

You can configure your webhook in the **Advanced Settings** of your Arcade workspace.

1. Go to `Settings > Advanced`
2. Enter your webhook **URL**
3. Copy your **webhook secret** (used for verifying the payload)
4. Save your changes

Arcade will send a `POST` request to your configured URL whenever a supported event occurs.

***

## What does the webhook payload look like?

The payload is sent as a JSON object. Here’s an example of a `formSubmission.created` event:

```json
jsonCopy code{
  "type": "formSubmission.created",
  "timestamp": "2024-02-15T15:51:12.013Z",
  "flowId": "khM1A286JbRPxN9fxYsE",
  "sessionId": "b8103665-e6ce-4db8-894e-f123ec49ed9c",
  "viewerIp": "127.0.0.1",
  "stepTitle": "Step title (optional)",
  "stepSubtitle": "Step subtitle (optional)",
  "answers": {
    "User Email": {
      "variant": "email",
      "value": "foo@bar.com"
    },
    "User Name": {
      "variant": "text",
      "value": "Foo Bar"
    }
  }
}
```

***

## What headers are included with the webhook?

Every webhook request includes:

* `content-type: application/json`
* `x-arcade-signature`: an HMAC-SHA256 signature of the raw body, Base64 encoded
* `x-arcade-signature-2` (optional): a second signature used during secret rotation

***

## How do I verify the webhook signature?

You can verify the signature by creating an HMAC using your webhook secret and comparing it to the `x-arcade-signature` header.

#### With a Next.js API route:

```ts
tsCopy codeimport crypto from 'node:crypto'
import getRawBody from 'raw-body'

export const config = {
  api: { bodyParser: false }
}

export default async function handler(req, res) {
  if (req.method !== 'POST') return res.status(405).end()

  const signature = req.headers['x-arcade-signature']
  const signature2 = req.headers['x-arcade-signature-2']
  const rawBody = await getRawBody(req)

  const validSignature = crypto
    .createHmac('sha256', process.env.ARCADE_SIGNING_SECRET)
    .update(rawBody)
    .digest('base64')

  if (signature !== validSignature && signature2 !== validSignature) {
    return res.status(403).end()
  }

  const event = JSON.parse(rawBody)
  // Handle the event
  res.status(200).end()
}
```

***

#### With a Next.js Route Handler (App Router):

```ts
tsCopy codeimport { type NextRequest, NextResponse } from 'next/server'
import crypto from 'node:crypto'

export async function POST(request: NextRequest) {
  const signature = request.headers.get('x-arcade-signature')
  const signature2 = request.headers.get('x-arcade-signature-2')
  const rawBody = await request.text()

  const validSignature = crypto
    .createHmac('sha256', process.env.ARCADE_SIGNING_SECRET!)
    .update(rawBody)
    .digest('base64')

  if (signature !== validSignature && signature2 !== validSignature) {
    return NextResponse.json({ error: 'Invalid signature' }, { status: 403 })
  }

  const event = JSON.parse(rawBody)
  // Handle the event
  return NextResponse.json({ success: true })
}
```

***

## Can I test my webhook?

Yes — we recommend using a tool like [Webhook.site](https://webhook.site/) to test your configuration before pointing to a production endpoint. You can also test against your dev environment using tools like `ngrok`.

***

## What should I do if I need more webhook events?

Let us know! We currently support form submission events, but we're exploring more event types (e.g. CTA clicks, Arcade completions, viewer sessions). Your input helps prioritize our roadmap.

***

{% @arcade/embed flowId="SE1a3DGOwrvc6HAhppUB" url="<https://app.arcade.software/flows/SE1a3DGOwrvc6HAhppUB/view>" %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.arcade.software/kb/interactive-demo/leverage/advanced-features/webhooks.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
