---
url: https://simpledatalogs.com/docs/integrations/vercel.md
description: >-
  Send Vercel runtime, build and request logs to simpledatalogs with a signed
  Log Drain, deduped on Vercel's own log ids.
---

# Vercel

A Vercel Log Drain posts your deployments' logs to ingest. Ingest checks Vercel's signature, and each entry becomes a log line.

Drains need a Vercel Pro or Enterprise team.

## Set it up

1. In Vercel, open **Team Settings → Drains → Add Drain** and choose **Logs**.
2. Pick the projects, sources and environments (see [Keep the volume down](#keep-the-volume-down)).
3. Under **Custom Endpoint**:

| Field | Value |
|---|---|
| Endpoint URL | `https://edge.simpledatalogs.com/vercel/v1/logs` |
| Format | JSON or NDJSON |
| Signature Verification Secret | Your ingest key, `sdl_sec_…` |
| Custom Headers | `Authorization: Bearer sdl_sec_…` (the same key) |

4. Click **Create Drain**. Vercel tests the endpoint first; the **Test** button sends sample entries any time.

::: warning Replace the generated secret
Vercel fills in a random signature secret. Replace it with your ingest key, or every delivery is refused with `403 invalid_signature`.
:::

If Vercel asks you to verify the endpoint, add its code to the URL: `https://edge.simpledatalogs.com/vercel/v1/logs?verify=<code>`. Ingest echoes it back in `x-vercel-verify`.

## What's stored

| Field | From the Vercel entry |
|---|---|
| `message` | `message`, masked like a text line; a request log without one reads `GET /about 200` |
| `level` | `level` (`info`, `warning`, `error`; `fatal` is `critical`) |
| `ts` | `timestamp` |
| `event_id` | Derived from Vercel's `id`, so a retried delivery never counts twice |
| `props` | `source`, `host`, `path`, `statusCode`, `requestId`, `deploymentId`, `projectId`, `projectName`, `environment`, `branch`, `type`, `entrypoint`, `traceId`, `spanId` and more; `method` and `region`; the request as `proxy.path`, `proxy.statusCode`, `proxy.vercelCache`, `proxy.userAgent` … |

The client IP (`proxy.clientIp`) and the TLS fingerprints (`ja3Digest`, `ja4Digest`) are never stored.

Vercel batches up to 1 MB. Ingest splits a batch over 512 KB at entry boundaries, so nothing is refused for size.

## Keep the volume down

::: warning Every request log is an event
With the `static` and `edge` sources on, every page view, image and asset request is a row, and counts against your monthly events.
:::

* Choose only the **sources** you need. `lambda` and `build` are usually enough.
* Choose **Production** only, unless you debug previews here.
* Add a **sampling rule**, such as 10% of `/`, and 100% of `/api`.
* Filter by `source` in Logs to see one kind at a time.

## Responses

* `200 {"accepted":"<id>"}` once the whole delivery is stored.
* `403 missing_signature` or `403 invalid_signature` when the signature doesn't match the key.
* Other refusals are [`/v1/ingest`'s](/api/responses#v1-ingest), with `Retry-After`. Vercel retries failed deliveries.

## Next steps

* [Heroku](/integrations/heroku): the other hosting drain.
* [Logs](/api/log-lines): how log lines are read and masked.
