Certification status for one object.
const url = 'https://testnet.permafrost.live/v1/api/meta/objects/42';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/meta/objects/42 \ --header 'Authorization: Bearer <token>'A 404 here means “not yours, or not there”, and the two are one
answer. An id owned by another tenant is refused exactly as an id that
was never stored, so this route cannot be used to find out what other
tenants hold.
Read state to know where the object stands:
| State | Meaning |
|---|---|
PENDING |
Accepted. Certification has not started. |
UPLOADING |
Certification in flight. |
SYNCED |
Certified on Walrus; the blob id is known. |
FAILED |
Certification ended in an error. |
DELETED |
Marked deleted. Treat it as absent. |
blob_id, walrus_epoch and synced_at are null until the object
reaches SYNCED.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Example
42The object identifier returned at upload time.
Responses
Section titled “Responses”The object’s certification metadata.
The eight fields the /v1/ contract exposes for a stored object.
Internal columns are not part of this shape.
object
The object identifier.
Where the object stands. SYNCED is the state in which it has cleared
certification on Walrus and its blob id is known.
The Walrus blob identifier. null until the object reaches SYNCED.
The Walrus epoch at which certification was recorded. null until SYNCED.
When the object reached SYNCED, in UTC. null before that.
When the object was first accepted, in UTC.
Object size in bytes.
The type recorded at upload time.
Examples
Certified — the blob id is known.
{ "id": 42, "state": "SYNCED", "blob_id": "9c4f3b2a1d0e8f7c6b5a4d3e2f1c0b9a8d7e6f5c4b3a2918", "walrus_epoch": 137, "synced_at": "2026-09-13T14:08:21Z", "created_at": "2026-09-13T14:07:55Z", "size_bytes": 1048576, "content_type": "image/png"}Not certified yet.
{ "id": 43, "state": "PENDING", "blob_id": null, "walrus_epoch": null, "synced_at": null, "created_at": "2026-09-13T14:09:01Z", "size_bytes": 524288, "content_type": "application/pdf"}The credential was not accepted. Every cause answers this same status with this same body — absent, malformed, unknown key, revoked key, unconfigured issuer, bad signature, wrong audience, expired token, or a subject that is not a canonical Sui address. The refusal is made at the edge, before the request reaches a service.
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": "Invalid or inactive API key"}The credential is real but the tenant it names has been revoked. Revoking a tenant closes both lanes at once — key and token.
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": "Tenant inactive or not found"}No such object, or an object the calling tenant does not own. The two are deliberately one answer, so this route cannot be used to learn what other tenants hold.
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": "not_found", "detail": "Object not found"}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.
Something failed on the instance. The reason is logged there, not returned.
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": "internal_error"}Permafrost runs on Sui testnet and Walrus testnet. Everything here describes a shipped testnet instance, not a production service.