PII controls
Control whether raw prompt / response payloads are persisted, and who can read them.
Why this exists
By default TokenID stores the full request and response body of every captured API call so you can audit, replay, or debug them later. For customers passing user-generated content through their LLM calls — chat apps, customer support, document Q&A — that body can contain personally identifying information. This guide covers the two switches that let you decide what gets persisted.
store_payload — drop payloads at ingest
Per-organization boolean, default true.
When store_payload=true, every event's full request + response is written to the payload JSONB
column. When store_payload=false, payloads are set to NULL at ingest time — the data never
reaches storage, BigQuery replica, or backups.
Set it from the dashboard at Settings → Payload Storage, or programmatically:
PATCH /api/v1/settings/organization
{
"store_payload": false
}
After flipping, only metadata (model, provider, token counts, cost, timestamps, request_id, team_id, feature) is captured. Existing rows are not retroactively cleared — they will age out on the retention schedule.
include_payload — gate reads behind an explicit opt-in
Even when payloads are stored, all read endpoints exclude them from the response by default:
GET /api/v1/events/— payload field returnsnullunless?include_payload=trueGET /api/v1/events/{id}— sameGET /api/v1/events/export— same
Setting ?include_payload=true opts in for that one request. The exclusion-by-default behavior
means casual dashboard browsing, exports, and most observability tooling never see the raw content.
Trade-off worth knowing
When store_payload=false, the per-event audit envelope (organization_id, user_id, api_key_id,
ingested_at, audit_id) is also dropped — it lives inside payload._tokenid. Events ingested
with payload off will have token counts and cost, but cannot be attributed to a specific user or
API key. Choose accordingly.
Storage configuration endpoint
For data-residency requirements, point your org at a specific region and (optionally) override
the blob bucket and read-replica DSN used for payload storage. This is the second half of the
PII story: store_payload controls whether payloads are persisted; the storage-config
endpoint controls where.
/api/v1/org/{org_id}/storage-configPUT requires the admin role.
Fields
| Field | Type | Notes |
|---|---|---|
preferred_region |
string | AWS-style region slug. One of us-east-1, us-west-2, eu-west-1, eu-central-1, ap-southeast-1, ap-northeast-1, ca-central-1 |
blob_bucket_override |
string | null | Optional bucket name to receive payload blobs; max 255 chars |
db_replica_dsn_secret |
string | null | Write-only — encrypted at rest, never returned on reads |
data_residency_notes |
string | null | Free-text context (audit-friendly justification, ticket id, etc.) |
# read current
curl https://token.audit.id/api/v1/org/{org_id}/storage-config \
-H "Authorization: Bearer td_live_xxxx"
# pin to EU
curl -X PUT https://token.audit.id/api/v1/org/{org_id}/storage-config \
-H "Authorization: Bearer td_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"preferred_region": "eu-west-1",
"data_residency_notes": "GDPR — EU customer data must not leave EU."
}'
GET returns 404 until a config has been written for the org. Updates are upserts: the row is
created on first PUT and rewritten in place thereafter.