Files
Files
Upload, list, fetch, and delete files scoped to your workspace.
The files endpoints store documents for reuse across chat requests. Files are scoped to the workspace that uploaded them; another workspace’s file id returns 404.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/files | Upload, multipart/form-data |
| GET | /v1/files | List the workspace’s files |
| GET | /v1/files/{id} | File metadata |
| GET | /v1/files/{id}/content | Download the bytes |
| DELETE | /v1/files/{id} | Delete |
Upload
curl --fail-with-body https://api.pre.dev/v1/files \
-H "Authorization: Bearer $PREDEV_API_KEY" \
-F "purpose=user_data" \
-F "file=@contract.pdf"import fs from 'node:fs';
import OpenAI from 'openai';
const client = new OpenAI({ baseURL: 'https://api.pre.dev/v1', apiKey: process.env.PREDEV_API_KEY! });
const file = await client.files.create({
file: fs.createReadStream('contract.pdf'),
purpose: 'user_data',
});
console.log(file.id);import os
from openai import OpenAI
client = OpenAI(base_url="https://api.pre.dev/v1", api_key=os.environ["PREDEV_API_KEY"])
with open("contract.pdf", "rb") as handle:
uploaded = client.files.create(file=handle, purpose="user_data")
print(uploaded.id)The upload takes the bytes in a file part and a purpose string (user_data for documents you will reference from chat messages) and returns the stored file object, including the id used in later requests.
List, fetch, download, delete
curl --fail-with-body "https://api.pre.dev/v1/files?limit=20" \
-H "Authorization: Bearer $PREDEV_API_KEY"
curl --fail-with-body "https://api.pre.dev/v1/files/$FILE_ID" \
-H "Authorization: Bearer $PREDEV_API_KEY"
curl --fail-with-body "https://api.pre.dev/v1/files/$FILE_ID/content" \
-H "Authorization: Bearer $PREDEV_API_KEY" -o file.bin
curl --fail-with-body -X DELETE "https://api.pre.dev/v1/files/$FILE_ID" \
-H "Authorization: Bearer $PREDEV_API_KEY"The list has only files this workspace uploaded through the gateway, newest first (order=asc for oldest first), 20 per page by default and at most 50 (limit). To page, pass last_id as after while has_more is true; after must be one of this workspace’s files, otherwise the call returns 404. purpose lists only files with that purpose. A page can hold fewer than limit files: a file whose read fails or takes more than 5 seconds is skipped, and a call that reaches 10 seconds leaves the rest for the next page. Skipped ids are in predev.skipped, which appears only when something was skipped; GET /v1/files/{id} fetches them.
Only files whose metadata says downloadable: true can be downloaded; a file you uploaded returns 400 from /content. In the SDKs these are client.files.list(), client.files.retrieve(id), client.files.content(id), and client.files.delete(id) (Node client.files.del(id) on older versions).
Use a file in a request
Reference the uploaded file from a chat message as a file content part, and add the file-parser plugin so models without native document input can read it. See multimodal.
curl --fail-with-body https://api.pre.dev/v1/files \ -H "Authorization: Bearer $PREDEV_API_KEY" \ -F "purpose=user_data" \ -F "file=@contract.pdf"import osfrom openai import OpenAIclient = OpenAI(base_url="https://api.pre.dev/v1", api_key=os.environ["PREDEV_API_KEY"])with open("contract.pdf", "rb") as handle: uploaded = client.files.create(file=handle, purpose="user_data")print(uploaded.id)const body = new FormData();body.set(file, "string")fetch("https://api.pre.dev/v1/files", { method: "POST", headers: { "Content-Type": "multipart/form-data" }, body})package mainimport ( "fmt" "net/http" "io/ioutil" "mime/multipart" "bytes")func main() { url := "https://api.pre.dev/v1/files" body := new(bytes.Buffer) mp := multipart.NewWriter(payload) mp.WriteField("file", `string`) req, _ := http.NewRequest("POST", url, body) req.Header.Add("Content-Type", "multipart/form-data") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := ioutil.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body))}import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.net.http.HttpResponse.BodyHandlers;import java.time.Duration;import java.net.http.HttpRequest.BodyPublishers;var body = BodyPublishers.ofByteArray(new byte[] { ... });HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build();HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() .uri(URI.create("https://api.pre.dev/v1/files")) .header("Content-Type", "multipart/form-data") .POST(body) .build();try { HttpResponse<String> response = client.send(requestBuilder.build(), BodyHandlers.ofString()); System.out.println("Status code: " + response.statusCode()); System.out.println("Response body: " + response.body());} catch (Exception e) { e.printStackTrace();}using System;using System.Net.Http;using System.Text;var body = new MultipartFormDataContent();var client = new HttpClient();var response = await client.PostAsync("https://api.pre.dev/v1/files", body);var responseBody = await response.Content.ReadAsStringAsync();use reqwest::{Result, Client};async fn main() -> Result<()> { let client = Client::new(); let url = "https://api.pre.dev/v1/files"; let res = client .post(url) .header("Content-Type", "multipart/form-data") .send() .await? .text() .await?; println!("{}", res); Ok(())}{ "id": "file-8Kz3pQ", "object": "file", "bytes": 1024000, "created_at": 1790500000, "filename": "contract.pdf", "purpose": "user_data"}{ "id": "file-8Kz3pQ", "type": "file", "filename": "contract.pdf", "mime_type": "application/pdf", "size_bytes": 1024000, "created_at": "2026-09-27T12:00:00Z", "downloadable": false}The workspace API key (pdk_…) from Integrations → Built-in in the pre.dev dashboard.
In: header
Request Body
multipart/form-data
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
The stored file.
TypeScript Definitions
Use the response body type in TypeScript.
File metadata. id and filename are always present. The other fields follow one of two styles: object: "file", bytes, purpose and a Unix created_at, or type: "file", size_bytes, mime_type, downloadable and an ISO created_at.
application/json
The file was rejected, for example an unsupported or empty file.
TypeScript Definitions
Use the response body type in TypeScript.
An error returned by the model for this request. The HTTP status is the model's own; code usually repeats it.
application/json
Missing or invalid API key.
TypeScript Definitions
Use the response body type in TypeScript.
An error raised by pre.dev, in the OpenAI error shape with an extra predev object (absent on catalog_unavailable from the catalog listings). Branch on error.code.
application/json
More than 30 failed key attempts from this IP address in the current minute.
TypeScript Definitions
Use the response body type in TypeScript.
An error raised by pre.dev, in the OpenAI error shape with an extra predev object (absent on catalog_unavailable from the catalog listings). Branch on error.code.
application/json
Unexpected error.
TypeScript Definitions
Use the response body type in TypeScript.
An error raised by pre.dev, in the OpenAI error shape with an extra predev object (absent on catalog_unavailable from the catalog listings). Branch on error.code.