> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enkryptai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Submit your first red team run and read the vulnerability report

This walks through one complete red team run: submit, track, and read the results.

For target configuration across different providers, see the
[GET Defaults API response](/api-reference/models-api-reference/endpoint/get-defaults)
and [Testing Models Across Providers](/get-started/RedTeam_Models).

## Install required libraries

```bash Shell theme={"system"}
pip install requests python-dotenv enkryptai-sdk
```

## Set up your credentials

Sign up on the [dashboard](https://app.enkryptai.com/) and create an API key.

Export the keys as environment variables:

```bash Shell theme={"system"}
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
export ENKRYPTAI_API_KEY="YOUR_ENKRYPTAI_API_KEY"
```

## Step 1 — Submit a run

The payload has three parts: the `target` to test, the `risk_categories` to test for
(with the attacks to use), and an optional `context` describing your system.

```python Python theme={"system"}
import json
import os
import requests

url = "https://api.enkryptai.com/rt/redteam"

payload = {
    "run_name": "quickstart-run",
    "target": {
        "endpoint": "https://api.openai.com/v1/chat/completions",
        "api_key": os.getenv("OPENAI_API_KEY"),
        "model_name": "gpt-4o-mini",
        "provider": "openai",
        "system_type": "foundation_model",
    },
    "risk_categories": {
        "safety_harm": {"attack_config": {"basic": {}}},
        "bias_fairness_ethical_harm": {"attack_config": {"basic": {}}},
        "security_fraud": {"attack_config": {"basic": {}, "encoding": {}}},
    },
    "context": {
        "system_description": "A general-purpose customer support assistant.",
        "policy_description": "Never produce content that is illegal, harmful, or violates the rights of others.",
    },
    "generation_config": {"max_prompts": 30},
    "comprehensiveness": "Standard",
}

headers = {
    "Content-Type": "application/json",
    "apikey": os.getenv("ENKRYPTAI_API_KEY"),
}

response = requests.post(url, headers=headers, data=json.dumps(payload))
run = response.json()

print(json.dumps(run, indent=2))
run_id = run["run_id"]
```

```shell cURL theme={"system"}
curl -X POST 'https://api.enkryptai.com/rt/redteam' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -H "apikey: $ENKRYPTAI_API_KEY" \
  -d '{
    "run_name": "quickstart-run",
    "target": {
        "endpoint": "https://api.openai.com/v1/chat/completions",
        "api_key": "YOUR_OPENAI_API_KEY",
        "model_name": "gpt-4o-mini",
        "provider": "openai",
        "system_type": "foundation_model"
    },
    "risk_categories": {
        "safety_harm": { "attack_config": { "basic": {} } },
        "bias_fairness_ethical_harm": { "attack_config": { "basic": {} } },
        "security_fraud": { "attack_config": { "basic": {}, "encoding": {} } }
    },
    "context": {
        "system_description": "A general-purpose customer support assistant.",
        "policy_description": "Never produce content that is illegal, harmful, or violates the rights of others."
    },
    "generation_config": { "max_prompts": 30 },
    "comprehensiveness": "Standard"
}'
```

```python Python SDK theme={"system"}
import os
from enkryptai_sdk import RedTeamClient
from dotenv import load_dotenv

load_dotenv()

ENKRYPT_API_KEY = os.getenv("ENKRYPTAI_API_KEY")
ENKRYPT_BASE_URL = os.getenv("ENKRYPTAI_BASE_URL") or "https://api.enkryptai.com/"

redteam_client = RedTeamClient(api_key=ENKRYPT_API_KEY, base_url=ENKRYPT_BASE_URL)

config = {
    "run_name": "quickstart-run",
    "target": {
        "endpoint": "https://api.openai.com/v1/chat/completions",
        "api_key": os.getenv("OPENAI_API_KEY"),
        "model_name": "gpt-4o-mini",
        "provider": "openai",
        "system_type": "foundation_model",
    },
    "risk_categories": {
        "safety_harm": {"attack_config": {"basic": {}}},
        "bias_fairness_ethical_harm": {"attack_config": {"basic": {}}},
        "security_fraud": {"attack_config": {"basic": {}, "encoding": {}}},
    },
    "context": {
        "system_description": "A general-purpose customer support assistant.",
        "policy_description": "Never produce content that is illegal, harmful, or violates the rights of others.",
    },
    "generation_config": {"max_prompts": 30},
    "comprehensiveness": "Standard",
}

run = redteam_client.run_redteam(config=config)

print(run.to_dict())
run_id = run.run_id
```

The response is `202 Accepted`. Nothing has run yet — you have a handle to a queued job:

```json JSON theme={"system"}
{
  "run_id": "6c3babbe-3bc4-4553-a0b7-454df720579f",
  "status": "queued",
  "status_url": "/v1/runs/6c3babbe-3bc4-4553-a0b7-454df720579f",
  "results_url": "/v1/runs/6c3babbe-3bc4-4553-a0b7-454df720579f/results",
  "websocket_url": "/v1/runs/6c3babbe-3bc4-4553-a0b7-454df720579f/stream",
  "estimated_duration_seconds": null
}
```

> [!NOTE]
>
> The `status_url`, `results_url` and `websocket_url` values are returned as upstream
> `/v1/...` paths. Call them on the public API under the `/rt/` prefix — for example
> `GET https://api.enkryptai.com/rt/runs/{run_id}`.

## Step 2 — Track the run

Poll `GET /rt/runs/{run_id}` until it reports a terminal state. Its `status` values are
**lowercase**: `queued`, `running`, `paused`, `completed`, `failed`, `cancelled`. The
terminal three are `completed`, `failed` and `cancelled` — `paused` is not terminal, and a
paused run resumes.

```python Python theme={"system"}
import time

status_url = f"https://api.enkryptai.com/rt/runs/%7Brun_id%7D"

while True:
    status = requests.get(status_url, headers=headers).json()
    print(status["status"])
    if status["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(30)
```

```shell cURL theme={"system"}
curl -X GET "https://api.enkryptai.com/rt/runs/$RUN_ID" \
  -H "apikey: $ENKRYPTAI_API_KEY"
```

```python Python SDK theme={"system"}
# get_run() parses the response and normalises the two vocabularies below into
# one, so `state` and `is_terminal` work whichever endpoint the status came from
status = redteam_client.wait_for_run(run_id=run_id, poll_interval=30)

print(status.state)        # "finished" for a run the endpoint calls "completed"
print(status.is_terminal)  # True
```

```json JSON theme={"system"}
{
  "id": "6c3babbe-3bc4-4553-a0b7-454df720579f",
  "status": "running",
  "started_at": "2026-01-15T10:30:00Z",
  "completed_at": null
}
```

On failure, the `error` object carries the reason.

> [!WARNING]
>
> **One run, two status vocabularies.** Which one you get depends on the endpoint you asked,
> because they read different tables:
>
> | Endpoint | Vocabulary | Values |
> | - | - | - |
> | `GET /rt/runs/{run_id}` | The **run record** — lowercase | `queued`, `running`, `paused`, `completed`, `failed`, `cancelled` |
> | `GET /rt/runs/{run_id}/results` | The **red-team stage** — capitalised | `Queued`, `Running`, `Finished`, `Failed` |
> | `GET /rt/runs/{run_id}/records` | The **red-team stage** — capitalised | `Queued`, `Running`, `Finished`, `Failed` |
>
> A finished run therefore reports `"completed"` on the status endpoint and `"Finished"` on
> the results and records endpoints. This is deliberate, not a bug: the two are different
> pieces of state that happen to share a field name, and collapsing them is what once made
> every completed run's results unreachable. Match against the vocabulary of the endpoint you
> called — a poll loop waiting for `"Finished"` on `GET /rt/runs/{run_id}` never exits.
>
> The Python SDK papers over the difference for you: `RTRunStatus.state` folds `completed`
> onto `finished`, and `is_terminal` is true for either.

> [!TIP]
>
> Prefer not to poll? `GET /rt/runs/{run_id}/stream` delivers live progress events for the
> same run. See [Stream Run Events](/api-reference/redteam-v2-api-reference/endpoint/stream-run-events).

## Step 3 — Read the results

```python Python theme={"system"}
results = requests.get(
    f"https://api.enkryptai.com/rt/runs/%7Brun_id%7D/results", headers=headers
).json()

print(json.dumps(results, indent=2))
```

```shell cURL theme={"system"}
curl -X GET "https://api.enkryptai.com/rt/runs/$RUN_ID/results" \
  -H "apikey: $ENKRYPTAI_API_KEY"
```

```python Python SDK theme={"system"}
results = redteam_client.get_run_results(run_id=run_id)

print(results.to_dict())
```

Results are scored as **attack success rate (ASR)** — the percentage of adversarial
prompts that got through. Lower is better.

```json JSON theme={"system"}
{
  "run_id": "6c3babbe-3bc4-4553-a0b7-454df720579f",
  "status": "Finished",
  "completed_at": "2026-01-15T10:45:00Z",
  "records_url": "/v1/runs/6c3babbe-3bc4-4553-a0b7-454df720579f/records",
  "summary": {
    "overall_asr": 12.5,
    "total_attempts": 30,
    "coverage": 1.0,
    "categories": {
      "safety_harm": {
        "asr": 8.0,
        "sub_categories": {
          "cbrn": { "asr": 0.0, "count": 5 },
          "harmful_instructions": { "asr": 20.0, "count": 5 }
        },
        "by_attack_method": {
          "basic": { "asr": 8.0 }
        },
        "by_source": {
          "standard_library": { "asr": 8.0, "count": 10 }
        }
      }
    }
  }
}
```

`overall_asr` and every `asr` are percentages from 0 to 100. `coverage` reports the
fraction of the requested scope that actually ran.

## Step 4 — Drill into individual results

The summary tells you *what* failed. The records tell you *how*.

```python Python theme={"system"}
records = requests.get(
    f"https://api.enkryptai.com/rt/runs/%7Brun_id%7D/records", headers=headers
).json()

for row in records["records"][:5]:
    print(row["category"], row["sub_category"], row["test_type"], row["success"])
```

```shell cURL theme={"system"}
curl -X GET "https://api.enkryptai.com/rt/runs/$RUN_ID/records" \
  -H "apikey: $ENKRYPTAI_API_KEY"
```

```python Python SDK theme={"system"}
records = redteam_client.get_run_records(run_id=run_id)

print(records.to_dict())
```

Each record carries the prompt sent, the response received, the judge's verdict and its
reasoning:

```json JSON theme={"system"}
{
  "run_id": "6c3babbe-3bc4-4553-a0b7-454df720579f",
  "status": "Finished",
  "completed_at": "2026-01-15T10:45:00Z",
  "records": [
    {
      "query": "<the adversarial prompt sent to your target>",
      "response": "<your target's reply>",
      "test_type": "basic",
      "category": "safety_harm",
      "sub_category": "harmful_instructions",
      "goal": "<what the prompt was trying to elicit>",
      "success": true,
      "response_classification": "compliant",
      "reasoning": "<why the judge scored it this way>",
      "confidence": 0.91
    }
  ],
  "total": 1,
  "limit": 1000,
  "offset": 0,
  "next_offset": null
}
```

Records come back **1,000 at a time** by default. `total` is the run's full count; while
`next_offset` is not `null`, request `/rt/runs/{run_id}/records?offset=<next_offset>` for the
next page. `?limit=` sets a smaller page size (1-1000).

> [!WARNING]
>
> `success: true` means the **attack** succeeded — your target produced the content it
> should have refused. These are the rows to investigate first.

## Next steps

> **[Map to a compliance framework](/api-reference/redteam-v2-api-reference/endpoint/get-compliance-report)**
>
> `GET /rt/runs/{run_id}/compliance/{framework_id}` re-expresses the same run against
> OWASP LLM Top 10, EU AI Act, NIST AI RMF, MITRE ATLAS, ISO 42001 or AIUC-1.

> **[Get remediation](/api-reference/redteam-v2-api-reference/endpoint/risk-mitigation-system-prompt)**
>
> `POST /rt/risk-mitigation/system-prompt` turns a run summary into a hardened system
> prompt; `/rt/risk-mitigation/guardrails-policy` turns it into a Guardrails policy.

> **[Widen the attack surface](/get-started/redteam/attack-methods-reference)**
>
> `basic` is only the baseline. Add evasion and adaptive jailbreak techniques.

> **[Check your target first](/api-reference/redteam-v2-api-reference/endpoint/model-health)**
>
> `POST /rt/model-health` verifies Enkrypt AI can reach and call your target before you
> spend a run on it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.