---
title: "Object Storage | Tarka Docs"
description: "Create private S3-compatible buckets and scoped credentials with Tarka Object Storage."
url: "https://tarkahq.com/docs/data/object-storage/"
---

Available Data · Object Storage

# Object Storage

Store datasets, generated output, model assets, and workload artifacts in private, versioned S3-compatible buckets.

Provisioning and management **Use the console or the Control API.**

Create buckets and bucket credentials at /console/storage or through the organization-scoped Control API. A resource created on either surface is immediately visible on the other.

[Open console](https://tarkahq.com/console) [Control API reference](https://tarkahq.com/docs/control-api/data/)

On this page

[Quickstart](https://tarkahq.com/docs/data/object-storage/#quickstart) [S3 clients](https://tarkahq.com/docs/data/object-storage/#clients) [Credentials](https://tarkahq.com/docs/data/object-storage/#credentials) [API reference](https://tarkahq.com/docs/data/object-storage/#api-reference) [Inference capture](https://tarkahq.com/docs/data/object-storage/#inference-capture) [Lifecycle](https://tarkahq.com/docs/data/object-storage/#lifecycle)

Quickstart

## Create a bucket and one scoped credential

Use the console for an interactive setup, or send the same lifecycle requests to the Control API with a Tarka account access token.

1. 01

   **Create a bucket**

   Names are lowercase DNS labels of at most 40 characters and are unique within an organization.
2. 02

   **Create a credential**

   The access key can read and write only that bucket.
3. 03

   **Connect an S3 client**

   Use the endpoint, region, and `s3_bucket_name` returned by the API.

Create bucket `Control API`

```
curl -X POST \
  "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/storage/buckets" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"training-data"}'
```

Bucket `201 Created`

```
{
  "id": "bucket_01K...",
  "org_id": "org_01K...",
  "name": "training-data",
  "status": "ready",
  "endpoint": "https://storage.tarka.rest",
  "region": "eu-central-1",
  "versioning_enabled": true,
  "s3_bucket_name": "tarka-a1b2c3d4e5f6-training-data"
}
```

Create credential `Control API`

```
curl -X POST \
  "https://tarka.rest/control/v1/orgs/$TARKA_ORG_ID/storage/buckets/$BUCKET_ID/credentials" \
  -H "Authorization: Bearer $TARKA_ACCOUNT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"label":"training uploader"}'
```

Credential `201 Created`

```
{
  "credential": {
    "id": "credential_01K...",
    "bucket_id": "bucket_01K...",
    "label": "training uploader",
    "access_key_prefix": "TKST...",
    "status": "active"
  },
  "access_key_id": "TKST...",
  "secret_access_key": "returned-once",
  "endpoint": "https://storage.tarka.rest",
  "region": "eu-central-1"
}
```

**The secret is shown once.**

Save `secret_access_key` directly to a secret manager. It is not included in list responses and cannot be recovered later. Create a replacement and revoke the old credential if it is lost.

Data plane

## Use standard S3 clients

Set the custom endpoint, returned region, and path-style addressing. Bucket operations use the returned `s3_bucket_name`; `name` remains the organization-local display name.

Download the credential environment file from the console, load it in your application environment, and install `boto3` for the Python example below. Keep the file out of source control.

**Do not construct the S3 name.**

Always read `s3_bucket_name` from the bucket response or console. Its format is not part of the compatibility contract.

Python `boto3`

```
import os

import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url="https://storage.tarka.rest",
    region_name="eu-central-1",
    aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
    aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
    config=Config(s3={"addressing_style": "path"}),
)

s3.upload_file("result.json", "tarka-a1b2c3d4e5f6-training-data", "results/result.json")
s3.download_file("tarka-a1b2c3d4e5f6-training-data", "results/result.json", "downloaded.json")
```

Access

## Scope credentials per workload

A storage credential is bound to exactly one bucket. Create separate credentials for development, production, CI, and individual services so each can be revoked independently.

**Keep secrets server-side**

Do not embed access keys in browser bundles, images, repositories, logs, or screenshots.

**Rotate by replacement**

Create a new credential, update the workload, verify it, then revoke the old one.

**Use the narrow bucket**

A credential for one bucket cannot list or access another organization bucket.

Reference

## Control API routes

Prefix each path with `https://tarka.rest/control/v1`. The bearer token is a Tarka account access token; inference keys are separate credentials.

| Method | Path | Operation |
| --- | --- | --- |
| `POST` | `/orgs/{org_id}/storage/buckets` | Create a private bucket |
| `GET` | `/orgs/{org_id}/storage/buckets` | List buckets |
| `DELETE` | `/orgs/{org_id}/storage/buckets/{bucket_id}` | Delete an empty bucket |
| `POST` | `/orgs/{org_id}/storage/buckets/{bucket_id}/credentials` | Create a scoped credential |
| `GET` | `/orgs/{org_id}/storage/buckets/{bucket_id}/credentials` | List redacted credential metadata |
| `POST` | `/orgs/{org_id}/storage/buckets/{bucket_id}/credentials/{credential_id}:revoke` | Revoke a credential |

Model data

## Capture inference in your organization

Owners and admins can enable inference capture on the Object Storage console page. It starts off and saves JSON records and media in a private `inference-history` bucket, with optional 7-, 30-, or 90-day expiry. The console shows delivery health.

Use the [inference capture guide](https://tarkahq.com/docs/control-api/inference-capture/) for REST and MCP examples, stored formats, retention policy, and permanent deletion. Disabling capture preserves existing objects.

Lifecycle

## Versioning, revocation, and deletion

New buckets are private and versioning is enabled before the bucket becomes ready. Revocation is permanent. A bucket can be deleted only after its current objects, historical versions, and delete markers have been removed.

**Deletion is destructive.**

Confirm that required data has been copied elsewhere before deleting all versions and removing the bucket. The Control API rejects deletion while data remains.
