Skip to main content
POST
/
api
/
v1
/
runs
Start Run
curl --request POST \
  --url https://api.example.com/api/v1/runs
Start a new test run to evaluate an AI agent.

Request

POST /api/v1/runs
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Body Parameters

ParameterTypeRequiredDescription
agent_idstringYesUUID of the agent to test
test_suite_idstringNoUUID of the test suite. If not provided, uses the default suite
namestringNoCustom name for this run
test_modestringNodemo (20 scenarios) or full (all scenarios). Default: demo
max_scenariosnumberNoLimit number of scenarios to run
max_turnsnumberNoMax conversation turns per scenario. Default: 4

Response

FieldTypeDescription
idstringUUID of the created run
test_run_idstringHuman-readable run ID (e.g., TR-00042)
statusstringInitial run status (pending or running)
total_scenariosnumberNumber of scenarios to run
poll_urlstringURL to poll for status updates

Examples

curl -X POST https://app.preclinical.dev/api/v1/runs \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "550e8400-e29b-41d4-a716-446655440000",
    "test_mode": "demo",
    "max_turns": 5
  }'

Success Response (201)

{
  "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "test_run_id": "TR-00042",
  "status": "running",
  "total_scenarios": 20,
  "poll_url": "/api/v1/runs/7c9e6679-7425-40de-944b-e07fc1f90ae7"
}

Error Response (400)

{
  "error": "Agent not found or does not belong to your organization",
  "code": "AGENT_NOT_FOUND",
  "details": {
    "agent_id": "invalid-uuid"
  }
}

Errors

CodeDescription
MISSING_REQUIRED_FIELDagent_id is required
AGENT_NOT_FOUNDAgent not found or doesn’t belong to your organization
INVALID_FIELD_VALUEInvalid value for test_mode or other field
RATE_LIMITEDToo many concurrent runs

Polling for Results

After starting a run, poll the status endpoint until the run completes:
async function waitForCompletion(runId) {
  const maxWaitMs = 300000; // 5 minutes
  const pollInterval = 5000; // 5 seconds
  const startTime = Date.now();

  while (Date.now() - startTime < maxWaitMs) {
    const response = await fetch(`https://app.preclinical.dev/api/v1/runs/${runId}`, {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    });

    const run = await response.json();
    console.log(`Status: ${run.status}, Pass rate: ${run.pass_rate}%`);

    if (['completed', 'failed', 'canceled'].includes(run.status)) {
      return run;
    }

    await new Promise(resolve => setTimeout(resolve, pollInterval));
  }

  throw new Error('Timeout waiting for run completion');
}

// Usage
const run = await startRun(agentId);
const result = await waitForCompletion(run.id);
console.log(`Final pass rate: ${result.pass_rate}%`);

Using Webhooks

Instead of polling, configure a webhook to receive a notification when runs complete:
// Your webhook endpoint receives:
{
  "event": "test_run_completed",
  "test_run": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "status": "completed",
    "pass_rate": 85.0,
    // ... full run details
  }
}

Test Modes

ModeScenariosUse Case
demo20Quick validation during development
fullAllComprehensive testing before deployment
Use demo mode for rapid iteration during development, then run full tests before releases.