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

> ## Agent Instructions
> Unkey is two separate products. Compute builds, deploys, and runs apps behind a gateway. API Management issues API keys, enforces rate limits, manages identities and permissions, and reports usage. Say which product a page belongs to; a reader can use either without the other.
> Every Unkey API endpoint is an HTTP POST to https://api.unkey.com/v2/{service}.{procedure} with a root key in the Authorization: Bearer header. Root keys are workspace scoped.
> Error codes have the form err:{system}:{category}:{specific} and each has a page at /errors/{system}/{category}/{specific}.
> The word environment means production or preview in Compute. Rate limiting has four meanings on this site; the glossary lists them.

# Metadata and tags

> Attach data to a key and to each verification of it.

Metadata is data you store on a key, like a plan tier. It comes back on every verification, so your backend doesn't need a database lookup. Tags are labels you send with each verification, like the endpoint called. They go only to analytics, so you can break usage down later.

## Metadata

<ParamField body="meta" type="object | null">
  A JSON object with at most 100 top-level properties. Nesting is allowed. Set it on `keys.createKey` or replace it on `keys.updateKey`, where leaving it out keeps the current value and `null` removes it. Every `keys.verifyKey` response returns it as `data.meta`.
</ParamField>

```bash theme={"system"}
curl -X POST https://api.unkey.com/v2/keys.createKey \
  -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "apiId": "api_...",
    "meta": { "plan": "pro", "features": ["exports", "webhooks"], "billingEmail": "ops@example.com" }
  }'
```

Keep metadata to what your request handler needs right away, like a plan tier, feature flags, or a tenant ID. Anything large slows every verification, and any service that calls `keys.verifyKey` can see it, so don't store secrets. To change one property, send the whole object again.

Metadata on an identity comes back separately as `data.identity.meta`. Put facts shared by all of a user's keys there, and key-specific facts on the key.

The dashboard's **Create key** dialog also has an <Tooltip tip="An optional free-text label stored on a key in the dashboard, such as live or test. Unkey attaches no behavior to it, and it is unrelated to Compute environments.">environment</Tooltip> field that sets a label on the key. That label isn't part of `keys.createKey`, `keys.updateKey`, or the verification response. Store such labels in `meta` when your backend must read them.

## Tags

<ParamField body="tags" type="string[]">
  On `keys.verifyKey`. Up to 20 strings of 1 to 512 characters each. They're recorded with the verification and don't change the result.
</ParamField>

```bash theme={"system"}
curl -X POST https://api.unkey.com/v2/keys.verifyKey \
  -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "sk_live_...",
    "tags": ["endpoint=/documents", "method=GET", "region=eu-west-1"]
  }'
```

Tags land in the `tags` column of the verifications table in analytics, so you can break usage down by endpoint, client version, or anything else. A `key=value` format makes them easy to filter. Don't put anything sensitive in a tag, because tags show up in analytics and the dashboard's verification logs. The [key verifications table](/docs/api-management/analytics/tables/key-verifications) shows how to query them.

## Which one to use

| Need | Use |
| - | - |
| Know the caller's plan or flags while handling the request | `meta` on the key, or `meta` on the identity if it is shared by all of a user's keys |
| Break usage reports down by endpoint, version, or region | `tags` on each verification |
| Tell live keys from test keys in your code | `meta`, since the dashboard environment label is not returned by verification |
