Secret API keys
Applies to @snowcone-app/sdk@0.17.0
What a secret key is
Some calls run on your server and bill to your organization — minting a realtime render grant, creating an order, requesting an upload URL. Those are authorized by a secret API key — Stripe-shaped, written sk_… in these docs — that you keep server-side and never expose to the browser. It is not the publishable shop.id (safe to expose, like Stripe’s pk_) and it is not the scsec_… shop secret used for signing image URLs— the full credential map is on Authentication.
sk_… by Stripe-style convention. The dashboard shows you the full key once at creation; treat whatever it gives you as the secret and store it as SNOWCONE_API_KEY. Match on the value the dashboard returns, not a hard-coded sk_ prefix.Create a key
Agents: you already have one. Minting a sandbox shop returns a shop-scoped api_key (scopes ai:generate, ai:bg-remove, uploads:write, mockups) that works immediately — AI generation and uploads with no human in the loop. It is revoked automatically when the shop is claimed. Mint/claim details live on Get a Shop ID.
Beyond that auto-issued sandbox key, keys are issued from the dashboard by a signed-in owner or admin of the organization. The flow:
Claim a shop
api_key, so this is where the human re-issues the agent a least-privilege key.Open the API keys page
shop.id and a one-click Create shop if you don’t have one yet.Name it and pick scopes
mockups:realtime for a live preview, orders:add for your own checkout. Optionally set an expiry.Copy it once
SNOWCONE_API_KEY). If you lose it, revoke it and create a new one. Revoked or expired keys stop working immediately.api_key covers AI generation, background removal, uploads, and mockups until the shop is claimed — see Get a Shop ID.Use a key
The SDK helpers take the key as an option and keep it server-side. For realtime, the key mints a short-lived grant the browser uses — the key itself never ships to the client:
// YOUR backend. The secret key never reaches the browser — it mints a
// short-lived grant the client uses (see /realtime).
import { mintRealtimeGrant } from '@snowcone-app/sdk';
export async function POST(req: Request) {
const { shop } = await req.json();
const grant = await mintRealtimeGrant({
apiKey: process.env.SNOWCONE_API_KEY!, // the secret key, with mockups:realtime
shop, // a shop your key's org owns
});
return Response.json(grant); // { token, expiresAt }
}Other server-side endpoints accept the key directly as an x-api-key (or Authorization: Bearer) header:
# Other server-side APIs take the key directly as a header.
curl https://api.snowcone.app/orders -X POST \
-H "x-api-key: $SNOWCONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "json": { "reference": "order-1", "items": [], "shipTo": {} } }'Scopes
A key may call only the endpoints its scopes allow; a call outside its scopes is rejected (403 — API key does not have required scope). Grant the least set you need.
Available scopes
mockups:realtimescopemockups is also accepted for realtime.mockupsscopecatalog:readscopeorders:addscopeorders:readscopeorders:shipscopeuploads:writescopePOST /uploads/base64, scoped to the key’s shop (assets land at your-shop-id.storage.snowcone.app — already renderable). Self-serve: a sandbox shop’s key carries this scope.ai:generate · ai:bg-remove · ai:videoscopedmca:readscope
