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

# Integrations

> Configure Esper at an application or edge boundary using Workers, proxies, Lambdas, or on-edge runtimes.

Esper integrations collect request context at an application or edge boundary,
send it to the runtime decision API, and apply the returned action at that
boundary.

Use these guides when you want Esper to sit at a boundary you already control,
such as:

* Vercel
* Cloudflare Workers
* AWS Lambda
* Google Cloud Functions
* Heroku

<Info>
  **Recipes Back These Guides**

  Each integration page is based on the recipe source shipped in this repository
  under `recipes/`. The docs explain what to configure, what the recipe is doing,
  and where it fits in the broader Esper workflow.
</Info>

## What every integration must send

Customers should not need to guess what Esper needs. At a minimum, every
integration should preserve the original request context well enough for Esper
to evaluate policy and return one immediate action consistently.

<Info>
  **Primary Runtime Contract**

  For `cloud`, the integration should call `POST /api/v1/runtime/mitigation` with:

  * `x-esper-api-key`
  * request context
  * observed timestamp
  * optional return URL for challenge handoff
  * any request fields your policy depends on

  The request context you preserve should include:

  * client IP
  * user agent
  * method
  * path
  * query params
  * request headers
  * cookies when relevant

  Forward query params and cookies even when the request is returning from an
  Esper-managed challenge. `/runtime/mitigation` validates
  `esper_challenge_proof` and the configured proof cookie before policy
  evaluation, so a solved challenge returns `allow` without creating a duplicate
  challenge decision or challenge session.
</Info>

<Tip>
  **Keep The Cloud Contract Small**

  Cloud integrations should keep the logical runtime decision contract the same
  regardless of transport or provider details. The customer should still only
  need an API key and an integration boundary that can preserve request context.
</Tip>

<Tip>
  **Preserve Original Request Context**

  If your integration drops IP, user agent, path, or headers before forwarding to
  Esper, entity mapping and policy evaluation will drift from the real request.
  The safest pattern is to forward the original request context as completely as
  your platform allows.
</Tip>

## Which Esper headers matter

Different runtime paths need different Esper-owned identifiers. The goal is to
keep customer-facing contracts small and stable.

| Flow                         | What customer sends   | Why it matters                                                                                   |
| ---------------------------- | --------------------- | ------------------------------------------------------------------------------------------------ |
| Runtime decision             | `x-esper-api-key`     | Authenticates the synchronous `/api/v1/runtime/mitigation` request                               |
| Managed challenge follow-up  | `X-Esper-Decision-ID` | Used only when a lower-level challenge flow is started outside the runtime wrapper               |
| Local mitigation enforcement | `X-Esper-Hybrid-Key`  | Lets local enforcement identify the active mitigation record without exposing internal Esper ids |

<Warning>
  **Customer Integrations Should Prefer `/api/v1/runtime/mitigation`**

  The customer-facing integration should not make separate manual Beacon,
  mitigation, and challenge-orchestration calls. Esper should receive one
  runtime request and return one immediate action: `allow`, `challenge`, or
  `block`.
</Warning>

## What to preserve from the original request

Regardless of platform, the integration should preserve these fields whenever
they are available:

* client IP, including trusted forwarded IP headers from your platform
* user agent
* request method
* request path
* query string parameters
* relevant request headers
* cookies if your rules or entity model depend on them

<Tip>
  **Challenge Redirect Data**

  For managed challenge flows, redirect data belongs in the challenge start query
  string, not in a JSON body. Use query parameters such as `return_url`,
  `path`, `query_params[...]`, and `route_params[...]`.
</Tip>

## How to choose an integration

* Choose **Vercel** if your application already runs on Vercel and you want a
  simple serverless entry point.
* Choose **Cloudflare Workers** if you want a low-overhead edge wrapper that
  verifies managed challenge returns, asks Esper for one runtime decision, and
  applies `allow`, `challenge`, or `block` before origin.
* Choose **AWS Lambda** if your traffic enters through API Gateway and Lambda.
* Choose **Google Cloud Functions** if your traffic enters through an HTTP
  Cloud Function or Cloud Run function.
* Choose **Heroku** if you want a simple app-process proxy with minimal
  infrastructure work.

## What each integration does

At a high level, each recipe:

1. receives the incoming request
2. gathers request context such as IP, path, method, user agent, headers, and
   query params
3. asks Esper for a mitigation decision
4. applies the result at that boundary
5. forwards traffic or telemetry as needed

<Tip>
  **Start With The Simplest Enforcement Story**

  If you are onboarding a new property, validate `allow` first, then introduce
  `challenge`, and only later rely on automatic `block`. Monitoring remains
  internal to Esper and should not require a separate customer-facing action mode.
</Tip>

## Integration checklist by mode

### Runtime decision

* Send `x-esper-api-key`
* Call `POST /api/v1/runtime/mitigation`
* Preserve original request context in the request body
* Make sure client IP and user agent survive platform forwarding

### Managed Esper challenge

* Let the integration consume Esper's `challenge` action directly
* Use the returned `redirect_url` immediately
* Forward proof query parameters and proof cookies on later runtime requests
* Treat separate challenge-start calls as lower-level plumbing, not the primary
  customer flow

### Local mitigation enforcement

* Preserve or inject `X-Esper-Hybrid-Key` where your local enforcement path
  requires it today
* Keep the same entity mapping inputs stable between ingest and enforcement
* Do not invent a second actor identity model at the edge

### Generic monitor / block / challenge handling

* Forward enough request context for Esper to make the right decision
* Apply only the returned action:
  * `allow`
  * `challenge`
  * `block`
* Keep policy evaluation and mitigation handling at the same traffic boundary when possible

## What to expect from the recipes today

* They are practical starting points for adapting the recipe code.
* They keep setup code small enough to review and adapt.
* They make the request boundary explicit, which is the key place where Esper
  receives context and returns a decision.

## Read next

* [Beacon Server](../beacon-server)
* [Mitigation Server](../mitigation-server)
* [Mitigation Overview](../mitigation)

## Integration guides

* [Vercel](./vercel)
* [Cloudflare Workers](./cloudflare)
* [AWS Lambda](./aws)
* [Google Cloud Functions](./google-cloud)
* [Heroku](./heroku)
