Tag your traffic

Tell CoreValue which of your users and customers each request was for, so you can see and cap spend per user and customer.

CoreValue already knows which key, team, model and provider each request used. It does not know who in your product the request was for, or what feature made it. Send that with a few Cova-* headers, and every page of the console can split spend by it.

The headers

HeaderTells CoreValueWhere it shows up
Cova-Customer-IdWhich of your customers the request was forRequests → Customer column · Spend → Customer · Budgets & Limits → Customers · Reports
Cova-Feature-IdWhich feature or surface made it, such as checkoutRequests → Feature column · Spend → Feature
Cova-User-IdThe person using your productRequests → User column · Spend → End user
Cova-Session-Id, -Name, -PathWhich run it belongs to, and which stepRequests → Run column · Spend → Run · Runs
Cova-Property-<Name>Anything else you want to split byRequests → a column per property · Spend → Property
Cova-ActorWhether a person or a program produced the turnRequests → Actor column · the run's Actors
Cova-Team-IdA team label for your own recordsThe request's Properties only — see below

Every header is optional. The Spend by … panel on the Dashboard uses the same tabs as Spend.

Send them

curl https://gateway.corevalue.dev/v1/chat/completions \
  -H "Authorization: Bearer $COVA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Cova-Customer-Id: acme-corp" \
  -H "Cova-Feature-Id: support-bot" \
  -H "Cova-User-Id: user_abc123" \
  -H "Cova-Property-Environment: production" \
  -d '{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Hello"}]}'
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello"}],
    extra_headers={
        "Cova-Customer-Id": "acme-corp",
        "Cova-Feature-Id": "support-bot",
        "Cova-User-Id": "user_abc123",
        "Cova-Property-Environment": "production",
    },
)
const response = await client.chat.completions.create(
  { model: "gpt-4o-mini", messages: [{ role: "user", content: "Hello" }] },
  {
    headers: {
      "Cova-Customer-Id": "acme-corp",
      "Cova-Feature-Id": "support-bot",
      "Cova-User-Id": "user_abc123",
      "Cova-Property-Environment": "production",
    },
  },
);

The client is the one from the Quickstart. To check a tag arrived, open the request on Requests and look under Properties.

Customers and features

Cova-Customer-Id and Cova-Feature-Id are cut at 256 characters; a value of only spaces is ignored. Spend groups customers without regard to case, so Acme-Corp and acme-corp are one customer — the same rule customer budgets use. The Customer column on Requests shows the ID exactly as it was sent.

To cap a customer's spend, see Per-customer budgets.

End users

Cova-User-Id takes letters, digits and _ - : ., up to 256 characters. A value with any other character is dropped. It also lets a rate limit count per user.

An end user is not a member of your organisation, and member budgets never use this header.

Properties

Cova-Property-<Name> attaches any label you choose. Send as many as you need.

  • Name: lowercased, hyphens become underscores, then only letters, digits and _ are allowed, up to 64 characters. A name that breaks the rule is dropped. Cova-Property-Deploy-Region is stored as deploy_region.
  • Value: cut at 256 characters.

Each property appears in Requests as a column, off by default — turn it on with Manage columns — and as a field in Filter. On Spend, the Property tab groups spend by the values of the property you pick.

Runs

Send Cova-Session-Id on every request of one agent run or workflow, with Cova-Session-Name and Cova-Session-Path if you want them. See Runs.

Actor

Cova-Actor is human, agent or unknown. Without it, the gateway infers agent when the request feeds a tool result back to the model, and unknown otherwise. Hover the Actor column to see whether a value was declared or inferred; filter on it with Actor and Actor source. The inference misses the first turn of every agent run, so send the header if you need the count to be right. Details are in Headers.

What you can trust

These headers are self-reported: the gateway records what your application sends. Anyone holding a key can send a different customer or user ID.

  • To pin a key to particular customers, scope it. A key scoped to one customer fills in Cova-Customer-Id itself.
  • Teams come from the key, never from Cova-Team-Id. The Team tab on Spend, team budgets, chargeback and who can see a request all use the team the key is assigned to. Cova-Team-Id is kept on the request as a property and changes none of them.
  • A property cannot impersonate these headers. Cova-Property-Cova-Customer-Id is stored as the property cova_customer_id and is not a customer ID; Cova-Property-cova_actor is dropped.

Keep IDs stable — an ID that changes splits one customer into two rows. Do not put secrets or personal data in a header value.

On this page