Skip to main content

Mental model

Tenant
├── API Key(s)
└── Artifacts
    ├── art_abc  ── filename, metadata, session_id, agent_id
    │   └── blob (content-addressed, deduplicated per tenant)
    ├── art_def  ── same session, different agent
    │   └── blob
    └── art_ghi  ── different session
        └── blob (may share storage with art_abc if identical content)

Sessions are optional labels. They can be sealed to prevent late uploads.
Agents are optional labels. No server-side management for either.

Core nouns

An isolated account. All artifacts, API keys, and usage belong to exactly one tenant. Created automatically when you sign up. Think of it as your project or team.
The core object. A single uploaded file with metadata. Has a stable ID (art_ + 16 alphanumeric chars), a filename, content type, metadata, and belongs to a tenant. Every upload creates a new artifact — no implicit versioning.
An optional, user-defined string grouping artifacts from the same run or workflow. Example: "pipeline_run_42". Not managed by Artifacta — just a label. Sessions can be sealed to prevent late uploads.
An optional, user-defined string identifying which agent produced an artifact. Example: "earnings_analyst". Just a label — not managed server-side.
A JSON object of key-value pairs attached at upload time. Max 8 KB. Keys must match ^[a-zA-Z][a-zA-Z0-9_-]{0,63}$no dots allowed. Filterable via the API (one key-value exact match per query).
SHA-256 hash of file contents. Used for blob-level deduplication within a tenant. Two artifacts with the same content share one blob in storage — invisible to you, saves space.
Time-to-live. Default: 30 days. Can be overridden per artifact (--ttl 7d, --ttl 90d, --ttl never). Can be extended via extend-ttl. The only mutable field on an artifact.

Key design decisions

Every upload creates a new artifact. Uploading report.pdf twice produces two distinct artifacts with two IDs. No implicit versioning.
Artifact content and metadata are immutable. Once uploaded, you cannot change content, filename, or metadata. To correct something, upload a new artifact. Exception: expires_at is mutable via extend-ttl.
Sessions are labels, not managed objects. There is no POST /v1/sessions. A session exists when at least one artifact references that session_id. Sealing is the only explicit session operation.

Artifact lifecycle

push → active → [extend-ttl] → expires → garbage collected
                → [delete]    → soft-deleted → hard-deleted (30 days)
  • Soft delete: DELETE sets deleted_at. Artifact disappears from listings and downloads immediately.
  • Hard delete: Background job removes the Postgres row and R2 blob 30 days after soft delete.
  • Expiration: Artifacts past their expires_at return 410 Gone. Garbage collected automatically.

Deduplication

Two separate mechanisms:
LayerMechanismWhat it does
Blob storageContent-hash (SHA-256) per tenantTwo artifacts with identical content share one blob in R2. Saves storage. Invisible to you.
APIIdempotency key (24h TTL)Same Idempotency-Key header within 24h returns the original response. No content comparison. Prevents duplicate artifacts on retry.