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

# Python SDK Overview

> Install, initialize, and use the Artifacta Python client.

## Install

```bash theme={null}
pip install artifacta-cli
```

This installs both the CLI and the Python client library.

## Initialize the client

```python theme={null}
from artifacta import Client

# Option 1: Auto-detect from environment or config file
client = Client()
# Reads ARTIFACTA_API_KEY from env, then ~/.config/artifacta/config.toml
# Also reads ARTIFACTA_SESSION_ID and ARTIFACTA_AGENT_ID as defaults

# Option 2: Explicit API key
client = Client(api_key="ak_live_abc123")

# Option 3: Custom base URL
client = Client(base_url="https://api.artifacta.io")
```

<Tip>
  **Zero-config for agents:** If `ARTIFACTA_API_KEY` and `ARTIFACTA_SESSION_ID` are set in the environment, `Client()` with no arguments is all you need. Every `push()` call inherits the session automatically.
</Tip>

## Methods at a glance

### Write

| Method                                    | Description                                    |
| ----------------------------------------- | ---------------------------------------------- |
| [`push()`](/sdk/push)                     | Upload a file from disk or bytes               |
| [`push_dict()`](/sdk/push-dict)           | Serialize a dict to JSON and upload            |
| [`delete()`](/sdk/delete)                 | Soft-delete an artifact                        |
| [`create_link()`](/sdk/create-link)       | Create a temporary download URL                |
| [`seal_session()`](/sdk/seal-session)     | Seal a session                                 |
| [`publish_artifact()`](#publish_artifact) | Publish an artifact as a shareable public page |
| [`unpublish()`](#unpublish)               | Take down an artifact's public page            |

### Read

| Method                            | Description                     |
| --------------------------------- | ------------------------------- |
| [`pull()`](/sdk/pull)             | Download to a file path         |
| [`pull_bytes()`](/sdk/pull-bytes) | Download as bytes (in memory)   |
| [`pull_dict()`](/sdk/pull-dict)   | Download and parse as JSON dict |
| [`list()`](/sdk/list)             | List artifacts with filters     |
| [`get()`](/sdk/get)               | Get artifact metadata           |

### Utilities

| Method                                     | Description                                         |
| ------------------------------------------ | --------------------------------------------------- |
| [`Client.session_new()`](/sdk/session-new) | Generate a session ID locally (static, no API call) |
| [`whoami()`](/sdk/whoami)                  | Verify auth and get tenant info                     |

## Quick example

```python theme={null}
from artifacta import Client

client = Client()

# Push a file
artifact = client.push(
    "report.pdf",
    session_id="run_q4",
    agent_id="earnings_bot",
    metadata={"model": "claude-sonnet-4-6"}
)
print(artifact.id)          # art_2xk9f7v3m1p0
print(artifact.size_bytes)  # 250880

# Push structured data
artifact = client.push_dict(
    {"results": [1, 2, 3], "score": 0.95},
    filename="results.json",
    session_id="run_q4"
)

# Pull to disk
client.pull(artifact.id, output="./downloads/")

# Pull as bytes (no disk I/O)
content = client.pull_bytes(artifact.id)

# Pull as dict
data = client.pull_dict(artifact.id)

# List with filters
for a in client.list(session_id="run_q4", metadata={"model": "claude-sonnet-4-6"}):
    print(f"{a.id}: {a.filename}")

# Create a shareable link
link = client.create_link(artifact.id, expires_in=86400)
print(link.url)  # https://dl.artifacta.io/lnk_xxx

# Seal a session
client.seal_session("run_q4")
```

## `publish_artifact()`

```python theme={null}
publish_artifact(
    artifact_id: str,
    *,
    title: str | None = None,
    visibility: str = "unlisted",
    access: str = "none",
    password: str | None = None,
) -> dict
```

Publishes an artifact as a shareable page at `https://artifacta.io/a/{slug}`. Idempotent — re-publishing the same artifact updates the page and keeps the same URL.

| Parameter     | Type        | Default      | Description                                           |
| ------------- | ----------- | ------------ | ----------------------------------------------------- |
| `artifact_id` | str         | —            | Artifact ID to publish.                               |
| `title`       | str \| None | `None`       | Page title.                                           |
| `visibility`  | str         | `"unlisted"` | `"unlisted"` (URL-only) or `"public"` (discoverable). |
| `access`      | str         | `"none"`     | `"none"` (open) or `"password"` (Pro plan).           |
| `password`    | str \| None | `None`       | Required when `access="password"`.                    |

Returns a `dict` with `page_id`, `public_url`, `visibility`, and `access`.

```python theme={null}
from artifacta import Client

client = Client()

# Publish an artifact as an unlisted page
page = client.publish_artifact("art_abc123")
print(page["public_url"])  # https://artifacta.io/a/pg_...

# Publish publicly with a title
page = client.publish_artifact(
    "art_abc123",
    title="Q2 Report",
    visibility="public",
)

# Publish with password protection (Pro plan)
page = client.publish_artifact(
    "art_abc123",
    access="password",
    password="hunter2",
)
```

## `unpublish()`

```python theme={null}
unpublish(id_or_slug: str) -> dict
```

Soft-unpublishes an artifact page. The artifact itself is not deleted. Accepts an artifact ID (`art_...`) or a page slug (`pg_...`).

Returns a `dict` with `page_id` and `unpublished: True`.

```python theme={null}
# Unpublish by artifact ID
result = client.unpublish("art_abc123")
print(result["page_id"])  # pg_...

# Unpublish by page slug
result = client.unpublish("pg_aB3xK9mP1qR5sT2u")
```

## Error handling

All methods raise typed exceptions matching the [API error taxonomy](/errors):

```python theme={null}
from artifacta import (
    Client,
    ArtifactNotFoundError,
    ArtifactExpiredError,
    SessionSealedError,
    QuotaExceededError,
    RateLimitedError,
)

client = Client()

try:
    artifact = client.push("output.json", session_id="run_42")
except SessionSealedError:
    print("Session is finalized — use a new session")
except QuotaExceededError:
    print("Storage or request limit reached — delete artifacts or upgrade")
except RateLimitedError as e:
    print(f"Throttled — retry in {e.retry_after_seconds}s")
```

See the [full exception reference](/sdk/errors) for the complete mapping.

## Environment variable defaults

The SDK respects the same environment variables as the CLI:

| Variable               | SDK behavior                                      |
| ---------------------- | ------------------------------------------------- |
| `ARTIFACTA_API_KEY`    | Used by `Client()` if no explicit `api_key` param |
| `ARTIFACTA_API_URL`    | Used as `base_url` default                        |
| `ARTIFACTA_SESSION_ID` | Default `session_id` for `push()` and `list()`    |
| `ARTIFACTA_AGENT_ID`   | Default `agent_id` for `push()`                   |
