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

> ## Agent Instructions
> Automate.ax automations are TypeScript programs.
> Use Bun for installation and command examples.
> Use Automate.ax for the product name and automate.ax for the package, CLI, and domain.
> Treat documented public APIs as current; do not invent transitional or deprecated names.

# Receive unsupported events

> Receive unsupported provider events with an Automate.ax HTTP trigger.

Automate.ax doesn't support user-defined, platform-managed triggers. Managed triggers depend on privileged server components for subscription setup, authentication, renewal, event ingestion, and durable delivery, so an automation can't define one entirely in its own code.

## Receive a custom webhook

Use `onHttpRequest` as the callback for an unsupported webhook:

```ts automations/receive-custom-webhook.automation.ts theme={null}
import { automation, markSignificant, onHttpRequest } from "automate.ax"

export default automation("Receive a custom webhook", () => {
  const request = onHttpRequest()
  markSignificant(request)
})
```

Deploy the automation, then register the HTTP trigger URL printed by the command-line tool as the provider's webhook callback. Each request starts an automation execution. Its headers, query parameters, decoded body, and exact `rawBody` bytes are available on the request signal. Use `rawBody` for signature verification so parsing doesn't change the signed content.

Automate.ax omits browser and proxy infrastructure headers from durable request data: `cookie`, `cf-*`, `sec-*`, and `x-forwarded-for`. You can't authenticate a custom webhook that requires one of those headers. For example, Cloudflare Notifications sends its authentication secret in `cf-webhook-auth`, so that webhook isn't compatible with a custom trigger.

You are responsible for configuring and renewing the provider's webhook, authenticating requests, validating its payload, and handling provider retries or duplicate events. Automate.ax provides the HTTP endpoint and execution delivery. It doesn't manage the provider-side subscription for a custom webhook.

## Verify webhook signatures

Use the provider's maintained verification package from the `npm` registry when one is available. Install it with Bun, for example:

```bash theme={null}
bun add standardwebhooks
```

Store the signing secret in 1Password and resolve it with a connected service account. Pass only the sensitive signal returned by `onePassword.resolveSecret` to the verification action. Don't put a raw secret literal in an action input or return, log, or include the resolved value in an error.

This example verifies a provider that follows the [Standard Webhooks specification](https://github.com/standard-webhooks/standard-webhooks). Its `npm` package compares signatures in constant time:

```ts automations/standard-webhook.automation.ts theme={null}
import { Webhook } from "standardwebhooks"
import {
  automation,
  defineAction,
  markSignificant,
  onHttpRequest,
} from "automate.ax"
import { onePassword } from "automate.ax/onepassword"
import { z } from "zod"

const eventSchema = z.object({
  id: z.string(),
  type: z.string(),
})

const verifyWebhook = defineAction("Verify webhook")
  .input(
    z.object({
      headers: z.record(z.string(), z.string()),
      rawBody: z.custom<Uint8Array<ArrayBufferLike>>(
        (value) => value instanceof Uint8Array,
      ),
      signingSecret: z.string(),
    }),
  )
  .output(eventSchema)
  .retry({ replaySafety: "safe" })
  .handler(({ input }) =>
    eventSchema.parse(
      new Webhook(input.signingSecret).verify(
        new TextDecoder().decode(input.rawBody),
        input.headers,
      ),
    ),
  )

export default automation("Verify a signed webhook", () => {
  const request = onHttpRequest()
  const signingSecret = onePassword.resolveSecret({
    secretReference: "op://Automation/ExampleWebhook/signingSecret",
  })

  const verified = verifyWebhook({
    headers: request.headers,
    rawBody: request.rawBody,
    signingSecret,
  })

  markSignificant(verified)
})
```

Use the provider package's required header names, signed-content format, encoding, and replay tolerance. Gate every side effect on successful verification. Deduplicate retries with the provider's stable delivery ID; a valid signature proves authenticity but doesn't make repeated delivery idempotent.

Signature verification runs after Automate.ax accepts the HTTP request and creates durable run data. Package replay-window checks therefore use the time when the action starts unless the package lets you supply a separately recorded receipt time. Queue or cold-start delay can make a short window reject a valid delivery. Use a managed integration trigger when verification or replay protection must happen at event ingestion.

When one of your actions gives a callback URL directly to the provider, use `onHttpRequest({ protection: "callback" })` and generate the URL with `runtime.createCallbackUrl(endpoint)`. This bearer capability prevents callers without the signed URL from reaching that exact trigger. It doesn't prove the provider's identity. Validate the provider's signature as well when you need identity assurance. Protected callback deliveries remain independent root contexts, so correlate a provider job ID to the initiating action instead of relying on the capability for context inheritance.

Use `respondToHttpRequest({ requestId: request.requestId, ... })` when the provider requires a verification challenge or synchronous response. This makes the trigger wait automatically. See [On HTTP request](/reference/triggers/on-http-request) for the full request shape and response timeout.
