Develop / Guides

Request tags (Preview)

How to label requests by matter, cost centre or team with X-Noirdoc-Tags, set per-tag budgets and model restrictions, and manage tags through /v1/tags.

Request tags let you attribute individual requests to a matter, cost centre, team or client of your application through the X-Noirdoc-Tags header – without issuing a separate API key for every matter. Each tag keeps its own usage counters and can carry its own euro budget, its own model and provider restrictions and its own Noirdoc Shield mode (shield_mode).

  1. Set up the default tag template or create tags in the portal

    Once enabled, admins of your organisation manage tags under Models → Tags.

    In the Default tag template section, you define how the gateway handles unknown tag names in the X-Noirdoc-Tags header:

    • Automatically create unknown tags on first use (default: turned on): when your application sends a new tag, the gateway creates it automatically on the first forwarded request and copies the budget, the model and provider restrictions and shield_mode from the template.
    • Automatic creation turned off: the gateway rejects unknown tags in the X-Noirdoc-Tags header with status code 403 and error code tag_not_found. Create valid tags in advance through New tag or with POST /v1/tags.

    Tag names follow these rules:

    • Format: 1 to 64 characters from a-z, A-Z, 0-9 and _, ., : and -, starting with a letter or digit (^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,63}$).
    • Reserved name: _default is reserved for the template endpoint /v1/tags/_default and cannot be used as a tag name.
    • Limit: each organisation can create up to 1,000 request tags (tag_limit_exceeded).

    Result: your organisation has a default tag template or pre-created tags.

  2. Set the budget, restrictions and Noirdoc Shield per tag

    For the Default tag template and for each individual tag, you can set the same guardrails as for an API key (see Budgets per key, Restrict models & providers and Set up Noirdoc Shield):

    • Spending limit (€) and Reset: Never, Daily (00:00 UTC), Weekly (Mondays at 00:00 UTC) or Monthly (on the 1st of the month at 00:00 UTC). Empty means no separate limit for this tag.
    • Noirdoc Shield (shield_mode): Inherit ("inherit", defers to headers and the organisation default), On ("on", turns Shield on for requests carrying this tag) or Off ("off", turns Shield off unless the organisation policy is enforced or the API key or another attached tag turns Shield on).
    • Allowed models: All models or Selected models only.
    • Provider restrictions: Data residency, Only providers without CLOUD Act exposure, Only §203-covered providers and a selection of allowed Providers.

    Result: under Models → Tags, the table shows the status (Active or Inactive), usage in the current period, total spend and the time of last use for each tag.

  3. Send X-Noirdoc-Tags with requests

    Pass 1 to 5 comma-separated tag names in the X-Noirdoc-Tags header. If the same tag appears more than once on a request, the gateway deduplicates it. Before forwarding the request to the provider, the gateway strips the header.

    GET /v1/models also evaluates X-Noirdoc-Tags and returns only models permitted for both the key and all named tags. Likewise, POST /v1/shield/inspect accepts X-Noirdoc-Tags for cost attribution and tag budget enforcement.

    Result: the gateway checks the budget and restrictions of the named tags and books the request to each tag after the response.

    Shell
    curl https://api.noirdoc.de/v1/chat/completions \
      -H "Authorization: Bearer $NOIRDOC_API_KEY" \
      -H "X-Noirdoc-Tags: mandat-2026-042,team-arbeitsrecht" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "qwen3.8-27b",
        "max_tokens": 500,
        "messages": [{"role": "user", "content": "Hello"}]
      }'
    Python
    import os
    from openai import OpenAI
    
    client = OpenAI(
        base_url="https://api.noirdoc.de/v1",
        api_key=os.environ["NOIRDOC_API_KEY"],
    )
    
    response = client.chat.completions.create(
        model="qwen3.8-27b",
        max_tokens=500,
        messages=[{"role": "user", "content": "Hello"}],
        extra_headers={
            "X-Noirdoc-Tags": "mandat-2026-042,team-arbeitsrecht",
        },
    )
    TypeScript
    import OpenAI from "openai";
    
    const client = new OpenAI({
      baseURL: "https://api.noirdoc.de/v1",
      apiKey: process.env.NOIRDOC_API_KEY,
    });
    
    const response = await client.chat.completions.create(
      {
        model: "qwen3.8-27b",
        max_tokens: 500,
        messages: [{ role: "user", content: "Hello" }],
      },
      {
        headers: {
          "X-Noirdoc-Tags": "mandat-2026-042,team-arbeitsrecht",
        },
      },
    );

Multiple tags and interaction with the key

When you send one or more tags in X-Noirdoc-Tags, the gateway combines the rules of the organisation, the API key and all named tags:

  • Allowed models and providers (intersection): a model and a provider are eligible only if they are permitted for the organisation (§ 203 StGB), for the calling API key and for every attached tag. If any tag excludes the model or all of its providers, the gateway answers with 403 model_not_allowed_for_tag or provider_not_allowed_for_tag.
  • Noirdoc Shield (shield_mode and precedence): whether Shield inspects a request follows the precedence order organisation enforced > API key shield_mode ("on" / "off") > request tag shield_mode > X-Noirdoc-Shield header > organisation default (default_on / default_off), see Policy and precedence. When multiple tags are sent in X-Noirdoc-Tags, any "on" among attached tags wins over "off"; "inherit" defers to the next level.
  • Order of budget checks: before forwarding the request, the gateway checks the organisation’s credit first (insufficient_credit), then the API key’s budget (key_budget_exhausted) and then the budgets of the tags in the order listed in X-Noirdoc-Tags. If a tag’s budget is used up or smaller than the request’s cost estimate, the gateway answers with 402 tag_budget_exhausted; message names the affected tag.
  • Full cost booked per tag: after the response or inspection, the gateway books the full cost of the request – priced models managed by Noirdoc as well as the Noirdoc Shield inspection fee (€0.40 per 1M inspected input tokens, including on POST /v1/shield/inspect and on BYOK routes when Shield is active) – both to the API key and to every tag named in X-Noirdoc-Tags. This lets you track independent dimensions – such as a matter budget (mandat-2026-042) and a department budget (team-arbeitsrecht) – on the same request. As with key budgets, requests through your own providers (BYOK) without active Shield count as €0.

Managing tags via the API (/v1/tags)

Alongside the interface under Models → Tags, you can manage tags and the default tag template through the /v1/tags endpoint – for example automatically when opening a new file in your practice management software.

API key permission

By default, an API key is not allowed to call /v1/tags (403 insufficient_key_permissions). Under Models → API keys, turn on Allow tag management (/v1/tags) when creating or editing the key.

Endpoints at a glance

Method and pathEffect
GET /v1/tagsLists the organisation’s tags (optionally with limit, offset and search filter q).
POST /v1/tagsCreates a new tag (201 Created). If the name already exists, the gateway answers with 409 tag_already_exists.
GET /v1/tags/_defaultReads the organisation’s default tag template (tag_auto_create_enabled, shield_mode, budget and restrictions).
PUT /v1/tags/_defaultUpdates the organisation’s default tag template.
GET /v1/tags/{name}Reads a single tag including shield_mode, current usage (budget_spent_eur), total spend (budget_spent_total_eur) and last_used_at.
PUT /v1/tags/{name}Creates the tag or replaces its settings; existing usage counters are preserved.
PATCH /v1/tags/{name}Updates individual fields of an existing tag; existing usage counters are preserved.
DELETE /v1/tags/{name}Deactivates an active tag or permanently deletes an already inactive tag without spend history (204 No Content).

When updating via PUT /v1/tags/{name} or PATCH /v1/tags/{name}, budget_spent_eur, budget_spent_total_eur and last_used_at remain unchanged.

DELETE /v1/tags/{name} works in two stages so that billing records are not lost:

  1. Active tag (is_active: true): the first DELETE call sets the tag to is_active: false (204 No Content). Subsequent requests carrying this tag receive 403 tag_disabled. You can reactivate the tag at any time via PATCH /v1/tags/{name} with {"is_active": true}.
  2. Already inactive tag (is_active: false): a second DELETE call permanently deletes the tag (204 No Content) only if no spend has been recorded on it (budget_spent_total_eur == 0). If spend has already been recorded, the gateway answers with 409 tag_has_spend_history.
Shell
curl -X PUT https://api.noirdoc.de/v1/tags/mandat-2026-042 \
  -H "Authorization: Bearer $NOIRDOC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Matter 2026/042 – Employment law",
    "budget_limit_eur": 25.0,
    "budget_reset": "monthly",
    "shield_mode": "on",
    "allowed_residencies": ["DE", "EU"],
    "require_no_cloud_act": true,
    "require_section203": true
  }'

Errors

Status Code Meaning
400 invalid_request_tags The X-Noirdoc-Tags header or the tag name in the path under /v1/tags is empty, contains more than 5 tags or does not match the format ^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,63}$.
402 tag_budget_exhausted The budget of a tag named in X-Noirdoc-Tags is used up for the current period or does not cover the estimated cost of the request; message names the tag.
403 request_tags_disabled The request sends X-Noirdoc-Tags or calls /v1/tags, but request tags (Preview) are not enabled for this organisation.
403 tag_not_found The named tag does not exist. On requests with X-Noirdoc-Tags, automatic tag creation is turned off (status code 403); on /v1/tags/{name}, the gateway answers with status code 404.
403 tag_disabled A tag named in X-Noirdoc-Tags is deactivated.
403 tag_limit_exceeded The organisation has reached the maximum of 1,000 request tags.
403 insufficient_key_permissions The API key lacks permission for /v1/tags (can_manage_tags) or /v1/shield/policy (can_manage_shield), a key pinned to shield_mode: on tries to weaken the Shield policy or a tag's shield_mode, or the tag requests broader models, providers or compliance rules than the calling key itself holds.
403 model_not_allowed_for_tag The model is not one of the allowed models of a tag named in X-Noirdoc-Tags.
403 provider_not_allowed_for_tag The restrictions of a tag named in X-Noirdoc-Tags (providers, data residency, CLOUD Act, § 203) exclude every provider of this model.
409 tag_already_exists A tag with this name already exists in the organisation.
409 tag_has_spend_history Spend has already been recorded for this tag, so it cannot be permanently deleted.