API

Quickstart

Create sample data, run a reviewed sample, and export results with raw HTTP calls to the Everyn API.

This quickstart takes you from an API key to a reviewed CSV export. You will create a small leads.csv, upload it as a durable dataset, define a reusable job spec, run a limited sample, inspect the outcome, and export only after review.

The API is raw HTTP. The TypeScript and Python examples below use fetch and requests; they are not SDK examples.

Workflow

StageExit condition
UploadThe dataset upload reaches completed and returns datasetId.
Job specThe reusable job spec is created with a validated outputSchema.
Sample runA limited run reaches succeeded or completed_with_flags.
ReviewOutputs match the schema and failures are understandable.
ExportA reviewed run creates a ready export and downloads CSV bytes.

Before you start

You need:

  • An Everyn API key with datasets:write, datasets:read, job_specs:write, job_specs:read, runs:write, runs:read, exports:write, and exports:read.
  • curl and jq for the canonical copy-paste path.
  • Optional: Node.js 18 or newer for the TypeScript fetch examples.
  • Optional: Python 3 with requests installed for the Python examples.

Create the sample CSV locally:

cat > leads.csv <<'CSV'
company,website,industry,employee_count,region,notes
Northstar Robotics,https://northstar.example,Manufacturing,420,North America,Looking for automated QA on production lines
Lumen Health,https://lumen.example,Healthcare,180,Europe,Expanding clinical operations across two countries
Atlas Freight,https://atlas.example,Logistics,760,North America,Interested in lane optimization and shipment visibility
CSV

Set shell variables for this terminal session. Do not put real API keys in .env files or source control.

export EVERYN_BASE_URL="https://api.geteveryn.com"
export EVERYN_API_KEY="sk-everyn-..."

The TypeScript and Python snippets assume the same environment variables are available in the process.

1. Check authentication

List runnable models before creating a job spec.

curl -sS "$EVERYN_BASE_URL/v1/models" \
  -H "Authorization: Bearer $EVERYN_API_KEY"

Successful responses include a data array of model records. If you receive 401 or 403, fix the key before continuing. See Authentication, API errors, and the Models API reference.

2. Upload the CSV dataset

Create a dataset upload with an idempotency key. Reuse the same key only when retrying the same request after a timeout.

UPLOAD_RESPONSE=$(curl -sS -X POST "$EVERYN_BASE_URL/v1/dataset-uploads" \
  -H "Authorization: Bearer $EVERYN_API_KEY" \
  -H "Idempotency-Key: upload-leads-001" \
  -F "sourceType=csv" \
  -F "sourceName=leads.csv" \
  -F 'metadata={"purpose":"quickstart"}' \
  -F "file=@./leads.csv;type=text/csv")

echo "$UPLOAD_RESPONSE" | jq
UPLOAD_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.id')

Expected successful upload response excerpt:

{
  "id": "upl_...",
  "status": "processing",
  "datasetId": null,
  "failure": null
}

Wait for intake to finish. This loop exits on completed, fails fast on failed or expired, and times out after about one minute.

DATASET_ID=""

for attempt in $(seq 1 30); do
  UPLOAD_RESPONSE=$(curl -sS "$EVERYN_BASE_URL/v1/dataset-uploads/$UPLOAD_ID" \
    -H "Authorization: Bearer $EVERYN_API_KEY")
  STATUS=$(echo "$UPLOAD_RESPONSE" | jq -r '.status')

  if [ "$STATUS" = "completed" ]; then
    DATASET_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.datasetId')
    break
  fi

  if [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "$UPLOAD_RESPONSE" | jq '.failure'
    exit 1
  fi

  sleep 2
done

if [ -z "$DATASET_ID" ]; then
  echo "Timed out waiting for dataset upload $UPLOAD_ID"
  exit 1
fi

echo "DATASET_ID=$DATASET_ID"

Expected completed upload excerpt:

{
  "id": "upl_...",
  "status": "completed",
  "datasetId": "ds_...",
  "failure": null
}

If the upload fails, inspect failure.code, failure.docsUrl, and failure.fieldErrors. See Dataset uploads and the Dataset Uploads API reference.

3. Create a job spec

A job spec is the reusable work contract for future runs. This example scores each company for fit against a target customer profile.

JOB_SPEC_RESPONSE=$(curl -sS -X POST "$EVERYN_BASE_URL/v1/job-specs" \
  -H "Authorization: Bearer $EVERYN_API_KEY" \
  -H "Idempotency-Key: job-lead-fit-001" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Lead fit scoring",
    "description": "Score leads against the target ICP.",
    "mode": "add_columns",
    "prompt": "Score each company for ICP fit. Return a score, reason, and confidence.",
    "model": "openai:gpt-5.4-mini",
    "outputSchema": {
      "columns": [
        {
          "name": "fit_score",
          "type": "integer",
          "description": "Score from 1 to 5.",
          "minimum": 1,
          "maximum": 5
        },
        {
          "name": "fit_reason",
          "type": "string",
          "description": "Concise explanation."
        },
        {
          "name": "confidence",
          "type": "number",
          "description": "Confidence from 0 to 1.",
          "minimum": 0,
          "maximum": 1
        }
      ]
    }
  }')

echo "$JOB_SPEC_RESPONSE" | jq
JOB_SPEC_ID=$(echo "$JOB_SPEC_RESPONSE" | jq -r '.id')

Expected response excerpt:

{
  "id": "js_...",
  "name": "Lead fit scoring",
  "currentVersionId": "jsv_...",
  "version": {
    "mode": "add_columns",
    "model": "openai:gpt-5.4-mini",
    "outputSchema": {
      "columns": [
        { "name": "fit_score" },
        { "name": "fit_reason" },
        { "name": "confidence" }
      ]
    }
  }
}

If model validation fails, pick a runnable model from /v1/models. See Job specs and the Job Specs API reference.

4. Create and start a sample run

Start with a limited run before approving broader spend. The limit scope keeps this sample bounded even when the dataset grows later.

RUN_RESPONSE=$(curl -sS -X POST "$EVERYN_BASE_URL/v1/runs" \
  -H "Authorization: Bearer $EVERYN_API_KEY" \
  -H "Idempotency-Key: run-preview-001" \
  -H "Content-Type: application/json" \
  --data "{
    \"datasetId\": \"$DATASET_ID\",
    \"jobSpecId\": \"$JOB_SPEC_ID\",
    \"scope\": { \"type\": \"limit\", \"count\": 3 }
  }")

echo "$RUN_RESPONSE" | jq
RUN_ID=$(echo "$RUN_RESPONSE" | jq -r '.id')

curl -sS -X POST "$EVERYN_BASE_URL/v1/runs/$RUN_ID/start" \
  -H "Authorization: Bearer $EVERYN_API_KEY" | jq

Expected run response excerpt:

{
  "id": "run_...",
  "state": "queued",
  "rowCounts": {
    "total": 3,
    "processed": 0,
    "failed": 0
  }
}

Repeating the start request for a queued or running run returns the existing run and must not submit duplicate runner work.

Wait for the sample run to reach a terminal state:

TERMINAL_STATE=""

for attempt in $(seq 1 60); do
  RUN_RESPONSE=$(curl -sS "$EVERYN_BASE_URL/v1/runs/$RUN_ID" \
    -H "Authorization: Bearer $EVERYN_API_KEY")
  STATE=$(echo "$RUN_RESPONSE" | jq -r '.state')

  case "$STATE" in
    succeeded|completed_with_flags|failed|canceled)
      TERMINAL_STATE="$STATE"
      break
      ;;
  esac

  sleep 2
done

if [ -z "$TERMINAL_STATE" ]; then
  echo "Timed out waiting for run $RUN_ID"
  exit 1
fi

echo "$RUN_RESPONSE" | jq '{id, state, rowCounts}'

Use succeeded as the clean path. Use completed_with_flags as the inspect-and-decide path. Treat failed and canceled as stop-and-debug states. See Runs and the Runs API reference.

5. Review before expanding scope

Inspect rows, events, outputs, failures, and resolved retry-lineage results:

curl -sS "$EVERYN_BASE_URL/v1/runs/$RUN_ID/rows?limit=50" \
  -H "Authorization: Bearer $EVERYN_API_KEY" | jq

curl -sS "$EVERYN_BASE_URL/v1/runs/$RUN_ID/events?type=row.failed" \
  -H "Authorization: Bearer $EVERYN_API_KEY" | jq

curl -sS "$EVERYN_BASE_URL/v1/runs/$RUN_ID/outputs" \
  -H "Authorization: Bearer $EVERYN_API_KEY" | jq

curl -sS "$EVERYN_BASE_URL/v1/runs/$RUN_ID/failures" \
  -H "Authorization: Bearer $EVERYN_API_KEY" | jq

curl -sS "$EVERYN_BASE_URL/v1/runs/$RUN_ID/resolved-results" \
  -H "Authorization: Bearer $EVERYN_API_KEY" | jq

Review checklist:

  • The run is terminal: succeeded or completed_with_flags.
  • rowCounts.processed matches the attempted sample size.
  • Generated fields match the outputSchema: fit_score, fit_reason, and confidence.
  • Any failed or flagged rows have understandable failure.code, failure.message, and failure.docsUrl.
  • The prompt, model, schema, and review criteria are good enough before you create a larger run.

Export only after this checklist passes.

6. Retry or revise

Retry unresolved rows from a terminal run when the same pinned job spec version is still correct:

RETRY_RESPONSE=$(curl -sS -X POST "$EVERYN_BASE_URL/v1/runs/$RUN_ID/retry" \
  -H "Authorization: Bearer $EVERYN_API_KEY" \
  -H "Idempotency-Key: retry-run-001")

echo "$RETRY_RESPONSE" | jq

Revise the job spec and run another limited sample when the prompt, model, mode, output schema, or review criteria need to change. Retry is for execution problems; revision is for product-contract problems.

7. Export reviewed results

Create a self-starting CSV export from the reviewed run.

EXPORT_RESPONSE=$(curl -sS -X POST "$EVERYN_BASE_URL/v1/runs/$RUN_ID/exports" \
  -H "Authorization: Bearer $EVERYN_API_KEY" \
  -H "Idempotency-Key: export-results-001" \
  -H "Content-Type: application/json" \
  --data '{ "type": "generated_outputs", "format": "csv", "fileName": "results.csv" }')

echo "$EXPORT_RESPONSE" | jq
EXPORT_ID=$(echo "$EXPORT_RESPONSE" | jq -r '.id')

Expected export response excerpt:

{
  "id": "exp_...",
  "status": "ready",
  "downloadReady": true,
  "downloadUrl": "/v1/exports/exp_.../download",
  "failure": null
}

If the export is not immediately ready, poll it before downloading:

for attempt in $(seq 1 30); do
  EXPORT_RESPONSE=$(curl -sS "$EVERYN_BASE_URL/v1/exports/$EXPORT_ID" \
    -H "Authorization: Bearer $EVERYN_API_KEY")
  STATUS=$(echo "$EXPORT_RESPONSE" | jq -r '.status')

  if [ "$STATUS" = "ready" ]; then
    break
  fi

  if [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "$EXPORT_RESPONSE" | jq '.failure'
    exit 1
  fi

  sleep 2
done

if [ "$STATUS" != "ready" ]; then
  echo "Timed out waiting for export $EXPORT_ID"
  exit 1
fi

curl -sS "$EVERYN_BASE_URL/v1/exports/$EXPORT_ID/download" \
  -H "Authorization: Bearer $EVERYN_API_KEY" \
  -o results.csv

See Exports API reference for export types and download behavior.

Troubleshooting

SymptomWhere to look
401 or 403Authentication and the key scopes on the machine key.
Duplicate create after a timeoutIdempotency and the original idempotency key.
CSV failed to processDataset uploads and the failure.docsUrl on the upload.
Job spec rejectedJob specs, /v1/models, and validation errors.
Run failed or rows failedRuns, API errors, and Runs API reference.
Lists stop after one pagePagination.

Next steps