Connect your app
Every request carries one bearer credential:
Authorization: Bearer <token or key>Use your issuer for real users, an invite key for a first try. Both behave the same. For AWS SDKs and tools, either one mints S3 access keys.
Your issuer (the integration path)
Section titled “Your issuer (the integration path)”Your users’ signed tokens are their credentials: no per-user keys to store or rotate. A user’s tenant appears with their first valid token.
What you send us
Section titled “What you send us”One JSON object per issuer, to hello@permafrost.live:
{ "issuer": "https://issuer.example/", "jwks_url": "https://issuer.example/.well-known/jwks.json", "audience": "<your deployment's audience>"}issuer and jwks_url are yours. audience is the value we give you for your deployment. Tokens are refused until we enable the issuer and confirm by email.
To bind an issuer to its own address (a backend service signing only for itself), add "subjects": "self" and "subject": "<its Sui address>". Its tokens for any other tenant are refused.
What a token carries
Section titled “What a token carries”- Ed25519 signature (
alg: EdDSA),kidnaming a key in your JWKS. issandaudmatching what you sent.exp, andnbfif used. Small clock skew is tolerated.sub= the user’s Sui address (0x+ 64 lowercase hex). That address is the tenant.
Every refused token gets the same 401. Test tokens against your JWKS first; tell us before rotating signing keys.
Check it worked
Section titled “Check it worked”Create a bucket with a token: 200 means you’re in. A fresh token for the same sub sees the same bucket.
An invite key (a first try)
Section titled “An invite key (a first try)”Redeem our one-time link with your tenant’s address:
curl -sS -X POST \ -H 'Content-Type: application/json' \ -d '{"sui_address":"0x<64 hex characters>"}' \ https://c1.permafrost.live/invites/<token>/redeemUse your deployment’s host. The 201 carries raw_key (pf_sk_…), shown once. The link works once; a failure returns a generic 400.
An invite key is read-only or read-write; we set that when we send the link, and read-only is the default. A read-only key lists, reads and checks receipts; any write (PUT, DELETE, multipart, bucket changes) gets 403 AccessDenied. Ask for read-write if your first try stores data.
With a read-write invite, add "s3_keys": true to also get an S3 access-key pair (access_key_id, secret_access_key, shown once). A read-only invite can’t mint one:
-d '{"sui_address":"0x<64 hex characters>","s3_keys":true}'On testnet, ownership of the address isn’t checked. Lost the key? Rotate it on your deployment page or ask us.
S3 access keys (for SDKs and tools)
Section titled “S3 access keys (for SDKs and tools)”Mint a pair with either bearer (an invite key must be read-write):
curl -sS -X POST -H "Authorization: Bearer $PF_SK" https://c1.permafrost.live/me/s3-keysThe 201 carries access_key_id (PFAK…) and secret_access_key, shown once. Use any region and path-style addressing (or virtual-hosted, where your deployment has it on); SDK and CLI settings are in S3 compatibility. A pair serves the tenant that minted it; DELETE /me/s3-keys/<id> revokes it at once.
Run the Quickstart with your credential, or read S3 and identity.
Permafrost runs on Sui testnet and Walrus testnet. Everything here describes a shipped testnet instance, not a production service.