Account/Data Export

Exporting your data

An export is a single JSON file describing what the account holds: its Cells, databases, buckets, domains, API tokens, webhook endpoints, members, and the last 30 days of activity. Download it from Account → Overview → Export account data, or call the API.

curl -L -H "Authorization: Bearer $TISSUE_JWT" \
  -o tissue-export.json \
  https://api.tissue.systems/v1/account/export

The file is served as an attachment named tissue-export-<account_id>-<YYYY-MM-DD>.json.


What the export is, and what it is not

It is metadata, not content. The export lists the things the account owns; it does not contain them.

In the file Not in the file
Cell names, addresses, bindings, deploy timestamps Cell source code
Database names Database rows — use ribo db exec "<sql>"
Bucket names Objects — use ribo bucket cp or the S3 API
Custom domains and their status
API token ids, names, scopes, creation and last-use times Token values, which exist only at creation
Members with roles and join dates Password hashes, TOTP secrets, recovery-code digests, invite tokens
Webhook endpoints Captured request bodies — read those through the vesicle API
Up to 1000 activity events from the last 30 days Anything older than the 30-day activity window

No credential and nothing close enough to one to be attacked offline leaves this endpoint. An export is a file people mail to themselves.


Rules the endpoint enforces

A signed-in session is required. GET /v1/account/export refuses a tok_ API token with "Export requires a signed-in session." — a whole-account snapshot should take the credential a person holds, not one left in a CI runner. Use the dashboard button, or a JWT from ribo login.

One export per five minutes per account. A second call inside the window answers 429 with Retry-After: 300.

A null block means unavailable, not empty. The members block is assembled by a different service from the rest of the file. When that call fails, the key is null rather than [], so an export never quietly reports an account as having no members when the truth was that nobody could be asked.


Shape of the file

{
  "exported_at": "2026-08-12T18:04:11Z",
  "account": { "id": "acct_…", "name": "Acme", "email": "ada@example.com", "subdomain": "strand-9c" },
  "members": [ { "email": "…", "role": "owner", "joined_at": "…" } ],
  "cells": [],
  "databases": [],
  "buckets": [],
  "domains": [],
  "tokens": [ { "id": "…", "name": "CI", "scopes": ["cells:read"], "created_at":, "last_used_at":} ],
  "vesicle_endpoints": [],
  "events": []
}

Blocks may gain keys over time. Read the ones you need by name rather than by position.


See also