API tags
Tags are optional key-value metadata labels that can be attached to API credentials and other secrets for categorization, filtering, and cost attribution.
Overview
API tags enable you to:
- Organize and categorize secrets (API keys, BYOK credentials, MCP tokens, and KEKs) by purpose, environment, team, or owner
- Filter and search your credential inventory using tag key-value pairs
- Attribute costs to specific applications, projects, cost centers, or business units
- Enforce governance through policies that require or restrict certain tags
- Track changes with audit logs that record tag modifications
Tags are stored as a map of key-value pairs, with both keys and values as strings. Each secret can have zero or more tags, and tag values are case-sensitive.
Supported resources
Tags are supported on Secrets across all realms:
| Realm | Purpose |
|---|---|
llm-providers | API keys for LLM providers (OpenAI, Anthropic, etc.) |
byok | Bring Your Own Key credentials |
mcp | Model Context Protocol OAuth tokens |
telemetry | OpenTelemetry export credentials |
kek | Key encryption keys (system-level) |
API operations
Create a secret with tags
Include a tags map in the request body when creating a secret:
curl -X POST https://api.example.com/v1/secrets \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "openai-prod-key",
"realm": "llm-providers",
"value": "sk-...",
"description": "OpenAI API key for production",
"tags": {
"app": "chatbot",
"environment": "production",
"cost-center": "engineering"
}
}'
Response:
{
"secret": {
"id": "sec_abc123...",
"name": "openai-prod-key",
"realm": "llm-providers",
"description": "OpenAI API key for production",
"tags": {
"app": "chatbot",
"environment": "production",
"cost-center": "engineering"
},
"createdAt": "2025-03-15T10:30:00Z",
"updatedAt": "2025-03-15T10:30:00Z",
"status": "SECRET_STATUS_ACTIVE"
}
}
Retrieve a secret with tags
Fetch a secret by name to view its tags:
curl -X GET https://api.example.com/v1/secrets/openai-prod-key \
-H "Authorization: Bearer $API_KEY"
The response includes the full tag set under the tags field.
List and filter secrets by tags
Query secrets using tag filters to retrieve only credentials matching specific criteria:
# Filter by a single tag key-value pair
curl -X GET "https://api.example.com/v1/secrets?tags.environment=production" \
-H "Authorization: Bearer $API_KEY"
# Filter by multiple tags (AND logic)
curl -X GET "https://api.example.com/v1/secrets?tags.environment=production&tags.app=chatbot" \
-H "Authorization: Bearer $API_KEY"
# Filter by realm and tags together
curl -X GET "https://api.example.com/v1/secrets?realm=llm-providers&tags.cost-center=engineering" \
-H "Authorization: Bearer $API_KEY"
Filtering uses AND logic: a secret matches only if all specified tag filters apply.
Update secret tags
Update a secret to modify its tags:
curl -X PATCH https://api.example.com/v1/secrets/openai-prod-key \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tags": {
"app": "chatbot",
"environment": "production",
"cost-center": "ai-operations",
"owner": "platform-team"
}
}'
All fields in the tags map replace the existing tags entirely (full replacement, not merge).
Rotate a secret (preserves tags)
When you rotate a secret, tags are preserved on the rotated version:
curl -X POST https://api.example.com/v1/secrets/openai-prod-key/rotate \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"newValue": "sk-..."}'
The rotated secret retains all tags from the previous version.
Delete a secret (removes tags)
When a secret is deleted, its associated tags are removed as well:
curl -X DELETE https://api.example.com/v1/secrets/openai-prod-key \
-H "Authorization: Bearer $API_KEY"
Use cases
Cost attribution and chargeback
Use tags to answer "What should this cost be booked against?" and enable team leads and finance to split spending reports by cost center, application, or business unit:
{
"tags": {
"cost-center": "engineering",
"app": "rag-pipeline",
"environment": "production"
}
}
When combined with cost reports, these tags enable you to answer questions such as:
- Which applications consumed the most tokens in production?
- What is the monthly spend per cost center?
- Which teams should be charged for this quarter's API usage?
Environment and realm organization
Separate credentials by deployment environment:
{
"tags": {
"environment": "production",
"region": "us-west-2",
"team": "platform"
}
}
Compliance and audit
Tag secrets with compliance-relevant metadata for audit and regulatory purposes:
{
"tags": {
"pci-applicable": "true",
"soc2-audit": "required",
"data-classification": "confidential"
}
}
Policy-enforced tags
Define policies that require certain tags or restrict tag values to a governed set. This ensures consistent tagging practices and defensible cost attribution:
- Require tags: A secret cannot be created or updated without certain required tags
- Restrict values: A tag value must be from an enumerated, policy-defined list (e.g.,
environmentmust be one ofdev,staging,production)
See Choose the right cost control for policy configuration details.
Tag design best practices
Use consistent naming conventions
Adopt standardized tag keys and values across your organization:
{
"environment": "production",
"cost-center": "engineering",
"owner": "platform-team",
"application": "chatbot"
}
Avoid inconsistently named keys (e.g., env vs environment, app vs application), which breaks filtering and analytics.
Keep tag values simple and enum-like
Restrict tag values to a small, known set of options when possible:
{
"environment": "dev|staging|production",
"team": "platform|data|infra|security",
"cost-center": "001|002|003"
}
Simple values are easier to filter, audit, and enforce in policies.
Limit the number of tags per secret
A reasonable limit is 5–10 tags per secret. Too many tags become unwieldy to manage and enforce.
Document your tag schema
Maintain a reference document or policy that describes:
- The tag keys your organization uses
- Allowed values for each key
- The purpose and use case for each tag
- Which tags are required vs optional
- Governance rules (e.g., cost-center is required for production credentials)
Use lowercase and hyphens for keys
Follow a consistent naming scheme for tag keys:
{
"environment": "production",
"cost-center": "engineering",
}
This avoids confusion from mixed case (e.g., CostCenter vs cost-center vs costCenter).
Audit logging
Changes to secret tags are recorded in the audit log. Each action—create, update, rotate, or delete—captures:
- What changed: Old and new tag values
- Who changed it: User ID and authenticated entity
- When: Timestamp
- Resource: Secret ID and name
- Context: Request ID, IP address, and other metadata
Use audit logs to:
- Verify tag governance compliance
- Investigate cost attribution disputes
- Track credential lifecycle and ownership changes
- Meet compliance and regulatory audit requirements
See Audit log events for the complete event reference.
Policy-based tag enforcement
The Admin Dashboard and policy engine can enforce tag governance by:
- Requiring tags before a secret can be created or updated
- Restricting values to a policy-defined enumeration
- Blocking creation or modification if required tags are missing or invalid
Example policy:
secretTags:
required:
- cost-center
- environment
allowedValues:
environment:
- dev
- staging
- production
cost-center:
- "001"
- "002"
- "003"
With this policy in place:
- Every secret must include both
cost-centerandenvironmenttags environmentmust be one ofdev,staging, orproductioncost-centermust be one of001,002, or003- Requests that violate the policy receive a 400 Bad Request error with details
See the Admin Dashboard documentation for policy configuration.
SDK examples
Go
import "github.com/tetrateio/agent-router/sdk/go/agentrouter/secret/v1"
// Create a secret with tags
resp, err := secretClient.CreateSecret(ctx, &secret.CreateSecretRequest{
Name: "openai-prod-key",
Realm: "llm-providers",
Value: "sk-...",
Description: "OpenAI API key for production",
Tags: map[string]string{
"app": "chatbot",
"environment": "production",
"cost-center": "engineering",
},
})
// List secrets filtered by tags
listResp, err := secretClient.ListSecrets(ctx, &secret.ListSecretsRequest{
Realm: "llm-providers",
Tags: map[string]string{
"environment": "production",
},
})
Python
from agent_router.secret.v1 import secret_pb2, secret_service_pb2
# Create a secret with tags
request = secret_service_pb2.CreateSecretRequest(
name="openai-prod-key",
realm="llm-providers",
value="sk-...",
description="OpenAI API key for production",
tags={
"app": "chatbot",
"environment": "production",
"cost-center": "engineering",
}
)
response = client.CreateSecret(request)
# List secrets filtered by tags
request = secret_service_pb2.ListSecretsRequest(
realm="llm-providers",
tags={
"environment": "production",
}
)
response = client.ListSecrets(request)
TypeScript
import { SecretServiceClient } from '@agent-router/sdk';
// Create a secret with tags
const response = await secretClient.createSecret({
name: "openai-prod-key",
realm: "llm-providers",
value: "sk-...",
description: "OpenAI API key for production",
tags: {
app: "chatbot",
environment: "production",
"cost-center": "engineering",
},
});
// List secrets filtered by tags
const listResponse = await secretClient.listSecrets({
realm: "llm-providers",
tags: {
environment: "production",
},
});
Related guides
- Know what every app and project costs — use tags for cost attribution and billing
- Secrets API reference — full Secret API documentation
- Audit log events — audit trail for tag changes
- Cost control and budgets — policy-based tag enforcement