# Veilfile: llms.txt Veilfile is private, ephemeral artifact hosting for AI agents. An agent uploads a file (screenshot, log bundle, HAR, doc) and gets back an unguessable, expiring URL. A sanctioned place to put artifacts instead of a public repo or pasting secrets into chat. Human developers create workspaces and issue API keys to their agents; agents call the API with a key, no human in the loop. Base URL: `https://veilfile.com` (replace with your deploy; local dev is `http://localhost:8000`). ## Quickstart 1. A human signs up in the Veilfile dashboard (email address required), clicks the verification link we email, then creates a workspace and issues an API key (`POST /api/v1/keys` or the dashboard). Key issuance is blocked until the email is verified. The key looks like `vlf_...` and is shown once. Store it as an env var, never in chat. 2. Upload via the REST API: `curl -X POST https://veilfile.com/api/v1/artifacts -H "Authorization: Bearer vlf_..." -F "file=@screenshot.png" -F "ttl_days=7"` → `{id, url, expires_at, size_bytes, secret_flags}` (plus `ttl_adjusted: true` whenever the applied TTL differs from what you sent: above-max values are clamped down, unparseable values fall back to the plan max, sub-1 values are clamped up to 1 day; plus a `warning` string only when `secret_flags` is non-empty). 3. Or connect the hosted MCP server at `POST https://veilfile.com/mcp` (JSON-RPC 2.0, `Authorization: Bearer vlf_...`) with tools `upload_artifact`, `create_upload_url`, `list_artifacts`, `revoke_artifact`. For files too large to pass through the model as base64, `create_upload_url` mints a one-time URL (single-use, 15 minutes) to PUT the raw bytes from your shell instead. ## Endpoints - `POST /api/v1/artifacts`: multipart upload (`file`, optional `ttl_days`); max 25 MiB; allowed types: png, jpg, jpeg, webp, gif, txt, md, log, json, har, pdf. - `GET /a/`: download; public, no auth (the 256-bit token is the auth); inline for viewable types, attachment otherwise; 404 when expired/revoked. Served with `Cache-Control: no-store` and `X-Robots-Tag: noindex, nofollow`: telling caches not to store the bytes and crawlers not to index them. - `GET /api/v1/artifacts`: list own artifacts, newest first (key auth). - `DELETE /api/v1/artifacts/`: revoke early (key auth). - `POST /mcp`: MCP server (key auth): `initialize`, `notifications/initialized`, `tools/list`, `tools/call`. - `/api/v1/keys`, `/api/v1/usage`, `/api/v1/billing/*`: dashboard session auth only. ## Key format All API keys start with `vlf_`. Pass as `Authorization: Bearer vlf_...`. Uploads are secret-scanned on arrival (flags returned, never blocking by default). Pass `on_secret=reject` per upload to reject flagged files with `400` (`secret_detected`) instead of storing them. Flagged responses include `secret_flag_locations` (`{flag: [{line, offset}]}`); AWS secret access keys are detected independently of key IDs. Limits: 100 uploads/hour/key; plan monthly caps (Free 100/mo, Team $4 2,000/mo, Scale $12 10,000/mo) counting successful uploads only (rejected 4xx uploads never consume quota); hard storage caps (Free 1 GB, Team 25 GB, Scale 100 GB). Over-cap uploads fail with 402. Errors are JSON `{"error": "", "code": ""}` for every failure including auth and throttling (`unauthorized`, `forbidden`, `rate_limited`, `file_type_not_allowed`, …); HTTP statuses are standard and `429`s carry `Retry-After`. ## TTL behavior - Omitting `ttl_days` gives the plan maximum, not something shorter. - Plan TTL maxima: Free 7 days, Team 90 days, Scale 365 days. - A `ttl_days` above the plan maximum is clamped down, never rejected (REST; the MCP tool requires a positive integer). The 201 response then includes `"ttl_adjusted": true`. Always read `expires_at` in the response; never trust the value you sent. ## secret_flags are advisory, not blocking A flagged upload IS stored and its link works. Blocking on secret-shaped content would break legitimate uploads like test fixtures, so the scan only warns: when `secret_flags` is non-empty, the upload response also carries a `warning` string telling you to ask the human whether to keep or revoke the upload before sharing the link. For never-host semantics, check `secret_flags` in the upload response and call `DELETE /api/v1/artifacts/` (or the `revoke_artifact` MCP tool) when it is non-empty. ## MCP upload encoding MCP uploads are base64: the request body is about a third larger than the file. The 25 MiB limit is enforced on the DECODED bytes, so a ~25 MiB file means a ~33 MiB request. ## Reporting abuse If a file on Veilfile violates the terms, report it at https://veilfile.com/report-abuse/ or email abuse@veilfile.com with the link and a short description. Reports of child sexual abuse material are prioritized above everything else and go to NCMEC (the National Center for Missing and Exploited Children), as federal law requires. ## Safety screening (SHA-256 blocklist) Every upload's SHA-256 is checked against a blocked list before anything is stored. `VEILFILE_SAFETY_MODE` can be `off`, `log`, or `enforce` (currently `off` and inert). When enforced, a blocked upload is refused with `400` `content_not_allowed` (deliberately bare, indistinguishable from a file-type rejection by design) and nothing is stored. Treat it as a policy rejection, not a client bug: do not retry the same bytes. ## MCP protocol version The server speaks MCP protocol version `2025-06-18` and also accepts `2024-11-05`. On `initialize` it answers with the version the client sent when it supports it, and falls back to `2025-06-18` for anything else. An unsupported version never errors. ## Key lifecycle Keys are issued with `POST /api/v1/keys` (dashboard or API). Rotate by issuing a new key and deleting the old one: `DELETE /api/v1/keys/` deactivates a key instantly (204), and the old key stops working at once. Revoking a key does NOT invalidate download links already issued (`/a/` links are public bearer tokens): to kill a link, revoke the artifact itself with `DELETE /api/v1/artifacts/` (or the `revoke_artifact` MCP tool). ## Usage and the storage meter `/api/v1/usage` accepts API-key or dashboard session auth and returns the plan's monthly upload count plus the live storage meter (bytes used against the hard storage cap). The dashboard shows the same meter. When an upload fails with 402 `storage_cap_reached`, have the human check the dashboard: delete old artifacts or upgrade the plan. Full reference: https://veilfile.com/docs/api/. Human-readable docs (quickstart, agent setup, how it works, API): https://veilfile.com/docs/.