Get startedQuickstart
Sell your first key
with the API.
Create a product, give it keys, put it on sale, and have your server told the moment someone pays. Everything here runs in test mode: the checkout uses a simulated payment and no money moves.
Step 1: Make two API keys
In the dashboard, open Developers, API keys. Make a live key with products:write (a live key asks for your two-factor code, and needs a reviewed store), then a test key with stock:write and webhooks:write. Each key is shown once; keep them in your server's environment, never in a browser or an app.
ANYSHOP_LIVE_KEY=as_live_7Fq2...Q7pX
ANYSHOP_TEST_KEY=as_test_M4c9...b2RtStep 2: Create the productlive key
A product starts as a draft. Its price is an integer in minor units of your store's currency: 1999 is $19.99. Send an Idempotency-Key so a retry after a timeout never makes two products.
curl https://api.anyshop.io/v1/products \
-H "Authorization: Bearer $ANYSHOP_LIVE_KEY" \
-H "Idempotency-Key: first-product-1" \
-H "Content-Type: application/json" \
-d '{
"name": "Lumen Studio Pro",
"type": "serial",
"category": "software_licenses",
"price": 1999,
"platform": "Windows and macOS",
"delivery_instructions": "In Lumen Studio Pro, choose Help, Enter license key, and paste this key."
}'{
"object": "product",
"id": "prod_01m3rr5kmbeb2s18x1kpntjxqb",
"slug": "lumen-studio-pro",
"status": "draft",
"currency": "USD",
"variants": [
{ "id": "var_01m3rr5kmd6h0q2t8w4y9zb7ce", "name": "Standard", "price": 1999 }
],
"published_at": null
}Step 3: Add test keys to its stocktest key
Keys go into the stock of the mode your API key is in, so these are test keys: only test checkouts can sell them. Duplicates within the upload and keys already in stock are left out and counted, never added twice.
curl \
https://api.anyshop.io/v1/products/prod_01m3rr5kmbeb2s18x1kpntjxqb/stock_items \
-H "Authorization: Bearer $ANYSHOP_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{ "keys": ["TEST1-K2LM-3F9Q", "TEST2-P8WN-4H7R", "TEST2-P8WN-4H7R"] }'{
"object": "stock_upload",
"product": "prod_01m3rr5kmbeb2s18x1kpntjxqb",
"livemode": false,
"submitted": 3,
"added": 2,
"repeated_in_upload": 1,
"already_in_stock": 0
}Step 4: Put it on salelive key
Publishing makes the product active. A serial key product can go on sale with no stock in a mode; it shows as sold out there until keys arrive.
curl -X POST \
https://api.anyshop.io/v1/products/prod_01m3rr5kmbeb2s18x1kpntjxqb/publish \
-H "Authorization: Bearer $ANYSHOP_LIVE_KEY"Step 5: Tell anyshop where to send eventstest key
Add a webhook endpoint for order.paid. It must be a public https address; anyshop never follows redirects or calls private networks. The answer holds the signing secret, shown this once.
curl https://api.anyshop.io/v1/webhook_endpoints \
-H "Authorization: Bearer $ANYSHOP_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://api.pixelforge-supply.com/anyshop",
"events": ["order.paid"] }'{
"object": "webhook_endpoint",
"id": "whe_01m3rs9d2f4k6m8p0r2t4v6x8z",
"livemode": false,
"signing": "hmac",
"status": "enabled",
"secret": {
"object": "webhook_secret",
"algorithm": "hmac",
"value": "whsec_Q3s9mV1...kP4="
}
}Step 6: Verify, then act
Events are signed with Standard Webhooks, so any Standard Webhooks library checks them. Verify against the raw body, answer with a 2xx quickly, and do the slow work after. The same event can arrive twice: use its webhook-id header to do the work once.
import express from "express";
import { Webhook } from "standardwebhooks";
const webhook = new Webhook(process.env.ANYSHOP_WEBHOOK_SECRET); // whsec_...
const app = express();
app.post("/anyshop", express.raw({ type: "application/json" }), (req, res) => {
let event;
try {
event = webhook.verify(req.body, req.headers);
} catch {
return res.sendStatus(400);
}
if (event.type === "order.paid") {
// yours: do it once per req.headers["webhook-id"]
grantAccess(event.data.buyer.email, event.data.items);
}
res.sendStatus(204);
});
app.listen(3000);Step 7: Buy it yourself
On the dashboard home, choose Buy it yourself (once you have made a test purchase, the button leaves the home page: open app.anyshop.io/test-purchase instead). It opens a test checkout for your newest product; pay with the simulated rail's Succeeds. The key is delivered on the spot, and your server gets this:
{
"type": "order.paid",
"timestamp": "2026-10-02T14:32:05.112Z",
"data": {
"object": "order",
"id": "ord_01m3rt5x2c7q9f0a4d6k8h1n3p",
"number": 1001,
"livemode": false,
"status": "paid",
"currency": "USD",
"total": 1999,
"buyer": { "email": "you@pixelforge.dev" },
"paid_with": "simulated",
"items": [
{
"product": { "id": "prod_01m3rr5kmbeb2s18x1kpntjxqb", "name": "Lumen Studio Pro" },
"quantity": 1,
"unit_amount": 1999
}
]
}
}