Data Export
Walk away with everything stored. Two surfaces: a per-project Data Export API for logs, metrics, usage, and execution audit, and a GDPR surface for personal-data export and account deletion. Downloads are NDJSON, the lifecycle is queue, poll, download, and the deletion path holds a grace window before the data goes.
- Max export window
90 daysWider ranges rejected with 400.- Download format
application/x-ndjsonAlways, regardless of requested format.- GDPR download window
30 daysPer-account export cadence is 24 hours.- Deletion grace
30 daysCancellable until the grace window expires.
Two export systems:
- Data Export API (
/exports/), Export request logs, aggregated metrics, and usage/billing data in CSV, JSON, or JSONL format. - GDPR Data Rights (
/gdpr/), Export all personal data or request account deletion with a configurable grace period.
Data Export API
The Data Export API supports project-scoped export of logs, metrics, usage, and execution-audit data. Logs, metrics, and usage exports are queued for background processing; execution exports are materialised synchronously on the create call.
All routes are mounted under /:project_id/v1/. Replace
:project_id with your project's external id (for example
proj_abc123). Authentication uses a project API key passed
as Authorization: Bearer ere_my-project_....
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /:project_id/v1/exports/logs | Queue a request-log export. Returns 202 with status pending. |
| POST | /:project_id/v1/exports/metrics | Queue an aggregated-metrics export. Returns 202 with status pending. |
| POST | /:project_id/v1/exports/usage | Queue a usage/billing export. Returns 202 with status pending. |
| POST | /:project_id/v1/exports/executions | Materialise an execution-audit NDJSON export synchronously. Returns 202 with status completed on success. |
| GET | /:project_id/v1/exports | List export jobs. Query params: limit (default 20, max 100), offset (default 0), status (optional filter). |
| GET | /:project_id/v1/exports/:id | Get export job status. |
| GET | /:project_id/v1/exports/:id/download | Download a completed export. The response is always application/x-ndjson served as export-<uuid>.ndjson. |
| DELETE | /:project_id/v1/exports/:id | Cancel a pending or processing export. The job transitions to status cancelled. |
Response Shape
Every endpoint that returns an export job uses the same DTO:
| Field | Type | Description |
|---|---|---|
id |
string (UUID) | Server-generated bare UUID. Subsequent status/download calls must use this exact value. |
export_type |
string | One of logs, metrics, usage, executions. |
format |
string | The requested format (recorded but only jsonl/NDJSON is materialised in-tree). |
status |
string | See Export Job Statuses. |
start_date / end_date |
string (ISO 8601) | The bounds the job was created with (echoed back as response fields even though the request uses since/until). |
filters |
object | Filter blob persisted verbatim. No typed schema is enforced at the router boundary. |
created_at / completed_at / failed_at |
string (ISO 8601), nullable | Lifecycle timestamps. |
error_message |
string, nullable | Populated when status is failed. |
download_url |
string, nullable | Canonical download path. Present once the job is completed. |
Export Types
All create-export bodies use since and until
(ISO 8601) for the export window. The legacy keys start_date
and end_date are not accepted on input and
will be rejected with a 400 invalid_request_error.
Logs Export
Export request-level logs with optional filtering:
POST /:project_id/v1/exports/logs
{
"since": "2026-01-01T00:00:00Z",
"until": "2026-01-31T23:59:59Z",
"format": "jsonl",
"filters": {
"endpoint_ids": ["endpoint-prod"],
"status_codes": [200, 429],
"model_name": "llama-3.1-8b",
"min_latency_ms": 100,
"max_latency_ms": 5000,
"region": "RegionOne"
}
}
Metrics Export
Export aggregated metrics:
POST /:project_id/v1/exports/metrics
{
"since": "2026-01-01T00:00:00Z",
"until": "2026-01-31T23:59:59Z",
"format": "jsonl"
}
Usage Export
Export usage and billing data:
POST /:project_id/v1/exports/usage
{
"since": "2026-01-01T00:00:00Z",
"until": "2026-01-31T23:59:59Z",
"format": "jsonl"
}
Executions Export
Export execution-audit rows as NDJSON. Unlike the other endpoints, this
one materialises the payload synchronously on the create call: the
response carries status completed (or failed)
and the download is immediately available. All body fields are optional;
an empty body or {} requests the default 24-hour window
ending at the current time.
POST /:project_id/v1/exports/executions
{
"since": "2026-01-01T00:00:00Z",
"until": "2026-01-31T23:59:59Z",
"format": "jsonl",
"filters": {}
}
Filter Options
Filters are persisted verbatim as a free-form JSON object and applied by the export worker. The keys below are the worker-recognised shape today; the router does not enforce a typed filter schema, so unknown keys are accepted and stored but may be ignored downstream.
| Filter | Type | Description |
|---|---|---|
endpoint_ids |
array of strings | Filter by endpoint slug(s). |
status_codes |
array of integers | Filter by HTTP response status codes. |
model_name |
string | Filter by model name. |
min_latency_ms |
integer | Minimum request latency in milliseconds. |
max_latency_ms |
integer | Maximum request latency in milliseconds. |
region |
string | Filter by region identifier. |
The maximum date range for any export is 90 days. Requests with a wider range are rejected with a 400 error.
Export Formats
| Format | Content Type | Description |
|---|---|---|
jsonl |
application/x-ndjson | One JSON object per line. The only format materialised in-tree today; recommended for all exports. |
json |
application/x-ndjson | Aspirational. Accepted by the create endpoints but the download always returns NDJSON. |
csv |
application/x-ndjson | Aspirational. Accepted by the create endpoints but the download always returns NDJSON. |
The download endpoint always returns
application/x-ndjson served as
export-<uuid>.ndjson, regardless of the
format recorded on the job. Content negotiation is not
supported and Accept-Encoding: gzip is ignored.
Only the executions export materialises its payload
synchronously on create. logs, metrics, and
usage jobs are persisted in the pending
state and remain queued until an out-of-tree worker picks them up.
Export Workflow
The general lifecycle for queued exports (logs, metrics, usage):
- Request, Submit an export request (
POST /:project_id/v1/exports/logs, etc.). The router responds with 202 Accepted and a job DTO whosestatusispending. - Poll, Check the job (
GET /:project_id/v1/exports/:id) untilstatusiscompletedorfailed. - Download, Fetch the NDJSON file (
GET /:project_id/v1/exports/:id/download).
The executions endpoint short-circuits steps 1 and 2: the
create call returns 202 with status: completed (or
failed) and the download is immediately available. The
id on every job is a bare UUID; the status and download
endpoints validate it as such and 404 on any other shape.
Export Job Statuses
| Status | Description |
|---|---|
pending |
Export is queued for processing. This is the initial status for logs, metrics, and usage jobs. |
processing |
Export is being generated by the worker. |
completed |
Export is ready for download. |
failed |
Export failed. Check error_message on the job DTO. |
cancelled |
Export was cancelled via DELETE /:project_id/v1/exports/:id before completion. |
Example Workflow
The examples below use proj_abc123 as a stand-in for the
project's external id. Replace it with your own.
# 1. Request an export (202 Accepted with status "pending")
curl -X POST https://api.erebine.ai/proj_abc123/v1/exports/logs \
-H "Authorization: Bearer ere_my-project_abc123" \
-H "Content-Type: application/json" \
-d '{
"since": "2026-01-01T00:00:00Z",
"until": "2026-01-31T23:59:59Z",
"format": "jsonl"
}'
# Response: {"id": "d3a1b2c4-5678-49ab-9cde-0123456789ab", "status": "pending", ...}
# 2. Poll for completion
curl https://api.erebine.ai/proj_abc123/v1/exports/d3a1b2c4-5678-49ab-9cde-0123456789ab \
-H "Authorization: Bearer ere_my-project_abc123"
# Response: {"id": "d3a1b2c4-...", "status": "completed", "download_url": "...", ...}
# 3. Download the NDJSON file (always application/x-ndjson)
curl -o export.ndjson \
https://api.erebine.ai/proj_abc123/v1/exports/d3a1b2c4-5678-49ab-9cde-0123456789ab/download \
-H "Authorization: Bearer ere_my-project_abc123"
import requests
import time
PROJECT_ID = "proj_abc123"
BASE = f"https://api.erebine.ai/{PROJECT_ID}/v1"
headers = {
"Authorization": "Bearer ere_my-project_abc123",
"Content-Type": "application/json"
}
# 1. Request an export
response = requests.post(
f"{BASE}/exports/logs",
headers=headers,
json={
"since": "2026-01-01T00:00:00Z",
"until": "2026-01-31T23:59:59Z",
"format": "jsonl"
}
)
response.raise_for_status() # 202 Accepted
export_id = response.json()["id"] # bare UUID
# 2. Poll for completion
while True:
status_resp = requests.get(f"{BASE}/exports/{export_id}", headers=headers)
status = status_resp.json()["status"]
if status == "completed":
break
if status in ("failed", "cancelled"):
raise Exception(f"Export {status}")
time.sleep(5)
# 3. Download the NDJSON payload
download = requests.get(f"{BASE}/exports/{export_id}/download", headers=headers)
download.raise_for_status()
with open("export.ndjson", "wb") as f:
f.write(download.content)
const PROJECT_ID = "proj_abc123";
const BASE = `https://api.erebine.ai/${PROJECT_ID}/v1`;
const headers = {
"Authorization": "Bearer ere_my-project_abc123",
"Content-Type": "application/json"
};
// 1. Request an export
const createResp = await fetch(
`${BASE}/exports/logs`,
{
method: "POST",
headers,
body: JSON.stringify({
since: "2026-01-01T00:00:00Z",
until: "2026-01-31T23:59:59Z",
format: "jsonl"
})
}
);
const { id: exportId } = await createResp.json(); // bare UUID
// 2. Poll for completion
let status;
do {
const statusResp = await fetch(`${BASE}/exports/${exportId}`, { headers });
const job = await statusResp.json();
status = job.status;
if (status === "failed" || status === "cancelled") {
throw new Error(`Export ${status}`);
}
if (status !== "completed") {
await new Promise(r => setTimeout(r, 5000));
}
} while (status !== "completed");
// 3. Download the NDJSON payload (always application/x-ndjson)
const download = await fetch(`${BASE}/exports/${exportId}/download`, { headers });
const ndjson = await download.text();
console.log(`Exported ${ndjson.split("\n").filter(Boolean).length} records`);
GDPR Data Rights
The GDPR endpoints allow you to export all personal data associated with your account or request account deletion.
GDPR Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /gdpr/export | Request a GDPR data export. |
| GET | /gdpr/exports | List your export requests (paginated). |
| GET | /gdpr/export/:exportId | Get export request status. |
| GET | /gdpr/export/:exportId/download | Download the export file. |
| DELETE | /gdpr/export/:exportId | Delete an export. |
| POST | /gdpr/export/:exportId/cancel | Cancel a pending export. |
Export Status Values
| Status | Description |
|---|---|
pending |
Export request created, processing not yet started. |
processing |
Export is being generated. |
completed |
Export is ready for download. |
failed |
Export failed or was cancelled. Check error_message for details. |
expired |
Export file has expired (download window has passed). |
deleted |
Export was manually deleted by the user. |
Generated in the background: POST /gdpr/export
queues the export and returns 202 Accepted with status processing.
Poll GET /gdpr/export/:exportId until the status is
completed, then download it, or failed, then read
error_message.
Cancelling a GDPR export via
POST /gdpr/export/:exportId/cancel terminates the job but
transitions it to failed, not cancelled.
Only the deletion lifecycle (below) uses a distinct
cancelled status.
Exported Data
A GDPR export includes the personal data associated with your account:
- Project information
- Model metadata
- Endpoint configurations
- API key metadata (not the key values themselves)
- Usage events
- Invoices
- Audit logs
- Chat, conversation, and inference message bodies
- Workspace memories, decisions, milestones, and relations
- Your uploaded file contents and feedback attachments -- the actual bytes, not just an inventory
-
Sign-up invitations you sent that are still on record: the invited
address as stored (lowercased, with any
+tagremoved) and when you sent it
The structured data is generated as JSON. When your account has stored
files, the export is delivered as a single .tar archive whose
data.json holds the structured records and whose
blobs/ directory holds the file contents, so one download
carries both the structured records and the file bytes. Accounts with no
stored files receive a plain JSON file. Exports are stored in object storage.
The download window is 30 days; the per-account export cadence is 24 hours by default; check with your deployment operator if you need different values.
Account Deletion
Account deletion is a two-step process with a grace period to prevent accidental data loss.
Deletion Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /gdpr/delete | Request account deletion. Emails a confirmation code to the account's address; a request while one is pending sends a new code. |
| GET | /gdpr/delete/:requestId | Get deletion request status. |
| POST | /gdpr/delete/:requestId/confirm | Confirm deletion using the confirmation token. Starts the grace period. |
| POST | /gdpr/delete/:requestId/cancel | Cancel deletion during the grace period. |
| GET | /gdpr/delete/preview | Preview what data would be deleted. |
Deletion Statuses
| Status | Description |
|---|---|
pending |
Request created, awaiting the emailed confirmation code. Nothing is deleted in this state. |
confirmed |
Token submitted; grace period is active. Cancellation is still possible. |
processing |
Grace period has elapsed; deletion is in progress. |
completed |
All project data has been permanently deleted. |
cancelled |
Deletion was cancelled during the grace period. |
failed |
Deletion encountered an error during processing. |
Deletion Process
- Preview (optional), Use
GET /gdpr/delete/previewto see a summary of what data would be removed before committing. - Request, Submit a deletion request (
POST /gdpr/delete). A confirmation code is emailed to the requesting account's own verified address, never one named in the request, and expires after 7 days. The response never carries the code. Requesting again while the request is pending sends a new code and the earlier one stops working. Without an email service the request is refused with503email_unavailable; with an unverified address,409email_unverified; if the email cannot be sent,502email_not_sent. - Confirm, Enter the code with Confirm on the Settings page, or submit it to
POST /gdpr/delete/:requestId/confirmwith the body{"confirmation_token": "CODE"}. Confirmation starts the grace period. Nothing is deleted until you confirm. - Grace period, The grace period is 30 days by default. You can cancel at any time during this window using
POST /gdpr/delete/:requestId/cancel. - Deletion, After the grace period expires, all account data is permanently deleted by a background job.
Before requesting deletion, use the preview endpoint to see exactly what data would be removed. Consider exporting your data first using the GDPR export feature.