Introduction

Overview

Tessera is an HTTP API for storing encrypted, erasure-coded objects across independent storage providers. This is the reference for it.

Tessera stores objects as 15 encrypted shards distributed across 15 independent storage providers. Any 10 shards reconstruct the original. Your client does the encryption and the erasure coding; the API coordinates placement, holds the record of where things are, funds the storage contracts, and repairs shards when providers fail.

The consequence for you as an integrator is unusual and worth understanding before you start: Tessera is not in the data path. Object bytes never transit our servers. You call our API to find out where to write, you write directly to providers, and then you tell us what you did.

What this means in practice

You are writing a storage client, not calling a storage endpoint. There is no PUT /objects/my-file.txt that accepts a body. If you want one, you build it — the primitives below are what you build it from, and they are deliberately small.

The shape of an upload

1. POST /prepare-write   → 15 providers, with an access token and contract for each
2. (your client)           encrypt → Reed–Solomon split into 15 shards
3. (your client)           write each shard directly to its provider
4. POST /slabs           → register the shards as a slab, get a slab ID back
5. POST /objects         → register the object as an ordered list of slabs

A download is the same in reverse: read the object, read its slabs, fetch any 10 shards per slab directly from providers, reconstruct, decrypt.

Base URL and versioning

export TESSERA_API="https://api.PLACEHOLDER_DOMAIN.example"

Endpoints are unversioned in the path today. Breaking changes will be introduced as new paths, not as silent changes to existing ones.

Authentication in one paragraph

Every authenticated request carries three query parameters: credential (your ed25519 public key), validUntil (a unix expiry you choose), and signature (an ed25519 signature over a blake2b hash of the method, host, path, expiry, and body). There are no sessions, no bearer tokens, and no cookies. See Authentication for the exact construction and working code — you will need it before anything else works.

The endpoints

EndpointPurpose
POST /auth/provisionCreate a credential. The only unauthenticated endpoint.
GET /auth/checkVerify a credential is valid and active.
DELETE /auth/revokeRevoke a credential immediately.
POST /prepare-writeGet providers, contracts, and access tokens for a write.
GET /hostsList providers currently good for upload.
POST /slabsRegister erasure-coded shards as a slab.
GET /slabsList your slab IDs.
GET /slabs/{id}Read a slab: shard roots, providers, EC parameters.
DELETE /slabs/{id}Unpin a slab.
POST /slabs/pruneReclaim slabs no object references.
POST /objectsRegister an object as an ordered list of slab segments.
GET /objectsList object change events since a timestamp.
GET /objects/{key}Read an object's placement record.
DELETE /objects/{key}Delete an object.
GET /accountStorage and transfer counters.

Administrative and internal operator endpoints exist but are not part of the customer API surface, are not documented here, and are not reachable with a customer credential.

What is not here

Being direct about the gaps is more useful than making you find them:

  • No S3 compatibility. No bucket API, no presigned URLs, no multipart upload protocol.
  • No filenames or directories. The object model has no such fields. Names live in an encrypted metadata blob that only your keys can interpret — see Concepts.
  • No server-side encryption. Encryption happens in your client, by design.
  • No resumable upload protocol. Resumption is per-shard and is your client's concern; a failed shard write is retried against a different provider.
  • No browser-only integration. The API sets no CORS headers, so a browser cannot call it cross-origin. Call it from a server or a native client, or proxy it through your own backend.

Where to go next