POST/ingestPush items
Send a batch of items (for example, conversations). Each item is a JSON object whose fields match your task config. We tell you the exact fields at setup.
curl -X POST "$BASE/ingest" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: batch-2026-08-12-001" \
-d '{
"project_id": "YOUR_PROJECT_ID",
"items": [
{ "case_id": "case_001", "scenario": "patient message...", "prediction": "Routine" },
{ "case_id": "case_002", "scenario": "patient message...", "prediction": "Urgent" }
]
}'Idempotency
Send an Idempotency-Key header with each batch. If a request times out and you retry with the same key, we recognise it and skip the insert, so a retry never creates duplicates. A repeated key returns:
{ "ok": true, "message": "Batch already ingested (idempotent)." }Use a fresh key per distinct batch. Without a key, each call appends its items, so two identical calls would create duplicates.
Response
{ "ok": true, "message": "Ingested 2 items." }Bulk (data in your storage)
For large volumes, don’t push the data through the API at all. Leave it in your storage (e.g. S3) and send a manifest_url instead of items. A manifest is a JSONL file where each line is one item.
curl -s -X POST "$BASE/ingest" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"project_id": "...",
"source": { "manifest_url": "https://your-bucket.s3.../manifest.jsonl", "sample": 1000 }
}'The data itself never passes through the API and never leaves your storage — it is read directly from your bucket, so any volume works. Poll results as usual.
source.mode picks what gets reviewed. "sample" (default) reviews a representative random sample (default 1000) — best for evaluating a model’s quality without labeling everything. "all" reviews every item — best for labeling a full dataset; for very large sets we agree a volume and cadence up front.
"source": { "manifest_url": "https://your-bucket.s3.../manifest.jsonl", "mode": "all" }