List the documents you have in custody.
const url = 'https://testnet.permafrost.live/v1/api/custody/list';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://testnet.permafrost.live/v1/api/custody/list \ --header 'Authorization: Bearer <token>'Every custody object owned by the calling tenant, in the same shape
status returns. The list is scoped by the caller’s tenant; there is no
parameter that widens it.
Authorizations
Section titled “Authorizations”Responses
Section titled “Responses”Your custody objects.
object
The custody view of one held document. No key, key identifier, custody backend or owner appears here.
object
Sha256 of the plaintext — the hash the certificate names.
Sha256 of the stored ciphertext — the hash the verify route indexes.
True while the key lives and the document can still be served.
The complement of alive. True once the key has been destroyed.
When the key was destroyed, in UTC. null while it lives.
The on-chain certificate’s object id, once one has been minted.
The transaction that minted the certificate.
minted once the certificate exists. not_minted when the key was
destroyed and no certificate landed — the destruction is no less
final for it.
The claim the certificate makes, recorded on chain verbatim:
auditable_vendor_side. null while the document is alive.
Example
{ "objects": [ { "id": "3f2a9c18-5b7e-4d61-9a0c-8e2f1d4b6a37", "content_hash": "7d1a2b3c4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f9", "stored_hash": "0c9b8a7d6e5f40312213a4b5c6d7e8f90a1b2c3d4e5f6071829304b5c6d7e8fa", "alive": true, "incinerated": false, "incinerated_at": null, "certificate_object_id": null, "certificate_tx_digest": null, "certificate_status": "minted", "deletion_mode": null } ]}No tenant on the request. Through the public edge this is the edge’s own refusal of the credential; the custody surface’s own generic refusal has the same status and carries no hint about which header, which surface, or whether the id exists.
The refusal shape. detail is present on a few routes and deliberately
absent from the custody surface, where a detail string could carry an
internal path.
object
The code, or a short fixed sentence.
A human-readable note, where a route carries one.
Example
{ "error": "unauthorized"}The tenant is over an allowance. Retry-After carries whole seconds,
rounded up and never zero. The per-tenant refusal also carries
retry_after_ms; the custody surface’s own local limiter carries the
code alone. Both are per tenant, keyed by the tenant address — one
tenant spending its allowance does not consume another’s.
object
How long until one token is available, in milliseconds. Present on the per-tenant refusal.
Example
{ "error": "rate_limited", "retry_after_ms": 240}Headers
Section titled “Headers”Example
1Whole seconds to wait before retrying.
Permafrost runs on Sui testnet and Walrus testnet. Everything here describes a shipped testnet instance, not a production service.