API reference

Slabs

Register, read, list, unpin, and prune erasure-coded slabs — the layer that records which provider holds which shard.

A slab is one erasure-coded stripe. Registering it is how Tessera learns where your shards are, and therefore how repair and retrieval become possible.

POST /slabs

Registers one or more slabs. The body is an array, so a multi-slab object needs one call rather than several.

curl -X POST "$TESSERA_API/slabs?$AUTH" \
  -H 'content-type: application/json' \
  -d '[{
    "version": 1,
    "minShards": 10,
    "encryptionKey": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
    "sectors": [
      { "host": "ed25519:9f3c…", "root": "22ab…", "contractID": "a1b2…" }
    ]
  }]'

Slab object

FieldTypeDescription
versionintegerSlab format version. Use 1.
minShardsintegerShards required to reconstruct.
encryptionKeybase64Exactly 32 bytes. Standard base64 with padding.
sectorsarrayOne entry per shard, in shard order. Order is significant — it is the erasure-coding index.

Sector object

FieldTypeDescription
hoststringProvider public key, ed25519: + 64 hex characters.
rootstringMerkle root of the sector, 64 hex characters.
contractIDstringContract the sector was written under.

Response200 OK

["4f2a1b8c9d3e...", "7b1c2d3e4f5a..."]

Hex slab IDs, in the same order as the request.

Slab IDs are content-addressed

The ID is a digest of the slab's parameters, so registering identical parameters twice returns the same ID rather than creating a duplicate. Usefully, the digest does not include provider identities — repair can relocate a shard without changing the ID, so objects referencing the slab never need updating.

Validation — all of these are rejected at registration:

RuleError
encryptionKey is not exactly 32 bytesmanifest: invalid erasure coding params
Redundancy below 1.5× or above 4.0×manifest: invalid erasure coding params
The same provider appears twicemanifest: invalid erasure coding params
The same sector root appears twicemanifest: invalid erasure coding params
No account on the requestmanifest: empty account

Errors

StatusBodyCause
400invalid request body: ...Malformed JSON.
400manifest: invalid erasure coding paramsSee validation above.
402{"error": "storage cap exceeded", …}Registration would exceed your storage cap.
405method not allowedWrong method.

Cap accounting charges 4 MiB per sector at registration, which is the sector size regardless of how full the sector is. Packing small objects into shared slabs is therefore materially cheaper than one slab per small object.

GET /slabs/{id}

Reads a slab: everything needed to retrieve and reconstruct it.

curl "$TESSERA_API/slabs/4f2a1b8c9d3e...?$AUTH"
{
  "id": "4f2a1b8c9d3e...",
  "version": 1,
  "minShards": 10,
  "encryptionKey": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=",
  "sectors": [
    { "host": "ed25519:9f3c…", "root": "22ab…", "contractID": "a1b2…" }
  ],
  "createdAt": "2026-04-02T09:14:00Z"
}

The sectors array reflects current placement. If repair has moved a shard since you wrote it, you will see the new provider here — which is the reason to re-read the slab rather than cache placement indefinitely.

StatusBodyCause
400invalid slab id: ...Not 64 hex characters.
403manifest: forbidden for this accountThe slab belongs to another account.
404manifest: not foundNo such slab, for you.

GET /slabs

Lists your slab IDs.

curl "$TESSERA_API/slabs?limit=50&offset=0&$AUTH"
ParameterDefaultDescription
limit50Maximum IDs returned.
offset0Number to skip.
["4f2a1b8c...", "7b1c2d3e...", "9e8d7c6b..."]

Offset pagination drifts

offset is not a stable cursor. If slabs are created or pruned between pages, entries can be missed or repeated. For a complete enumeration — an export, for instance — walk GET /objects with its after cursor instead and collect slab IDs from the object records.

DELETE /slabs/{id}

Unpins a slab from your account.

curl -X DELETE "$TESSERA_API/slabs/4f2a1b8c...?$AUTH"

Response204 No Content.

StatusBodyCause
409manifest: slab still referenced by an objectDelete the referencing objects first.
403manifest: forbidden for this accountNot your slab.
404manifest: not foundNo such slab.

The 409 is a guard rail, not an obstacle: it exists so that deleting a slab cannot silently corrupt an object that still points at it.

POST /slabs/prune

Reclaims slabs no object references. The normal way to clean up after deleting objects.

curl -X POST "$TESSERA_API/slabs/prune?$AUTH"
{ "pruned": 3 }

Scoped to your account, so it can never affect anyone else's data. Safe to run on a schedule.

Packing strategy

A slab costs a 15-provider round trip to create and is accounted at 4 MiB per sector. That makes one-slab-per-small-object expensive on both counts.

The model is built for packing. Buffer small writes, concatenate them, erasure-code the buffer once, and give each logical object a byte range in the resulting slab:

// Three objects sharing one slab
{ id: objA, slabs: [{ id: slabID, offset: 0,       length: 1_048_576 }] }
{ id: objB, slabs: [{ id: slabID, offset: 1_048_576, length: 2_097_152 }] }
{ id: objC, slabs: [{ id: slabID, offset: 3_145_728, length:   524_288 }] }

Each object is retrieved independently; they simply happen to share a stripe. The trade-off is that the objects share a fate — the slab is a unit for repair and for deletion — so pack objects with similar lifetimes together.