> ## Documentation Index
> Fetch the complete documentation index at: https://hs-df36fa00.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Query Execution Receipts and Verify Agent Invocations

> Query execution receipts for every agent invocation. Verify outcomes manually or with the automated verifier sweep to ensure integrity.

Every agent invocation on ServiceNet produces an execution receipt — an immutable record containing cryptographic digests of the request and result. Receipts let you audit exactly what was called, when it ran, whether it succeeded, and whether its output has been independently verified. Use them to build audit trails, detect anomalies, and meet compliance requirements without storing raw payloads.

## Receipt fields

Every receipt response returns a `StoredReceipt` object. The core execution metadata is nested under the `receipt` key as an `ExecutionReceipt`. Two additional top-level fields, `output` and `stderr`, carry the raw invocation result and any captured error output when available.

### `ExecutionReceipt` fields (nested under `receipt`)

Each `ExecutionReceipt` captures the full lifecycle of a single invocation:

<ResponseField name="receipt_id" type="string (UUID)">
  The unique identifier for this receipt. Use it to fetch a specific receipt or submit a verification verdict.
</ResponseField>

<ResponseField name="agent_id" type="string">
  The ID of the agent that was invoked.
</ResponseField>

<ResponseField name="provider_id" type="string">
  The ID of the provider that hosts the agent.
</ResponseField>

<ResponseField name="status" type="string">
  The invocation outcome. One of:

  * `running` — the invocation is in progress (async only)
  * `succeeded` — the agent returned a successful A2A response
  * `failed` — the invocation failed (network error, agent error, or gateway rejection after dispatch)
  * `rejected` — the invocation was rejected by the gateway before any A2A call was made (blocked entity, policy violation, etc.)
</ResponseField>

<ResponseField name="verification" type="string">
  The current verification verdict. See [Verification verdicts](#verification-verdicts) below.
</ResponseField>

<ResponseField name="request_digest" type="string">
  SHA-256 hex digest of the normalized request payload (message, input, skill ID, and settlement fields). Use this to verify that two receipts represent identical requests.
</ResponseField>

<ResponseField name="result_digest" type="string | null">
  SHA-256 hex digest of the result payload, set on successful completion. `null` while the invocation is running or if it failed before producing output.
</ResponseField>

<ResponseField name="started_at" type="string">
  ISO 8601 timestamp when the gateway began processing the invocation.
</ResponseField>

<ResponseField name="completed_at" type="string | null">
  ISO 8601 timestamp when the invocation completed. `null` while `status` is `running`.
</ResponseField>

<ResponseField name="cost_units" type="integer | null">
  The number of cost units charged for this invocation, if the agent card declares a cost. `null` if the agent has no declared cost.
</ResponseField>

### `StoredReceipt` top-level fields

<ResponseField name="output" type="object | null">
  The raw JSON result payload returned by the agent, captured at completion time. `null` if the invocation failed, was rejected, or produced no structured output.
</ResponseField>

<ResponseField name="stderr" type="string | null">
  Any plain-text error or diagnostic output captured during the invocation. `null` when not present.
</ResponseField>

## Query receipts

### List receipts

Filter receipts by agent, provider, or verification verdict. All query parameters are optional.

```bash theme={null}
# All receipts for a provider
curl 'http://127.0.0.1:8042/v1/receipts?provider_id=acme-labs'

# All receipts for a specific agent
curl 'http://127.0.0.1:8042/v1/receipts?agent_id=stripe-agent'

# Only receipts that are pending verification
curl 'http://127.0.0.1:8042/v1/receipts?verification=pending'

# Combine filters and cap results
curl 'http://127.0.0.1:8042/v1/receipts?agent_id=stripe-agent&verification=pending&limit=50'
```

Responses wrap results in `{ "items": [...] }`. Each item is a `StoredReceipt` that nests the core `ExecutionReceipt` under a `receipt` key and includes optional `output` and `stderr` fields:

```json theme={null}
{
  "items": [
    {
      "receipt": {
        "receipt_id": "550e8400-e29b-41d4-a716-446655440000",
        "agent_id": "stripe-agent",
        "provider_id": "acme-labs",
        "status": "succeeded",
        "verification": "pending",
        "request_digest": "a3f2b1c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2",
        "result_digest": "f1e2d3c4b5a6978869504132c3b2a1f0e9d8c7b6a5948372615049382716059a",
        "started_at": "2025-01-15T12:34:55Z",
        "completed_at": "2025-01-15T12:34:56Z",
        "cost_units": 5
      },
      "output": { "payment_link": "https://pay.stripe.com/..." },
      "stderr": null
    }
  ]
}
```

### Query parameters

<ParamField query="agent_id" type="string">
  Return only receipts for the specified agent.
</ParamField>

<ParamField query="provider_id" type="string">
  Return only receipts for agents belonging to the specified provider.
</ParamField>

<ParamField query="verification" type="string">
  Filter by verification verdict. One of: `not_required`, `pending`, `verified`, `failed`.
</ParamField>

<ParamField query="limit" type="integer">
  Maximum number of receipts to return. Defaults to the node's configured list limit.
</ParamField>

### Fetch a single receipt

```bash theme={null}
curl http://127.0.0.1:8042/v1/receipts/550e8400-e29b-41d4-a716-446655440000
```

Returns a `StoredReceipt` object (not wrapped in `items`). The `StoredReceipt` nests the `ExecutionReceipt` under the `receipt` key and adds two optional fields — `output` (the raw JSON result, if available) and `stderr` (any captured error output). Returns HTTP 404 if the receipt ID does not exist.

```json theme={null}
{
  "receipt": {
    "receipt_id": "550e8400-e29b-41d4-a716-446655440000",
    "agent_id": "stripe-agent",
    "provider_id": "acme-labs",
    "status": "succeeded",
    "verification": "pending",
    "request_digest": "a3f2b1c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2",
    "result_digest": "f1e2d3c4b5a6978869504132c3b2a1f0e9d8c7b6a5948372615049382716059a",
    "started_at": "2025-01-15T12:34:55Z",
    "completed_at": "2025-01-15T12:34:56Z",
    "cost_units": 5
  },
  "output": { "payment_link": "https://pay.stripe.com/..." },
  "stderr": null
}
```

## Verification

### Verification verdicts

| Verdict        | Meaning                                                                                                |
| -------------- | ------------------------------------------------------------------------------------------------------ |
| `not_required` | The agent has `risk_level: "low"`. No verification step is needed.                                     |
| `pending`      | The agent has `risk_level: "medium"` or `"high"`. The receipt is waiting for a verifier to adjudicate. |
| `verified`     | At least one verifier has confirmed the outcome matches expectations.                                  |
| `failed`       | Verification found a discrepancy between the recorded digest and the expected result.                  |

<Note>
  Low-risk agents receive `not_required` automatically at receipt creation time and never enter the pending queue. Medium- and high-risk agents always start with `pending` and require either a manual verification or an automated sweep to advance.
</Note>

### Submit a manual verification

Send a `POST` to `/v1/receipts/:receipt_id/verify` to record a verification verdict for a specific receipt. You can use this for human-in-the-loop audits or custom automated checks outside the built-in sweep.

```bash theme={null}
curl -X POST http://127.0.0.1:8042/v1/receipts/550e8400-e29b-41d4-a716-446655440000/verify \
  -H 'content-type: application/json' \
  -d '{
    "verifier_id": "auditor-1",
    "verdict": "verified"
  }'
```

To record a discrepancy:

```bash theme={null}
curl -X POST http://127.0.0.1:8042/v1/receipts/550e8400-e29b-41d4-a716-446655440000/verify \
  -H 'content-type: application/json' \
  -d '{
    "verifier_id": "auditor-1",
    "verdict": "failed",
    "reason": "result digest does not match expected output for this input"
  }'
```

#### Verify request fields

<ParamField body="verifier_id" type="string" required>
  The identifier of the entity submitting this verdict. Can be a human auditor ID, an automated system name, or any string that identifies the verifier in your audit trail.
</ParamField>

<ParamField body="verdict" type="string" required>
  The verification outcome. Must be one of `verified` or `failed`. You cannot submit `not_required` or `pending` as a manual verdict.
</ParamField>

<ParamField body="automated" type="boolean">
  Set to `true` if this verdict was produced by an automated process rather than a human reviewer. Defaults to `false`.
</ParamField>

<ParamField body="reason" type="string">
  Optional explanation for the verdict. Especially useful when `verdict` is `failed` to describe what discrepancy was found.
</ParamField>

### List verification records for a receipt

Retrieve the full history of verification attempts for a specific receipt:

```bash theme={null}
curl http://127.0.0.1:8042/v1/receipts/550e8400-e29b-41d4-a716-446655440000/verifications
```

Returns `{ "items": [...] }` where each entry is a `VerificationRecord`:

```json theme={null}
{
  "items": [
    {
      "receipt_id": "550e8400-e29b-41d4-a716-446655440000",
      "verifier_id": "auto-verifier",
      "verdict": "verified",
      "automated": true,
      "reason": null,
      "verified_at": "2025-01-15T13:00:00Z"
    }
  ]
}
```

## Automated verifier sweep

The verifier sweep processes all receipts with `verification: "pending"` in a single pass. Run it on a schedule or after a batch of invocations to keep the pending queue clear.

```bash theme={null}
curl -X POST http://127.0.0.1:8042/v1/verifier/run \
  -H 'content-type: application/json' \
  -d '{ "verifier_id": "auto-verifier" }'
```

The response returns the `VerificationRecord` objects created during this sweep run:

```json theme={null}
{
  "items": [
    {
      "receipt_id": "550e8400-e29b-41d4-a716-446655440000",
      "verifier_id": "auto-verifier",
      "verdict": "verified",
      "automated": true,
      "reason": null,
      "verified_at": "2025-01-15T13:00:00Z"
    }
  ]
}
```

If no receipts are pending, `items` is an empty array.

<Tip>
  Run the sweep periodically in a background job or after any batch invocation workflow. Each run only processes receipts that are still `pending` — already-verified receipts are skipped automatically.
</Tip>

<Warning>
  Receipts with `status: "rejected"` are never assigned `pending` verification — they are rejected before any A2A call is made and produce no verifiable result digest. The sweep skips them entirely.
</Warning>
