# Labels

Tag a request with your own ids — the client, project or campaign it is for — and they come back with its result and its webhook. Your dashboard filters history by them and shows what each one spent, month by month.

Any endpoint takes them

```
{
  "url": "https://example.com",
  "labels": { "client": "acme", "project": "spring-launch" }
}
```

They work on every endpoint, including [/scrape](https://urlpipe.dev/docs/scrape) (one set for the whole request), and over the [MCP server](https://urlpipe.dev/docs/mcp). A form-encoded request sends them as `labels[client]=acme`.

## Where they come back

- In the `X-Labels` header of every response for the request — sync results, [GET /result/:token](https://urlpipe.dev/docs/results) and timeouts alike — as a JSON object. See [Response headers](https://urlpipe.dev/docs/response-headers).
- In the body of an async accept, beside the `token`: `{"token": "…", "status": "accepted", "labels": {"client": "acme"}}`.
- In every [webhook delivery](https://urlpipe.dev/docs/async#webhook), as a top-level `labels` object — route a result to the client it belongs to without keeping a table of tokens.
- In the MCP tools' metadata, and in `list_requests`, which filters by them.

## In your dashboard

Every project's **History** shows each request's labels. Click one to see every request carrying it, or choose **Filters → Labels** and enter a key and a value.

The project's **Labels** page totals requests, failures and credits for each value of a key, one calendar month at a time — the same months, and the same counting, as your [credits](https://urlpipe.dev/docs/credits). It also shows what requests without that label spent, so the figures add up to the project's month and you can bill each client for exactly their share.

## The rules

- An object of up to **16 keys**.
- Keys are 1 to 40 letters, digits, underscores, hyphens or periods — `client_id`, `project.name`, `env-2`. Case counts: `Client` and `client` are two keys.
- Values are strings of 1 to 256 characters, any language. Send ids as strings — `"42"`, not `42` — so what you filter by later is exactly what you sent.
- Filters match a value exactly, character for character.

Labels outside these rules are refused with a `422` before anything runs or is charged, and the message names what to change:

422 Unprocessable Entity

```
{
  "error": "invalid_labels",
  "message": "labels.client must be a string."
}
```

## Free to add

Labels cost nothing and change nothing about the work. They are not part of the [cache key](https://urlpipe.dev/docs/caching): a labelled request reuses a stored result exactly as an unlabelled one does, for free, and each request keeps its own labels — two clients fetching the same page each see their own.

A request's labels are fixed when you make it. Use ids rather than names, and keep secrets and personal data such as email addresses out of them: they appear in your dashboard, your webhooks and your team's view of the project.

[See how async results reach you](https://urlpipe.dev/docs/async)

Source: https://urlpipe.dev/docs/labels
