Vault Salt
GET /api/v1/vault/saltAuth: Privy session (browser) only — an API key gets 403 privy_required.
Returns the per-user salt the browser credential vault mixes into its v2 key
derivation. The vault key is HKDF-SHA256(wallet signature, salt, "spreadr-vault-v2"). The wallet signature is deterministic over a fixed
payload, so without this salt a phished signature alone would decrypt a
user's client_encrypted_blobs (see Linked Exchanges).
The salt is released only to an authenticated browser session, held in
memory by the app for the session, and never persisted client-side.
Response
200 OK — Cache-Control: no-store
{
"salt": "<base64 of 32 random bytes>",
"version": 2
}| Field | Description |
|---|---|
salt | 32 random bytes, base64-encoded. Minted on your first read and immutable afterwards. |
version | The key derivation the salt is for — currently 2. Clients must refuse any other value rather than derive with it. |
| Status | Meaning |
|---|---|
403 | The request was authenticated with an API key (privy_required). |
404 | The caller has no user profile yet (sign in through the app first). |
Immutability
There is deliberately no rotation or reset endpoint: every v2
client_encrypted_blob of the user is keyed on this salt, so rotating or
losing it would orphan them all — the user would have to re-connect every
exchange. Concurrent first reads always agree on one salt (the mint is a
conditional write).
Example
curl -H "Authorization: Bearer <privy jwt>" https://api.spreadr.xyz/api/v1/vault/salt