Skip to content

List the documents you have in custody.

GET
/v1/api/custody/list
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.

Your custody objects.

Media typeapplication/json
object
objects
required
Array<object>

The custody view of one held document. No key, key identifier, custody backend or owner appears here.

object
id
required
string format: uuid
content_hash

Sha256 of the plaintext — the hash the certificate names.

string | null
stored_hash

Sha256 of the stored ciphertext — the hash the verify route indexes.

string | null
alive
required

True while the key lives and the document can still be served.

boolean | null
incinerated

The complement of alive. True once the key has been destroyed.

boolean | null
incinerated_at

When the key was destroyed, in UTC. null while it lives.

string | null format: date-time
certificate_object_id

The on-chain certificate’s object id, once one has been minted.

string | null
certificate_tx_digest

The transaction that minted the certificate.

string | null
certificate_status
required

minted once the certificate exists. not_minted when the key was destroyed and no certificate landed — the destruction is no less final for it.

string
Allowed values: minted not_minted
deletion_mode

The claim the certificate makes, recorded on chain verbatim: auditable_vendor_side. null while the document is alive.

string | null
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.

Media typeapplication/json

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
error
required

The code, or a short fixed sentence.

string
detail

A human-readable note, where a route carries one.

string
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.

Media typeapplication/json
object
error
required
string
retry_after_ms

How long until one token is available, in milliseconds. Present on the per-tenant refusal.

integer
>= 1
Example
{
"error": "rate_limited",
"retry_after_ms": 240
}
Retry-After
integer
>= 1
Example
1

Whole seconds to wait before retrying.

Permafrost runs on Sui testnet and Walrus testnet. Everything here describes a shipped testnet instance, not a production service.