# Netlify proxy

> A dependency-free Edge Function for any site on Netlify: it answers the one path the dashboard issued and forwards the browser SDK's calls to Fingerly.

Last updated: 2026-09-25

An Edge Function for any site on Netlify. It answers one path the dashboard issued, on your own domain, and forwards only the browser SDK's submissions to Fingerly. It is not an open proxy: the upstream is a constant in the code, and every other path and method is refused. Version 1.0.0.

## Set up

### Step 1: Create the proxy

In the dashboard, open **Integration > Proxy keys** and choose **New proxy**. Pick the environment of the public key it will forward, and **Netlify** under **How it runs**. Copy the [proxy key](https://docs.fingerly.io/docs/proxy-integrations#proxy-keys) it shows once, and note the path it issued, such as `/k7x2qm4a`.

The dashboard then prints the steps below, filled in with your proxy's own path and key. They stay under **Show setup** in the proxy's menu, without the key, which is never shown again.

### Step 2: Add the edge function

Save `relay.ts` as `netlify/edge-functions/relay.ts` in your site. It has no dependencies. Its `PATH` constant holds the path; the dashboard prints the file with yours filled in.

### Step 3: Bind it to the path

In `netlify.toml` at the root of your site.

```toml netlify.toml
[[edge_functions]]
  function = "relay"
  path = "/k7x2qm4a"
```

### Step 4: Add the proxy key

As an environment variable scoped to functions, or in **Project configuration > Environment variables**.

```bash Terminal
netlify env:set FINGERLY_PROXY_KEY fly_px_production_… --scope functions
```

### Step 5: Deploy

The function runs from the next production deploy.

```bash Terminal
netlify deploy --prod
```

### Step 6: Point the browser SDK at the path

```ts fingerly.ts
import { load } from '@fingerly/web-js'

const fingerly = await load({
  apiKey: 'fly_pk_production_…',
  endpoints: '/k7x2qm4a',
})
```

The SDK posts both of its calls to the path exactly as given. Once pages use it, the proxy's row in **Proxy keys** shows it last seen, running `netlify/1.0.0`, with its requests over the last 30 days.

## How the visitor's address is trusted

The function sends `context.ip`, the address Netlify's edge accepted the connection from, as `x-fingerly-client-ip`. It is not read from any header, so the visitor cannot change it.

## What it sends and relays

Upstream, to `https://api.fingerly.io/api/v1/ingest` and nowhere else, on headers built from scratch: `content-type`, `x-api-key`, `Idempotency-Key` when present, and the `x-fingerly-*` headers the proxy sets itself (the proxy key, the visitor's address, the page origin, the user agent and `x-fingerly-proxy-version: netlify/1.0.0`). Cookies, `Authorization` and any `x-fingerly-*` header a visitor sends never leave.

Other methods answer `405` with `Allow: POST`, and other paths `404`. Bodies over 1 MiB are refused with `413`, redirects are not followed, and a missing or malformed key answers `503` rather than forwarding anything.

Back to the page: the API's status and body, with only `content-type`, `x-request-id`, `ratelimit-limit`, `ratelimit-remaining` and `retry-after`, plus `cache-control: no-store`. Nothing relayed names Fingerly.
