docs
// API Reference

Files API

Upload once, reference by id within the file's workspace. JSONL for batch jobs, fine-tune corpora, prompt assets, all on the OpenAI /v1/files shape with two-tier storage, per-project isolation, workspace-scoped access, and tier-bound retention.

Endpoints

Files belong to a workspace of the project (see Workspace Scope). All paths are relative to your project base URL https://api.erebine.ai/proj_ABC123.

Method Path Description
POST /{project_id}/v1/files Upload a file
GET /{project_id}/v1/files List files
GET /{project_id}/v1/files/{file_id} Get file metadata
GET /{project_id}/v1/files/{file_id}/content Download file content
DELETE /{project_id}/v1/files/{file_id} Delete a file

Upload Files

POST /{project_id}/v1/files

Upload a file using multipart/form-data:

Field Type Description
filerequired binary File content. Maximum 500MB.
purposerequired string File purpose. See Supported Purposes.
relative_pathoptional string Relative path within an upload tree, forward-slash separated (e.g. "sub/data.jsonl"). Preserved on the row and echoed back as x_relative_path. Used for directory uploads.
curl
curl -X POST https://api.erebine.ai/proj_ABC123/v1/files \ -H "Authorization: Bearer ere_myproject_your_api_key" \ -F "file=@requests.jsonl" \ -F "purpose=batch"

Response

Returns HTTP 201 Created with the file object:

{ "id": "file-1a2b3c4d5e6f7890abcd1234", "object": "file", "purpose": "batch", "filename": "requests.jsonl", "bytes": 1048576, "status": "uploaded", "created_at": 1709000000, "expires_at": null, "x_relative_path": null }

File IDs follow the format file-<24 hex chars>. x_relative_path echoes the optional relative_path form field; it is null for flat uploads. See Status Lifecycle for the expires_at contract.

List Files

GET /{project_id}/v1/files

Returns a list of all files for the project. Supports filtering by purpose and limits up to 100 per page.

Query Parameters

Parameter Type Description
limitoptional integer Maximum files to return (1-100, default 20).
purposeoptional string Filter by purpose (e.g., "batch").
x_prefixoptional string Filter by relative_path prefix. Returns rows whose path equals the prefix or begins with "<prefix>/". Case-sensitive. Erebine extension.
curl
curl https://api.erebine.ai/proj_ABC123/v1/files \ -H "Authorization: Bearer ere_myproject_your_api_key"

Response

{ "object": "list", "data": [ { "id": "file-1a2b3c4d5e6f7890abcd1234", "object": "file", "purpose": "batch", "filename": "requests.jsonl", "bytes": 1048576, "status": "uploaded", "created_at": 1709000000, "expires_at": null, "x_relative_path": null } ], "has_more": false }

Get File Metadata

GET /{project_id}/v1/files/{file_id}

curl
curl https://api.erebine.ai/proj_ABC123/v1/files/file-1a2b3c4d5e6f7890abcd1234 \ -H "Authorization: Bearer ere_myproject_your_api_key"

Download File Content

GET /{project_id}/v1/files/{file_id}/content

Downloads the raw file content. The response Content-Type is application/jsonl for JSONL files.

curl
curl https://api.erebine.ai/proj_ABC123/v1/files/file-1a2b3c4d5e6f7890abcd1234/content \ -H "Authorization: Bearer ere_myproject_your_api_key" \ -o output.jsonl

Delete Files

DELETE /{project_id}/v1/files/{file_id}

Marks the file as deleted in the database and removes it from object storage on a best-effort basis. There is no active-batch reference check; callers are responsible for not deleting files that are still in use by a running batch.

curl
curl -X DELETE https://api.erebine.ai/proj_ABC123/v1/files/file-1a2b3c4d5e6f7890abcd1234 \ -H "Authorization: Bearer ere_myproject_your_api_key"

Response

Returns the full file object with status: "deleted". Erebine does not emit OpenAI's canonical {id, object, deleted: true} shape; match on status.

{ "id": "file-1a2b3c4d5e6f7890abcd1234", "object": "file", "purpose": "batch", "filename": "requests.jsonl", "bytes": 1048576, "status": "deleted", "created_at": 1709000000, "expires_at": null, "x_relative_path": null }

Workspace Scope

A file belongs to the workspace its upload request resolved to: the X-Workspace-Id header, else the only workspace of an API key confined to one, else the project's default workspace. A batch's output and error files belong to the batch's workspace. Listing, retrieving, downloading and deleting resolve the workspace the same way and reach only that workspace's files; a file in another workspace answers 404, exactly as a missing one does, and is left untouched. An input_image part that names a file by file_id, in a Responses request or a line of a batch, reaches the same files; any other file answers 400 Bad Request (image_file_not_found), exactly as an unknown id does.

  • An API key confined to some of the project's workspaces reaches only those. Naming another returns 403 Forbidden (workspace_not_allowed), and a key confined to several workspaces must name one. A key that belongs to a user reaches only workspaces that user can read.
  • In a project with no default workspace, a key that belongs to a user must name a workspace; a request that names none returns 403 Forbidden (workspace_required).
  • Files stored before files recorded their workspace belong to none. Only a key with no user behind it and no workspace list reaches them.

Supported Purposes

A single 500MB upload cap applies to every purpose; there are no per-purpose size limits.

Purpose Format Description
batch JSONL Input/output files for batch processing. Consumed by the Batch API.
assistants Various Accepted for OpenAI compatibility. Stored but not processed.
vision PNG, JPEG, GIF, WebP Images. Validated on upload, with metadata removed. A Responses input_image part names one by file_id.
user_data Various General-purpose files. An image (PNG, JPEG, GIF, WebP) is validated like a vision file, and an input_image part can name it by file_id; any other file is stored as uploaded.
fine-tune JSONL Accepted for OpenAI compatibility. Stored but not processed.

Note: Only batch purpose files are consumed by the batch processor, and only vision and user_data images by an input_image part. The other purposes are accepted for API compatibility and stored without further processing.

Status Lifecycle

Status Description
uploaded File has been uploaded and stored in object storage.
validated File content has been validated and is ready for use (e.g., JSONL parsing succeeded).
error File validation failed. Check the batch job's error details for specifics.
deleted File has been deleted (terminal state).

Files are validated when they are first used by a batch job. Allowed transitions are:

  • uploaded -> validated on successful validation.
  • uploaded -> error on validation failure (terminal).
  • validated -> deleted on explicit delete (terminal).
  • error -> deleted on explicit delete (terminal).

expires_at contract: reserved on the response envelope and always null today. Files do not expire automatically; they remain until you call DELETE.

CLI Commands

The erectl CLI provides file management commands:

Upload a file
erectl files upload --purpose batch requests.jsonl
List files
erectl files list
Get file info
erectl files get file-1a2b3c4d5e6f7890abcd1234
Download file content
erectl files download file-1a2b3c4d5e6f7890abcd1234 -o output.jsonl
Delete a file
erectl files delete file-1a2b3c4d5e6f7890abcd1234

Client Examples

Python (requests)

Python
import requests headers = {"Authorization": "Bearer ere_myproject_your_api_key"} base = "https://api.erebine.ai/proj_ABC123/v1" # Upload a file with open("requests.jsonl", "rb") as f: upload_resp = requests.post( f"{base}/files", headers=headers, files={"file": ("requests.jsonl", f)}, data={"purpose": "batch"} ) file_obj = upload_resp.json() print(f"Uploaded: {file_obj['id']}") # List files files = requests.get(f"{base}/files", headers=headers).json() for f in files["data"]: print(f"{f['id']} - {f['filename']} ({f['status']})") # Get file metadata meta = requests.get(f"{base}/files/{file_obj['id']}", headers=headers).json() print(f"File size: {meta['bytes']} bytes") # Download file content content = requests.get( f"{base}/files/{file_obj['id']}/content", headers=headers ) with open("output.jsonl", "wb") as out: out.write(content.content) # Delete a file requests.delete(f"{base}/files/{file_obj['id']}", headers=headers)

Node.js (fetch)

JavaScript
import { readFile, writeFile } from "node:fs/promises"; const base = "https://api.erebine.ai/proj_ABC123/v1"; const headers = { "Authorization": "Bearer ere_myproject_your_api_key" }; // Upload a file const fileData = await readFile("requests.jsonl"); const formData = new FormData(); formData.append("file", new Blob([fileData]), "requests.jsonl"); formData.append("purpose", "batch"); const uploadRes = await fetch(`${base}/files`, { method: "POST", headers: { "Authorization": headers.Authorization }, body: formData }); const fileObj = await uploadRes.json(); console.log(`Uploaded: ${fileObj.id}`); // List files const listRes = await fetch(`${base}/files`, { headers }); const files = await listRes.json(); files.data.forEach(f => console.log(`${f.id} - ${f.filename}`)); // Get file metadata const metaRes = await fetch(`${base}/files/${fileObj.id}`, { headers }); const meta = await metaRes.json(); console.log(`File size: ${meta.bytes} bytes`); // Download file content const contentRes = await fetch(`${base}/files/${fileObj.id}/content`, { headers }); const content = await contentRes.arrayBuffer(); await writeFile("output.jsonl", Buffer.from(content)); // Delete a file await fetch(`${base}/files/${fileObj.id}`, { method: "DELETE", headers });

Error Handling

HTTP Status Envelope type Description
400 invalid_request_error Missing file, missing or invalid purpose, malformed relative_path or x_prefix, or non-multipart body.
401 invalid_request_error Invalid or missing API key.
403 invalid_request_error The request names a workspace the API key may not use (workspace_not_allowed), or a key that belongs to a user names none in a project with no default workspace (workspace_required). See Workspace Scope.
404 invalid_request_error File not found, or not in the request's workspace.
413 invalid_request_error Upload body exceeds the 500MB maximum.
429 rate_limit_exceeded Too many requests. Check the Retry-After header.
500 internal_error Database write, object-storage upload/download, or status-update failures during upload, list, get, download, or delete.

OpenAI deviations: 401 emits type: invalid_request_error rather than the canonical authentication_error, and 404 carries no machine-readable code field. Match on HTTP status, not envelope type or code, when porting client error handlers.