Skip to content

proven on the hosted testnet instance · 2026-09-13 · QA-14

Onboard with an invite

A tenant of your own on the hosted instance, and one key — pf_sk_… — that authenticates every request you make. Buckets you create are yours, objects you store are isolated under that tenant, and another tenant holding a perfectly valid credential of its own is refused on read, list, write and delete.

The key is shown once, in the answer to the call you make. It is not stored anywhere you can read it back from and it is never mailed to you.

  • A one-time link from us. Ask at hello@permafrost.live, with a window. Invites expire, so ask when you are ready to use it.
  • A Sui address. You choose it and send it in the request body.
  • curl, and the instance up — see The testnet instance.

It looks like this, with an unguessable token in the middle:

https://testnet.permafrost.live/invites/<token>/redeem

The token is the credential. Nothing else stands between it and a tenant, so treat it the way you would treat the key it becomes: out of band, to one person, once. It works exactly one time.

A POST to that same URL, carrying the address you want the tenant to be:

Terminal window
curl -sS -X POST \
-H 'Content-Type: application/json' \
-d '{"sui_address":"0x<your 64 hex characters>"}' \
https://testnet.permafrost.live/invites/<token>/redeem

display_name is accepted as well and is only a label.

On this testnet instance the address is a format-checked identifier you choose, not one you have proven you own. Nothing challenges you to sign with it. It is what your tenant is named and keyed by; treat it as an identifier for now, and expect an ownership challenge before any of this is asked to carry value.

A successful redemption answers 201:

{
"tenant_address": "0x…",
"tier": "free",
"raw_key": "pf_sk_…",
"key_id": "",
"key_prefix": "pf_sk_…",
"permissions": ["read", "write"]
}

raw_key is the whole credential and it appears here and nowhere else. Put it somewhere safe before you close the terminal. tier and permissions come from the invite we minted, never from your request — you cannot ask for more in the body than the link was granted.

If you lose it, you have not lost the tenant: rotate from the portal or ask us. See Keys, rotation, and the portal.

One answer covers every failure:

{ "error": "invalid or expired invite" }

Expired, already redeemed, revoked, never existed, malformed body — all of them, identically. That is deliberate: a caller who could tell them apart could probe for live tokens. It means the response will not tell you which one happened, so if you believe the link should work, ask us rather than retrying.

Two things worth knowing about that 400. A malformed attempt does not burn the invite, so a typo in the address is recoverable. And a redemption may only create a fresh tenant — if the address you sent already has a tenant here, the redemption is refused with the same generic 400 rather than attaching a key to the existing one. Use an address you have not redeemed with before.

Too many attempts in a row from one place answer 429 {"error":"too many attempts, retry later"} instead. Wait, then try once.

5. Put the key where the quickstart expects it

Section titled “5. Put the key where the quickstart expects it”
Terminal window
export PF_SK=pf_sk_

Then go to the Quickstart and source the blocks in order. The first one reads PF_SK into the bearer header every later command sends.

The bucket call at the top of the quickstart answers 200 for your key. That is the whole check: the edge validated the credential, resolved it to your tenant, and the storage layer created a bucket that belongs to it.

An unauthenticated request to the same host answers 401. That is the edge working, not an outage — Headers, status codes, 401 and 429 has the rest.

If your users already hold Sui addresses and you already sign something for them, you may not want a key at all. Bring your own issuer skips the invite entirely: a tenant per user, on first use, with nothing shown once and nothing to store.

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