# InferenceView private outcome intake

`POST https://inferenceview.com/api/intelligence/outcomes`

Enroll a producer in Operator tools or request an outcome integration. Use its
producer ID and signing key, not a wallet key. This endpoint does not execute a
purchase. Records remain private; reports do not change public integrity.

## Envelope

```json
{
  "schema": "inferenceview.outcome.v1",
  "event_id": "stable-event-id",
  "task_id": "task-123",
  "attempt_id": "attempt-1",
  "environment": "test",
  "occurred_at": "2026-09-11T12:00:00Z",
  "service_url": "https://api.example.com/search",
  "service_version": "2026-09",
  "charge": {"amount": "0.01", "fee": "0", "currency": "USDC"},
  "latency_ms": 420,
  "evaluation": {
    "status": "unknown",
    "rubric_id": "customer-search-acceptance",
    "rubric_version": "1"
  }
}
```

This is a schema example, not a real transaction. Use the actual event time.
Times must include a timezone or be Unix seconds. Future events beyond five
minutes are refused. Payload limit: 64,000 bytes.

Required: schema, event_id, task_id, attempt_id, environment, occurred_at,
service_url, evaluation.status, evaluation.rubric_id and rubric_version.
Identifiers contain 1–128 ASCII letters, digits, underscores, dots, colons or
hyphens. Environment is `test` or `live`; evaluation status is `pass`, `fail`
or `unknown`. Even `pass` is recorded as source-reported, not independently
verified. Use stable task IDs across retries and a separate attempt ID for each
attempt. Only one final observation per attempt is accepted.

Charges must be nonnegative exact decimal strings. Include currency with any
amount or fee. Fee must use the same currency as amount; send `null` when its
amount or currency is unknown. Do not convert tokens to USD at par. Missing fees
are unknown, not zero. Latency is optional and must be between 0 and 86,400,000
milliseconds. Do not include keys, credentials, customer identities or raw
customer inputs/results.

Optional artifact: `{"sha256":"<64 lowercase hex characters>","bytes":1234}`.
An optional `evidence_event_id` must reference a result already submitted to
the existing evidence API by the same producer, with the same task ID. Both
artifact fields must match the collector's retained result. A match confirms
byte linkage only. Settlement and semantic correctness still need separate
validation. Evidence collected elsewhere can be represented by its fingerprint
but is not independently verified by this endpoint.

## Authentication and retries

Send `X-IV-Producer`, `X-IV-Timestamp` (current Unix seconds) and
`X-IV-Signature`. Signature is lowercase hex HMAC-SHA256 over the timestamp,
a literal dot and the exact UTF-8 request bytes. Delivery time must be within
five minutes. Keep the key in your secret store.

```python
import hashlib, hmac, json, os, time, urllib.request

def send_outcome(event):
    body = json.dumps(event, separators=(",", ":"), allow_nan=False).encode()
    timestamp = str(time.time())
    signature = hmac.new(
        os.environ["IV_PRODUCER_KEY"].encode(),
        timestamp.encode() + b"." + body,
        hashlib.sha256,
    ).hexdigest()
    request = urllib.request.Request(
        "https://inferenceview.com/api/intelligence/outcomes",
        data=body,
        headers={
            "Content-Type": "application/json",
            "X-IV-Producer": os.environ["IV_PRODUCER_ID"],
            "X-IV-Timestamp": timestamp,
            "X-IV-Signature": signature,
        },
    )
    with urllib.request.urlopen(request, timeout=20) as response:
        return json.load(response)
```

On an uncertain response, retry the identical body and event ID with a fresh
delivery timestamp/signature. Identical retries are idempotent. Conflicting
replays or a second event for the same producer/environment/task/attempt fail.
Back off on 429 or 503. Correct a 400 rather than retrying it indefinitely.

## Private reads and summaries

`GET /api/intelligence/outcomes?environment=live&limit=25` requires the operator
Bearer key. Limits are 1–100. Test and live data never mix. Summaries cover only
the returned sample and explicitly say when truncated. Grouping keeps producer,
service version, rubric version and currency separate. Reported cost includes
reported charges and fees for both passing and failing attempts. Missing charges
or fees make the cost metric unknown. No accepted tasks means no finite cost
per accepted task. Plan allocation, evaluation and switching costs are not yet
captured; this is not an all-in or independently evaluated benchmark.

Records persist on the private Cube database and enter the private Backblaze
archive queue. Archive verification is separate from correctness of the claim.
