file_id in subsequent inference requests. This is the recommended path for any prompt that includes an image, document, or video — uploading once and referencing many times avoids hitting the 50 MB per-request body cap and lets you re-use the same asset across turns without re-encoding it.
Files are scoped to the Wafer user who owns the key — uploads made with one of your keys are usable by every other key on the same user account, matching the OpenAI and Anthropic Files API contract.
Endpoints
| Method | Path | Host | Auth |
|---|---|---|---|
POST | /v1/files | pass.wafer.ai | Authorization: Bearer <wfr_…> Serverless key |
GET | /v1/files | api.wafer.ai | Dashboard session (signed in at app.wafer.ai) |
GET | /v1/files/{file_id} | api.wafer.ai | Dashboard session |
DELETE | /v1/files/{file_id} | api.wafer.ai | Dashboard session |
wfr_… key is enough. Listing, inspecting, and deleting files are management actions and currently live on app.wafer.ai, behind your dashboard login. For most workflows you upload from code and manage in the UI.
Upload
The upload request body is the raw file bytes — not multipart. File metadata travels in headers:Authorization: Bearer <key>— your Serverless API key.Content-Type: <mime>— the file’s MIME type. Must be one of the allowed types for the declared purpose (see below).X-Wafer-Purpose: <purpose>— one ofvision,document, orvideo.
X-Wafer-Filename: <label>— a human-readable label. Shown in the dashboard’s file list.X-Wafer-Extraction-Fps: <fps>— video only (rejected on other purposes). Must be strictly positive. Defaults to1.0frame per second. There’s no upper cap, but the worker hard-stops at 3600 extracted frames, so a highfpsagainst a long clip simply truncates the tail.
Purposes and Allowed MIME Types
| Purpose | Allowed MIME types |
|---|---|
vision | image/jpeg, image/png, image/gif, image/webp |
document | application/pdf, text/plain |
video | video/mp4, video/quicktime, video/webm, video/x-matroska |
request_body_too_large (see Error Reference).
File Object
idalways starts withfile_followed by 32 hex characters (a UUID with the hyphens stripped). Use this string verbatim when referencing the file in inference requests.statusisreadyfor images and documents as soon as the upload completes. Video uploads returnpending/processingwhile server-side frame extraction runs. Onlyreadyfiles are usable in inference.expires_atis set on every file. Re-upload before that timestamp if you need to keep the file around longer.
Reference a File in a Chat Completion
Once a file isready, pass its file_id in a content block on POST /v1/chat/completions. Wafer resolves the file_id server-side and substitutes the file contents into the request before forwarding it to the backend.
Vision (image)
OpenAI-compatible shape on/v1/chat/completions:
/v1/messages:
Video
Video files are expanded server-side into a sequence of image frames before the inference call. Each frame is annotated withframe_index and timestamp_sec so the model can reason about temporal order.
fps(optional): subsample the pre-extracted frames at this rate. Must be> 0. Defaults to the extraction rate the file was uploaded with.max_frames(optional): cap the number of frames forwarded to the model. Use this to keep long videos under the model’s context window.
fps and max_frames accordingly. If you exceed the context window, the API returns context_length_exceeded with the limit and suggested_models.
List, Inspect, Delete (dashboard)
File management lives in the dashboard at app.wafer.ai. Use the UI to see your uploaded files, inspect status, and revoke files you no longer need. The underlying endpoints —GET /v1/files, GET /v1/files/{file_id}, DELETE /v1/files/{file_id} — live on api.wafer.ai and are guarded by your dashboard login session, so they are not intended to be called directly from CI or production code paths.
If you need to drop a file programmatically, delete it from the dashboard. We surface a single-key API for upload because that’s the path that has to happen from the same place inference happens; management is rarer and stays in the UI.
Errors (Upload)
The upload endpoint uses its own focused error envelope. Codes that customers actually encounter:400 invalid_purpose—X-Wafer-Purposewas missing or not one ofvision,document,video.400 missing_content_type—Content-Typeheader was empty.400 invalid_content_length—Content-Lengthwas missing, non-numeric, or negative.400 invalid_extraction_fps—X-Wafer-Extraction-Fpswas sent on a non-video purpose, was non-numeric, or was ≤ 0.400 init_rejected— wafer-api’s pre-flight rejected the upload (e.g. MIME doesn’t match the declared purpose). Themessagefield carries the upstream reason.403 files_require_user_key— the inference key isn’t user-scoped. Older non-user keys can serve inference but cannot own files; mint a new key from the dashboard.413 file_too_large— upload exceeded the 512 MB per-file limit (either viaContent-Lengthor counted at stream time).502 init_unavailable/storage_unavailable/storage_upload_rejected/complete_unavailable— transient failures in the upload pipeline. Retry.
file_id resolution surfaces its own codes (invalid_file_id, file_not_ready, file_expired, file_unavailable) on the chat completion response when the referenced file isn’t usable.
Notes
- File contents are inaccessible to other users — Wafer scopes every read to the owning user.
- Files uploaded against
pass.wafer.ai(US) are not automatically replicated topass-eu.wafer.ai. Upload separately if you use EU routing. - Inline
image_url.urldata URIs and remote HTTPS URLs are still accepted on chat completions for backwards compatibility, butfile_idis the recommended path for anything over a few hundred KB.