# Data policy

The marketplace sits between your application and model providers. We record
request metadata for billing and operations, and request and response content
from non-dedicated endpoints for debugging. Request logs are kept in a private,
encrypted storage bucket for up to 30 days. Dedicated endpoints and private
installations are excluded from request logging, including when a dedicated
endpoint falls back to a public model. An organization's request-log opt-out
also excludes its requests.

[Optimize](/docs/model-search) separately stores the eval cases and candidate
answers of a search, for your organization only, until you delete the search.
Provider retention policies are separate from the marketplace's policy and are
listed below.

## Request data

Request content is kept in the request log, separately from billing and analytics:

| Store | What it holds | Content? |
|---|---|---|
| Request log | Requests and responses from non-dedicated endpoints, with recognized credentials removed and size limits applied, for up to 30 days ([details](#request-logging)) | Yes |
| Process logs | request id, surface, model, outcome, HTTP status — every buyer-controlled string sanitized first | Never |
| Telemetry (analytics) | ids, org/key ids, provider, deployment, model, region, attempt ordinal, outcome, error code, statuses, timestamps, latency, five token counts, request/response *byte sizes*, cost, provider request id (house routes only; see below); the calling software's name, version and User-Agent header (keys and e-mail addresses removed); how the answer ended (finish reason); the output limit sent and whether the gateway set it; the number and types of tools (never their names or schemas); whether the request was cancelled before the first token; and the provider's error code with its message scrubbed of content (quoted text, names you chose, values, keys and addresses removed) | Never |
| Billing ledger | per-attempt row: the prices in force, reserved maximum, settled cost, token counts, HTTP status, error code, provider request id (house routes only; see below), timestamps, route and admission context | Never |
| Rendered pages | model directory, model pages, console, status — all render from metadata | Never |

Some details worth knowing:

- **Model names appear in process logs** (they are routing metadata).
  Buyer-controlled metadata strings in those logs are sanitized: control
  characters are stripped and length is capped. Request content is written
  separately as structured records in the request log.
- **Error bodies never echo your input.** Every error body is the gateway's
  own typed shape; a provider's raw error body is never relayed. When a refusal
  is translated across dialects or surfaced mid-stream, the gateway emits only
  the typed error class.
- **Telemetry records byte sizes, not bodies.** Telemetry keeps
  `request_bytes` and `response_bytes` so throughput is measurable without
  storing a single byte of what was said.
- **Image requests follow the same request-log policy.** On
  [`/v1/images/generations`](/docs/api-images), prompts, generated image content
  and any `revised_prompt` can appear in request logs, subject to the size limits
  below. They are not written to telemetry or the billing ledger.
- **Video creation requests follow the same request-log policy.** The prompt and
  creation response can appear in request logs. The video file streams from the
  provider when you download it and is not kept by the marketplace.
- **The playground keeps its chat history in your browser**: conversations in
  local storage and images in IndexedDB, filed by your sign-in, the conversation
  and the reply. Requests you send from the playground follow the request-log
  policy above. Deleting a chat, or **Clear all**, deletes the browser's copy;
  it does not delete a request log already recorded.
- **Playground decisions follow the same request-log policy.** Their state,
  questions, options and answers can appear in request logs. Telemetry and the
  billing ledger keep metadata such as model, provider, token counts and cost.
- **Authentication headers are excluded from request logs.** Recognized API-key
  formats and the provider credentials used by the request are removed before
  a record is written. The gateway authenticates API keys by comparing a SHA-256
  hash. See the redaction limits below.
- **The provider request id is kept on house routes only.** It is the reference
  number a provider gives one call, so a failed call can be traced with that
  provider. A house route runs on the marketplace's own provider account. A call
  through a provider credential you connect (BYOK) never keeps the id. A provider
  can put the API key into that header, so the gateway drops an id that contains
  the key it sent, or any 16 characters of the key in a row. It also drops an id
  longer than 256 characters.

> [!NOTE]
> For local development, setting
> `TM_UNSAFE_LOG_BODIES=1` prints request bodies to stdout for local debugging.
> The flag hard-refuses to activate outside `local`/`demo` regions — a
> production deployment that sets it gets a logged warning and no body logging.
> It never touches telemetry or the ledger in any region, and an image prompt
> never prints even under it.

Tests check that content stays out of process logs, telemetry and the billing
ledger, and that request logging respects endpoint exclusions, opt-outs,
credential redaction and size limits.

## What we do store

Running an account requires a small amount of real data:

| Data | Why | Form |
|---|---|---|
| Email address | Sign-in and billing receipts | Stored canonicalized (lowercased; gmail dots and `+tags` collapsed, `+tags` stripped elsewhere) so aliases share one account and promotional-credit eligibility |
| Members' emails | Organization membership and roles | Canonicalized the same way |
| API keys | Gateway authentication, and copying a key again from the console | SHA-256 hash plus the first 12 characters (so the console can show you *which* key); the gateway checks only the hash. Keys created since 17 October 2026 also keep an envelope-encrypted copy (AES-256-GCM, its key held outside the database), so an owner or admin of your organization can copy the key again; each copy is recorded. Disabling a key deletes its copy. An organization can ask us to turn copying off: its copies are then deleted and no new copy is kept |
| Legacy and operator-issued email-link tokens | Redeeming previously issued sign-in links | SHA-256 hash only, single use, 30-minute expiry |
| Clerk identity and session references | Connect verified sign-ins to the same marketplace account and support sign-out | Clerk issuer, user/session ids, verified canonical email, organization id and session timestamps |
| Authentication email delivery IDs | Prevent duplicate sends when the Clerk email relay is enabled | Message id, outcome and timestamp only; no email body, sign-in link or recipient in this table |
| Per-attempt metadata | Billing and the usage you read back | The ledger row described above |
| Provider credentials you connect (BYOK) | Routing through your own OpenAI, Anthropic, Azure or Bedrock account | Envelope-encrypted; never returned by any API or page. A Bedrock connection stores a role ARN, never AWS keys |
| Braintrust API key (Optimize) | Reading your evals | Encrypted; only its last four characters are ever shown |
| Optimize searches | Comparing models on your evals | The eval cases and the candidates' answers, scoped to your organization, deleted with the search |
| Video jobs | Following a render across reloads | Job id, model, length, shape, status and charge — never the prompt or the file |
| App attribution | Optional `HTTP-Referer` / `X-Title` headers you send | Stored as-is in telemetry — send them only if you want your app identified |
| Request log | Find and fix errors on non-dedicated endpoints | Requests and responses, recognized credentials removed, size-limited, encrypted, deleted after 30 days ([details](#request-logging)) |

The marketplace does not store passwords. Clerk handles passwords, email
verification and Google sign-in. Google sign-in requests
basic identity information (OpenID, email and profile); it does not request access
to Gmail, Drive or Calendar. The marketplace uses the verified email to find your
existing account, including accounts originally created through an email link.
Clerk processes authentication data under its
[privacy policy](https://clerk.com/legal/privacy).

Authentication emails can be delivered through Resend, including Clerk-generated
email links. The relay verifies the sender's signature and does not log or persist
the email body or sign-in link. Resend processes delivery data under its
[privacy policy](https://resend.com/legal/privacy-policy).

## Request logging

- **Which requests.** Model requests to non-dedicated endpoints, including chat,
  messages, responses, compaction, image generation, decisions, video creation and
  token counting. Dedicated endpoints are excluded even when a request is
  refused or falls back to a public model. Private installations and organizations
  that have opted out are also excluded.
- **What we store.** The request as the gateway received it, available upstream
  request and response details, and the response returned to the caller (JSON or
  streamed content). Also the request metadata above, selected client headers
  such as `User-Agent`, and your key's first 12 characters, which the console
  shows too. Records have a size limit, normally 2 MiB and up to 16 MiB for a
  configured program; large fields may be truncated. Logging is best effort, so
  not every request is guaranteed to have a complete record.
- **What is removed.** The `Authorization` and `x-api-key` headers, cookies, and
  headers outside the request log's allowlist. Before a record is written, the
  gateway removes keys in recognized formats (ours, OpenAI, Anthropic, AWS,
  Google, GitHub, Stripe, Slack and private keys) and the provider credential that
  the request used, including a credential you connect (BYOK). Each becomes
  `[REDACTED]`. Other secrets in your prompts can be stored as you sent them.
- **Where, and for how long.** In an encrypted storage bucket in our AWS account.
  The bucket is not public. The gateway can write records, but it cannot read
  them. Records are scheduled for deletion after 30 days.
- **Why.** To investigate errors and replay requests in tests so that we can fix
  their cause. We do not train models on these records, and we do not share them.
- **How to opt out.** Contact support to stop request logging for your
  organization. This does not change the provider's own retention policy or
  delete records already retained under the 30-day policy.

## Hackathons and similar programs

Requests from accounts in a hackathon or similar program are stored for up to 30
days to find and fix errors.

Program invitations retain their request-log notice. A program's logging mark
has an end date, but requests to non-dedicated endpoints may continue to be
logged under the general policy above after that date. Dedicated endpoints,
private installations and organization opt-outs remain excluded.

## Account authentication

Public signup and sign-in use Clerk in the browser at
[Sign up](https://dev.routerplus.com/signup) and [Sign in](https://dev.routerplus.com/login). Complete the
email-verification and authentication steps shown there. The local magic-link
submission and programmatic signup routes have been removed. Existing accounts
and API keys are preserved; Clerk connects a verified email to the same
marketplace account.

After Clerk verifies a sign-in, the marketplace issues its own seven-day signed
session cookie (`HttpOnly`). Marketplace **Sign out** revokes that cookie and the
linked Clerk session. Clerk-backed sessions are rechecked during authenticated
requests, using cached proof for at most 30 seconds. A revoked or expired Clerk
session can no longer authorize new marketplace requests after that cache expires.
Other devices stay signed in.

Beside the session cookie the browser holds a sign-in hint (`tm_in`, the same
expiry, readable by script) that says only "signed in", and a display cache
(`localStorage["tm-acct"]`: your email and your balance as the last page showed
them). They let every page draw your account menu and credits at once. Neither
opens anything, and both are cleared on sign out.

Previously issued marketplace email links and operator-issued links use stored
SHA-256 token hashes; a leaked database row is not a working link. These links
are single-use and expire. They do not provide a public account-creation route.

See [Authentication](/docs/authentication) for browser onboarding and API keys.

## What providers do with your prompts

The provider serving your request has its own retention policy, separate from
the marketplace's request logs. Every provider in the catalog must declare its
prompt retention in its manifest before it can serve traffic:

```json
{
  "provider": {
    "id": "anthropic",
    "privacy_policy_url": "https://www.anthropic.com/legal/privacy",
    "prompt_logging": "retained"
  }
}
```

`prompt_logging` is a closed enum — `"none"` or `"retained"` — and a manifest
without it (or without a privacy policy URL) fails conformance and never goes
live. The flag is surfaced where you make decisions:

- On every **model page**: the Data policy card links to this policy and says
  how many of the model's providers offer zero data retention. The providers
  table has a **Retention** column per provider; that describes the provider,
  not the marketplace's request log.
- In the machine-readable catalog, per provider of each model:

```bash
curl -s https://dev.routerplus.com/api/models.json | python3 -c \
  'import json,sys; [print(m["id"], "—", [(p["id"], p["prompt_logging"]) for p in m["providers"]]) for m in json.load(sys.stdin)["models"]]'
```

Every provider in the catalog today declares `"retained"`, per their published
policies, except Fastino, Cloudflare Workers AI, Perplexity, DeepInfra (its open models) and RouterPlus. Levanto, which serves the
decision model Sage, keeps no ordinary request, but keeps the full request of a
failed or slow one for 30 days to debug it, so it declares `"retained"` too.
Fastino, which serves the decision
model GLiNER-2.5-Decide, declares `"none"`. Fastino keeps an inference unless the
request says `store: false`, and the gateway sends `store: false` on every
request. Fastino's terms let it train on inputs unless a team has Zero Data
Retention on; our Fastino team has it on. So Fastino keeps nothing and trains on
nothing. Cloudflare Workers AI, which serves the decision models Clef and Clef-flash,
declares `"none"`, on Cloudflare's own statements. Of Clef, Cloudflare says: "we don't
read, store, or train on your requests or responses (unless you want to use our
fine-tuning product)". We do not use that product. Cloudflare's Workers AI data-usage
page says that Cloudflare does not use a customer's content to train any AI model on
Workers AI, or to improve any Cloudflare or third-party service, without the customer's
explicit consent. It also says that Cloudflare stores the content only if the customer
uses a Cloudflare storage service (R2 or KV, for example) with Workers AI. We use none.
The gateway calls the Workers AI REST API directly. It never sends Cloudflare's AI
Gateway header (`cf-aig-gateway-id`), so our requests do not go through AI Gateway,
whose logs are on by default and can hold the full prompt and response. Cloudflare's
replies to our calls carry none of AI Gateway's `cf-aig-*` headers.
Perplexity, which serves the decision model Perplexity Decider v1 27B, declares
`"none"`, on Perplexity's own statements. Its API FAQ says: "We do not retain any query
data sent through the API and do not train on any of your data." It also says that the API
has zero day retention of user prompt data by default, never used for AI training, and that
its compute is hosted on Amazon Web Services in North America. Perplexity keeps the usage
metadata it bills from, such as the number of requests and tokens (its API FAQ). The gateway
calls Perplexity's API directly, with our one Perplexity key.
DeepInfra, which serves fifteen open chat models (DeepSeek, GLM, Kimi, MiniMax, Hy4, Gemma, MiMo and gpt-oss),
declares `"none"`, on DeepInfra's own statements. Its data-privacy page says that it does
not store the data sent to its inference APIs on disk, holds it in memory only while it
runs the request, and does not log request content: it records only metadata such as the
request id, the cost and the sampling parameters. DeepInfra does not train on API data
(its exceptions are Google's and Anthropic's models, which this listing does not carry).
The gateway calls DeepInfra's OpenAI-compatible API directly, never its bulk inference API
(which may keep data longer).
Google's and Anthropic's models are DeepInfra's second listing, `deepinfra-labs`: Claude and Gemini, which DeepInfra
relays to Anthropic and Google under their own data and training policies. It declares
`"retained"`, as our Anthropic listing does, and is Claude's fallback after Anthropic direct.
Morph, which serves its Fast Apply models, Kimi K3 Fast and five open models, declares
`"retained"`: Morph publishes zero data retention only for self-hosted deployments, not for its
hosted API, which records requests for its traces dashboard. Its inference runs in the US, and
DeepSeek V4.1 Flash in Japan.
Mistral AI, which serves its own models (Mistral Large, Medium, Small, Ministral and Codestral)
and is GLM 5.3's last route, declares `"retained"`: Mistral keeps API prompts and answers for
30 days to monitor abuse, unless zero data retention is switched on for the account.
Bespoke Labs, which serves the decision models Bespoke Nimble v4 and v4 Max, declares
`"retained"`: Bespoke keeps API inputs, outputs and request logs for up to 30 days,
to debug the service and check for abuse, and then deletes them. It also keeps the
metadata it bills from (token counts, times, key id, status). Bespoke does not
train on API content unless an organization opts in, and ours does not.
OpenAI, which serves the decision model GPT-6 Luna Decisions (deployment
`openai-decisions`), declares `"retained"`: OpenAI keeps abuse-monitoring logs of
`/v1/decisions` requests for up to 30 days. Zero Data Retention needs an eligible account
and an agreement with OpenAI, and our organization does not have it. OpenAI does not train
on API data by default. The gateway calls OpenAI's API directly, with our one OpenAI key.

We report the flags; we do not editorialize them.

### RouterPlus

RouterPlus is our own decision-model service. It serves our models Decider 2B and Kev 4B,
and this page is its data policy. Its GPUs run in the United States.
The RouterPlus model service writes no request logs. It keeps a cache of its answers: each answer and its
usage, for 600 s (10 minutes). The cache key is the RouterPlus API key, the
model and the exact request body, byte for byte, so only an identical request gets a cached
answer. A cache entry is never shared across RouterPlus keys, but the gateway sends every
request with our one RouterPlus key: an identical request from any of our buyers within
600 s can get the cached answer, which repeats your option names. The cache is all it
keeps, so the listing declares `"none"`. RouterPlus
does not use your states, questions or answers for training. The marketplace side is the
same as for every provider: requests through non-dedicated endpoints follow the
request-log policy above.

## Reading your own metadata back

You can read your billing and usage metadata back with your API key:

```bash
curl -s -H "Authorization: Bearer $TM_API_KEY" https://dev-api.routerplus.com/v1/usage
curl -s -H "Authorization: Bearer $TM_API_KEY" "https://dev-api.routerplus.com/v1/generation?id=<request_id>"
```

Both endpoints read the billing ledger — balance, attempts, token counts,
settled cost. Neither returns message content.

> [!TIP]
> If you need to audit a specific request, keep the `x-request-id` response
> header from the original call — it is the lookup key for `/v1/generation`,
> and the id the marketplace will use if you write in about a billing dispute.

See [Authentication](/docs/authentication) for account and API-key access, and
[Errors](/docs/errors) for the error taxonomy referenced above.
