Getting Started
Get started with Snowcone

@snowcone-app/sdk — there is no @snowcone-app/render or @snowcone-app/realtime package. The optional in-browser design editor is @snowcone-app/canvas.Render a mockup
Three values: a product, your artwork, and your Shop ID. It’s just an image URL — build it in any language, and it renders in under a second.
<img src="https://img.snowcone.app/BEEB77?asset=https%3A%2F%2Fcdn.example.com%2Fart.png&shop=YOUR_SHOP_ID" />const asset = encodeURIComponent("https://cdn.example.com/art.png");
const src = `https://img.snowcone.app/BEEB77?asset=${asset}&shop=YOUR_SHOP_ID`;
// drop `src` into any <img>curl -L "https://img.snowcone.app/BEEB77?asset=…&shop=YOUR_SHOP_ID" -o mockup.avifasset = urllib.parse.quote("https://cdn.example.com/art.png", safe="")
src = f"https://img.snowcone.app/BEEB77?asset={asset}&shop=YOUR_SHOP_ID"Already signed up? Your shop was created when you signed up — copy its ID at snowcone.app/studio/api-keys. It’s public, like a Cloudinary cloud name. No account yet? Mint one with a single API call — no signup required.
# Mint a Shop ID in one call — no signup required.
curl -X POST https://api.snowcone.app/shops/sandbox -H 'Content-Type: application/json' -d '{}'
# → { "shop_id": "ab3dPq7Rms", # use as &shop= right away
# "shop_secret": "scsec_…", # for signing URLs (see Public or signed)
# "api_key": "kQ7r…2Fb", # shop-scoped key for AI-gen / asset writes, returned ONCE
# "claim": { … } } # hand this to a human to claim the shop & set up payoutsMint once and reuse the Shop ID — one copied from these examples attributes sales to someone else. A sandbox shop lives 24 hours unclaimed; your human claims it at snowcone.app/activate. The full claim flow, rate limits, and lifecycle live on Get a Shop ID.
Every render tells you what it cost. Fetch the URL with curl -i and the response reports its cache status, render time, and price — your first render doubles as your first bill preview.
# Every render tells you what it cost — check the response headers.
curl -i -L -o mockup.avif "https://img.snowcone.app/BEEB77?asset=…&shop=YOUR_SHOP_ID"
# x-render-cache: miss ← first hit renders fresh
# x-render-ms: 742 ← server render time for this image
# x-render-cost-usd: 0.02 ← what this render cost you
# Run it again: x-render-cache: hit — cached repeats don't re-render.Show product info
The mockup shows what they’re buying. Pull the rest — name, price, description, variants — from the public catalog.
import { getProduct } from "@snowcone-app/sdk";
const product = await getProduct("BEEB77"); // any product code
product.name; // "Framed Canvas"
product.price; // 2399 (MSRP, in minor units / cents — suggested retail)
product.description; // string[] — paragraphs (not a single string)
// Plus the fields a realtime render needs:
product.mockups?.[0]?.id; // "FV1qjO" (a mockupId)
product.placements?.map((p) => p.label); // ["Front"] (placement labels)
const variantId = product.options?.combinations?.find((c) => c.variantId)?.variantId;curl https://search.snowcone.app/indexes/snowcone/documents/BEEB77 \
-H "Authorization: Bearer eee819b849798ad9091228c486ec05d0931e5292"const res = await fetch(
"https://search.snowcone.app/indexes/snowcone/documents/BEEB77",
{ headers: { Authorization: "Bearer eee819b849798ad9091228c486ec05d0931e5292" } },
);
const product = await res.json(); // { id, name, price, mockups, placements, options, … }import requests
product = requests.get(
"https://search.snowcone.app/indexes/snowcone/documents/BEEB77",
headers={"Authorization": "Bearer eee819b849798ad9091228c486ec05d0931e5292"},
).json()getProduct(id) (see the SDK tab above) is just a typed convenience wrapper over this same public Meilisearch catalog — same data, same index, same public read key. Reach for whichever ergonomics you prefer.Start from a pre-made design
No artwork yet? Don’t start blank — the designs catalog is every published, remixable marketplace design, each already paired with a product. Render one by reference — design=<id> — from every shop, including a freshly minted sandbox, with zero configuration and for free: catalog renders never count against your usage budget, so your first beautiful mockup is one search away.
# Search the pre-made designs catalog (same public key, second index).
curl "https://search.snowcone.app/indexes/snowcone-designs/search" \
-H "Authorization: Bearer eee819b849798ad9091228c486ec05d0931e5292" \
-H "Content-Type: application/json" \
-d '{ "q": "christmas card", "limit": 5 }'
# Each hit carries URL components — productId + asset URLs. Compose with YOUR shop:
# https://img.snowcone.app/<productId>?asset.front=<assets.front>&shop=YOUR_SHOP_IDThe SDK wraps this as searchDesigns(query), and the MCP server’s snowcone_search_designs tool returns ready-to-render URLs for your shop.
Set your own margins
Every product has an MSRP — the Framed Canvas is $24 — which is also your default cost, so selling at MSRP earns $0. Raise your retail price, lower your cost with a wholesale tier, or both; Pricing & margins covers the levers.
Publishable vs secret
Everything above used exactly one credential: your Shop ID. It is the publishable key — public by design, safe to hard-code in client-side HTML, like a Stripe publishable key or a Cloudinary cloud name. Its counterpart is the secret key (sk_…): server-side only, owned by your organization, scoped to one shop, and carrying scoped permissions (mockups:realtime, catalog:read, orders:add, …). You only need one when you call api.snowcone.app — orders, uploads, AI, realtime grants. Both live at snowcone.app/studio/api-keys; the full credential map is on Authentication.
Public or signed
Your Shop ID is public by default — safe to expose, and once you lock it to your asset origins, the worst a stolen ID can do is re-render your own catalog. Want only URLs your server minted to render? Add an HMAC signature on top: Signed URLs. The full ladder, rung by rung, is on How Snowcone works.
Explore
There are many more ways to build a business on Snowcone — unlimited sales channels and business models. A few places to go next:

