Data and security
Where your files live, how long links last, how keys are stored, and who to tell about a leak.
Read as MarkdownWhat RiffAds stores, how long it keeps it, and how to keep your keys safe.
Where files live
- Outputs are copied into RiffAds storage (Cloudflare R2) when a job finishes. Only that copy is served.
- Provider links are never stored or returned.
- Every file sits under your workspace. The workspace comes from your key or connection, never from request input.
- Files are private. They are served only through short-lived signed links with
Cache-Control: private, no-store. No public URLs. - Finished outputs never expire.
Your files are never posted anywhere
No code path publishes to Meta, TikTok, YouTube or X. Files leave only when you or your agent fetch a signed link.
Link lifetimes
| Link | Lives for |
|---|---|
| Output link on REST, MCP and the CLI | 10 minutes (output_urls_expire_in_seconds: 600) |
| Upload PUT link | 5 minutes, one use |
Agent links are short because they end up in model transcripts.
Expired link is not a lost file
Read the generation again for a fresh link. A stale URL returns 403. Don't retry it.
urlisnulluntil the generation is finished. Branch on status, not on the URL.- If signing fails,
urlisnull, not an error. Read again.
What else is kept
| Thing | Kept |
|---|---|
| Generation records | Kept. Deleting a project does not delete its generations or outputs. |
| Content check record | A SHA-256 fingerprint of the input. Never the words. |
| Abandoned upload reservation | Cleared after 15 minutes. |
| Revoked API key | Disabled, never deleted, so history shows which key started which job. |
There is no self-service workspace deletion.
API keys
- Shown once. The database stores a hash. Nobody at RiffAds can recover it. Lost it? Revoke it and create another.
- Live only. No test keys, no sandbox. Every key can spend what its scopes allow.
- Never expire. Revoke to stop one.
- Made in the app. Owners and admins create and revoke keys at app.riffads.com/api-keys. No endpoint creates, lists or rotates keys, so an agent can't issue itself one.
- Name a workspace, not a person. Want per-person tracking? One key per person or system.
- No IP allowlist. The key is the whole credential.
Revoking works on the very next call. Work already running still finishes and is charged.
Keys belong on servers
Never put sk_live_... in browser code, mobile apps, public repos, CI logs or chat prompts. Whoever reads it can spend until it is revoked.
No CORS on the REST API
/api/v1 sends no CORS headers and has no OPTIONS handler. On purpose. Call it from a server, task runner, CI job or terminal. Never from a browser.
MCP is different: it allows CORS, because its token comes from an OAuth sign-in, not a secret key. Connect MCP.
CLI key file
riffads login saves ~/.riffads/config.json with mode 0600. RIFFADS_API_KEY in the environment wins over the file. riffads logout deletes the file only. The key still works until you revoke it. CLI setup.
Read-only access
- A key without the
generateorworkflowsscope can read and estimate, never start work. It is refused before anything is written. - A read-only MCP connection does not even see the spend tools.
Use read-only access for dashboards, reports and CI checks.
Tenancy
- REST: no workspace parameter or header. The workspace comes from the key.
- MCP: the token is a person, bound to one workspace. Checked again on every call.
- Another workspace's id and a missing id both return
not_found. Nobody can probe what exists.
What never leaves the server
- Provider names, model keys, prompts, signed URLs and stack traces never appear in an error.
- Your text is not stored by the content check. Only a fingerprint.
- Card numbers never reach RiffAds. Checkout runs on the payment provider's hosted page.
Report a problem
Leaked key: revoke it in the app first. It stops on the next call.
Privacy or security report: use the contact address in the Privacy Policy. Legal.