---
title: "Inference Capture | Tarka Control API Docs"
description: "Configure organization inference capture through the console, Control API, or MCP, and understand stored records, media, expiry, and delivery health."
url: "https://tarkahq.com/docs/control-api/inference-capture/"
---

Available Control API · Inference capture

# Capture inference in your bucket

Opt in to saving model requests and responses in your organization's private Object Storage bucket. The console, Control API, and MCP manage the same setting.

On this page

[Policy](https://tarkahq.com/docs/control-api/inference-capture/#policy) [REST](https://tarkahq.com/docs/control-api/inference-capture/#rest) [MCP](https://tarkahq.com/docs/control-api/inference-capture/#mcp) [Stored objects](https://tarkahq.com/docs/control-api/inference-capture/#objects) [Delivery health](https://tarkahq.com/docs/control-api/inference-capture/#health)

Organization setting

## Choose capture and expiry

Customer capture starts off. An organization owner or admin can enable it in [Console → Object Storage](https://tarkahq.com/console/storage), through REST, or through MCP. Enabling requires approved Object Storage access and creates or reuses the organization's `inference-history` bucket.

The setting covers admitted calls across model types, including language models, speech, and other utilities. There are no per-key or per-model customer overrides. Choose `retention_days` of `0` (until deleted), `7`, `30`, or `90`. Send both `enabled` and `retention_days` on updates; this is a replacement setting, not a partial patch.

Changes apply to new requests. Existing captures keep their original expiry. Disabling preserves the bucket and its objects, and requests already in flight may finish capturing. The active destination cannot be deleted until capture is disabled.

**Tarka's internal retention is a separate policy.**

Free Himalaya aliases retain inputs and outputs internally for evaluation and debugging until Tarka administrators delete them; they are not used for training. The `-private` Himalaya aliases forbid internal retention. Other model families have internal retention off. Customer opt-in can still capture any of these calls in the customer's own bucket. Neither this setting nor these tools grant access to Tarka's internal archive.

Private aliases currently have zero prices and use the `inference` key scope. Retention follows the selected alias, not payment or account balance. See [language model retention](https://tarkahq.com/docs/inference/llms/#data-retention).

The Responses API's `store` flag is independent: it defaults to `false`; explicit `true` enables separate conversation state for 30 days. It does not override either capture policy.

Control API

## Read and update through REST

Use an approved Tarka account bearer token, not an inference `tk_live_` key. Active organization members can read settings and health; only owners and admins can update them. Set `TARKA_ORG_ID` to the organization you intend to manage.

Read settings and health `GET`

```
curl "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/inference-capture" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN"
```

Enable seven-day capture `PUT`

```
curl -X PUT "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/inference-capture" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true,"retention_days":7}'
```

Example response `200 OK`

```
{
  "org_id": "00000000-0000-0000-0000-000000000001",
  "enabled": true,
  "retention_days": 7,
  "bucket_id": "00000000-0000-0000-0000-000000000002",
  "bucket_name": "inference-history",
  "delivered_last_24h": "12",
  "last_delivered_at": "2026-09-28T10:00:00Z"
}
```

GET and PUT use the same response schema. REST omits default scalar values: a missing `enabled` means `false`, missing counts mean `0`, and missing string fields mean an empty string. Present counts are protobuf 64-bit integers encoded as decimal strings. Before a bucket is created, bucket fields are absent; before a successful delivery, `last_delivered_at` is absent.

Stop new captures `PUT`

```
curl -X PUT "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/inference-capture" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"enabled":false,"retention_days":7}'
```

Native gRPC uses `GetInferenceCapture` and `UpdateInferenceCapture` on `tarka.provisioning.v1.ProvisioningService` at `grpc.tarka.rest:443`. The [protobuf contract](https://github.com/TarkaHQ/api/blob/main/proto/tarka/provisioning/v1/provisioning.proto) and [OpenAPI document](https://github.com/TarkaHQ/api/blob/main/openapi/tarka-control-v1.swagger.json) define the fields and routes.

MCP

## Use the same setting from an MCP client

Add `https://tarka.rest/mcp` as a remote Streamable HTTP server and connect with OAuth, as described in [MCP](https://tarkahq.com/docs/control-api/mcp/). Browser consent uses your Tarka console account. Manage or disconnect access at [MCP connections](https://tarkahq.com/oauth/mcp).

The default `provisioning:read` scope allows `tarka_get_inference_capture`. Updating requires consent to `provisioning:read provisioning:write` and the same owner/admin role and storage access as REST. A read-only connection attempting an update receives HTTP 403 with `insufficient_scope`.

Read settings and health `tools/call`

```
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "tarka_get_inference_capture",
    "arguments": {
      "org_id": "YOUR_ORG_ID"
    }
  }
}
```

Enable capture `tools/call`

```
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "tarka_update_inference_capture",
    "arguments": {
      "org_id": "YOUR_ORG_ID",
      "enabled": true,
      "retention_days": 7
    }
  }
}
```

Replace `YOUR_ORG_ID` with your organization ID. To disable, call `tarka_update_inference_capture` with `enabled: false` and your selected `retention_days`. Successful results expose the same response fields in `structuredContent`. MCP includes default false, zero, and empty scalar values explicitly. Business or authorization failures use `isError`; check it before reading the result. MCP OAuth tokens authenticate only to MCP, not to REST or S3.

Object Storage

## JSON records with separate media objects

Each delivery writes `captures/v1/YYYY-MM-DD/<delivery-uuid>/record.json`. The versioned manifest contains request and model identifiers, timestamps, parameters, responses, completion state, and artifact metadata. Each request has its own record; it is not a shared JSONL file.

Uploaded audio and inline images are stored as binary objects under the same request prefix, with content type, byte length, and SHA-256 in the manifest. For speech-to-text, this means the request parameters and transcription in JSON plus the uploaded audio bytes. Streamed speech output is joined into an output object; chat streams retain ordered events and an assembled response.

Transport credentials are removed. External media URLs are sanitized references with `bytes_retained: false`; remote media is not refetched. Content that only an upstream provider received cannot be reconstructed by capture. Interrupted streams may have an incomplete record.

Use [bucket-scoped S3 credentials](https://tarkahq.com/docs/control-api/data/#storage-credentials) and the returned `s3_bucket_name` to read or delete captures. The display name is `inference-history`; do not derive the S3 name from it. Artifacts upload before `record.json`, which marks a completed upload.

**Permanent deletion includes object versions.**

Expiry removes all versions and delete markers under a capture's prefix. Manual S3 deletion must do the same to remove retained bytes permanently. Disabling capture alone does not delete existing data.

Delivery health

## Check delivery independently of inference

Capture is asynchronous and best effort. Queue pressure, large payloads, storage failures, and process restarts can leave gaps while inference continues. A successful inference response does not guarantee a saved capture.

The console, GET route, and read tool report delivered and failed counts for the last 24 hours, outstanding deliveries, the latest error code, and the last successful delivery time. These describe customer deliveries only. Failures before a delivery receipt is created may not appear in these counters, so they are not proof that every request was retained.
