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

# Defensibility and trace

> Export the evidence behind a run's answer, and know what the portal trace and corrections cover.

When someone asks how an engine reached an answer, the defensibility packet is the one document to hand them. It bundles the run's identity and lineage, the output, the per-element provenance map when the run recorded one, the external data calls that fed it, the timeline of events, and the model usage summary. A client, a reviewer, or an auditor can read it without access to Nexio.

## What the packet contains

`GET /api/v1/runs/{run_id}/defensibility-packet` returns packet version `1`:

| Field                 | Contents                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `version`             | `"1"`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `run`                 | Identity and lineage: `id`, `status`, `started_at` (when the run was created), `environment` and `cost_rollup` (`input_tokens`, `output_tokens`, `cost_micros`), plus `completed_at`, `engine_id`, `engine_type`, `engine_config_version_hash`, `trace_id`, `submitted_by`, `submitted_by_label`, `error_details` and `warning_details` when they have a value. `status` here is the stored value in capitals, for example `COMPLETED`, not the lowercase value polling returns. |
| `output`              | The run's stored output. Absent when the run has no output yet.                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `provenance`          | The per-element provenance map. Absent when the run did not record one.                                                                                                                                                                                                                                                                                                                                                                                                          |
| `provenance_coverage` | `present` when `provenance` exists, `none` when it does not. `none` means the run did not record provenance, not that the output has no sources.                                                                                                                                                                                                                                                                                                                                 |
| `model_calls`         | One entry per recorded model call, with `stage` and `blob_type`. The prompt and completion are withheld: `blob` is always `null`.                                                                                                                                                                                                                                                                                                                                                |
| `external_calls`      | One entry per recorded external data call (for example an enrichment lookup), with `stage`, `blob_type` and the recorded request and response in `blob`.                                                                                                                                                                                                                                                                                                                         |
| `events`              | The run's event timeline in time order, for example stages, steps, model calls, external calls, retries, errors, webhook deliveries and lifecycle events, each with its timing and attributes. The timeline is cut off after about the first 1,000 events, and the packet does not say when it was cut.                                                                                                                                                                          |
| `llm_summary`         | Totals across model calls: `total_calls`, `total_tokens`, `total_cost_micros`, `cache_hit_rate`, and `by_model`.                                                                                                                                                                                                                                                                                                                                                                 |
| `redaction`           | `{"fields_redacted": 0}`.                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

### What is withheld, and what is not

* **Withheld:** the body of every model call. The call is attested by its stage so the chain is complete, but the prompt and completion are Nexio's engine implementation and are not part of the packet.
* **Not redacted:** everything else. The redaction step in the packet is not active today, so `fields_redacted` is always `0` and external-call evidence, output, provenance, warnings, event attributes and submitter labels appear as recorded. They can contain personal or restricted data. Store and send the packet with the same care as the run's input. The [data use](/reference/data-use) sheet labels event attributes, structured event errors and external-call evidence as "Export redacted"; that label names the intended export, and the redaction step behind it does nothing today, so this paragraph describes the packet as it is now.

## Get a packet

<CodeGroup>
  ```bash curl theme={null}
  curl -s https://api.usenexio.com/api/v1/runs/8e4b2c7a-1f5d-4a3e-9c6b-0d2f8a7e5b14/defensibility-packet \
    -H "Authorization: Bearer $NEXIO_API_KEY"
  ```

  ```python Python theme={null}
  import json
  import os

  import requests

  resp = requests.get(
      "https://api.usenexio.com/api/v1/runs/8e4b2c7a-1f5d-4a3e-9c6b-0d2f8a7e5b14/defensibility-packet",
      headers={"Authorization": "Bearer " + os.environ["NEXIO_API_KEY"]},
      timeout=60,
  )
  resp.raise_for_status()
  with open("packet-8e4b2c7a.json", "w") as f:
      json.dump(resp.json(), f, indent=2)
  ```

  ```typescript TypeScript theme={null}
  import { writeFile } from "node:fs/promises";

  const resp = await fetch(
    "https://api.usenexio.com/api/v1/runs/8e4b2c7a-1f5d-4a3e-9c6b-0d2f8a7e5b14/defensibility-packet",
    { headers: { Authorization: `Bearer ${process.env.NEXIO_API_KEY}` } },
  );
  if (!resp.ok) throw new Error(`packet failed: ${resp.status} ${await resp.text()}`);
  await writeFile("packet-8e4b2c7a.json", JSON.stringify(await resp.json(), null, 2));
  ```
</CodeGroup>

A shortened packet for a run of the `vendor-intake` engine from [Declared-contract engines](/engines/guides/contract-mode). The run made no model or external calls and recorded no provenance map. The timeline is cut to the two stage events the declared-contract runner records, `ENRICH` and `COMPOSE`.

```json theme={null}
{
  "version": "1",
  "run": {
    "id": "8e4b2c7a-1f5d-4a3e-9c6b-0d2f8a7e5b14",
    "status": "COMPLETED",
    "started_at": "2026-09-23T14:02:11.804553Z",
    "completed_at": "2026-09-23T14:02:12.472810Z",
    "engine_id": "7d3a9f12-6c4e-4b8a-9e21-5f0b8c7d6a34",
    "engine_type": "entity_analysis",
    "environment": "test",
    "engine_config_version_hash": "5d20b8e4c1f7a693",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "submitted_by": "api_key:9c1e4b7a-2d6f-4a83-b5e0-7f2c1d9a8e36",
    "submitted_by_label": "Harbor Group sandbox integration",
    "cost_rollup": { "input_tokens": 0, "output_tokens": 0, "cost_micros": 0 }
  },
  "output": {
    "response_type": "vendor_intake",
    "request_id": "8e4b2c7a-1f5d-4a3e-9c6b-0d2f8a7e5b14",
    "vendor": { "annual_spend_usd": 480000, "country": "US", "name": "Example Logistics" },
    "next_step": "Request a current security attestation from Example Logistics before onboarding.",
    "standard": "supplier-onboarding-2026"
  },
  "provenance_coverage": "none",
  "model_calls": [],
  "external_calls": [],
  "events": [
    {
      "id": "0e8b2d4f-6a1c-4e3b-9d7f-2c5a8e1b4d60",
      "kind": "stage",
      "name": "ENRICH",
      "stage": "ENRICH",
      "status": "ok",
      "attributes": {
        "type": "pipeline.stage",
        "run_id": "8e4b2c7a-1f5d-4a3e-9c6b-0d2f8a7e5b14",
        "stage": "ENRICH",
        "timestamp": "2026-09-23T14:02:12Z"
      },
      "schema_version": 1,
      "created_at": "2026-09-23T14:02:12.311240Z"
    },
    {
      "id": "7c1f3a5e-9b2d-4f8a-a6c4-1e3d5b7f9a02",
      "kind": "stage",
      "name": "COMPOSE",
      "stage": "COMPOSE",
      "status": "ok",
      "attributes": {
        "type": "pipeline.stage",
        "run_id": "8e4b2c7a-1f5d-4a3e-9c6b-0d2f8a7e5b14",
        "stage": "COMPOSE",
        "timestamp": "2026-09-23T14:02:12Z"
      },
      "schema_version": 1,
      "created_at": "2026-09-23T14:02:12.402907Z"
    }
  ],
  "llm_summary": {
    "total_calls": 0,
    "total_tokens": 0,
    "total_cost_micros": 0,
    "cache_hit_rate": 0,
    "by_model": []
  },
  "redaction": { "fields_redacted": 0 }
}
```

### Errors

| Status | Code                                  | Cause                                                                                      |
| ------ | ------------------------------------- | ------------------------------------------------------------------------------------------ |
| 400    | `missing_run_id`, `invalid_run_id`    | The path ID is absent or not a UUID.                                                       |
| 401    | `unauthorized`                        | Missing or invalid key.                                                                    |
| 403    | `insufficient_capability`             | Scoped key without `runs:defensibility:read`.                                              |
| 403    | `engine_binding_forbidden`            | Scoped key not bound to the run's engine.                                                  |
| 404    | `run_not_found`                       | No such run in your organization and the key's environment.                                |
| 500    | `internal_error`, `run_lookup_failed` | The run or part of its evidence could not be loaded. No partial packet is returned. Retry. |

### Credentials and retention

The packet accepts the organization key, or a scoped key that holds `runs:defensibility:read` (a capability separate from `runs:read`) and is bound to the run's engine. The run must be in the key's environment.

A daily job deletes runs created more than 90 days ago, together with their packet evidence. The exception is a run Nexio flags to be kept indefinitely; there is no API or portal control for that flag, so ask Nexio. Export the packet within the 90 days if you need it later.

## Run trace (portal)

The portal shows the same evidence, and more, on the run's **Trace** tab: the run's events with their timings, token counts and cost, and a viewer for recorded request and response bodies. The trace needs the portal permission `runs:trace`, which comes with a team member's role. There is no public API route for the trace and it cannot be granted to an API key. Use the defensibility packet for anything you need outside the portal.

## Supersession

Supersession attaches a corrected result to a run that was already delivered, while keeping the original. A superseded run sends a `run.superseded` webhook only when the engine's configuration sets `notify_on_supersede: true` (which configuration version Nexio checks is in [Configuration](/engines/configuration#settings-read-from-the-saved-configuration)) and an active webhook endpoint in the run's environment subscribes to `run.superseded`.

Built, not yet enabled as a customer feature: there is no public route and no portal control to supersede or to read a supersession.

<CardGroup cols={2}>
  <Card title="Runs" href="/engines/runs">
    What each run status carries.
  </Card>

  <Card title="Get run defensibility packet" href="/api-reference/engines/get-defensibility-packet">
    Endpoint reference.
  </Card>
</CardGroup>
