sellkeys/ Documentation

Documentation

Everything you need to sell with sellkeys and license your software.

Create a shop

Sign up, create a shop in the dashboard and pick an address. The shop is available right away at <name>.sellkeys.cc.

You set the name, logo, design, legal texts and notifications under Settings. With Pro you connect a custom domain (Settings → Custom domain) and get webhooks, API and unlimited products.

Connect Coldsweep

Payments run through Coldsweep, a non-custodial crypto gateway: buyers pay straight to your wallets, sellkeys never holds your money.

Click “Payments not connected” at the top of the dashboard, sign in to Coldsweep and allow access. sellkeys creates your store there and receives every confirmed payment via webhook; after that, delivery happens automatically.

As long as Coldsweep is not connected, your shop cannot sell anything.

Products

TypeDelivery
KeysOne key per line in stock; after payment, one key per item is sent out automatically.
FileThe buyer downloads the file after payment.
ServiceThe buyer receives your fixed text, e.g. instructions or an invite link.
Dynamicsellkeys sends the signed order to your URL and delivers your response.
LicenseGenerates a license key for your Auth app on payment.

You set up variants with their own price and stock, addons, bundles, coupons and subscriptions in the catalog.

Webhooks

Under Settings → Webhooks & API (Pro) you enter an https URL and choose the events. sellkeys sends JSON via POST and retries failed deliveries several times.

Events: order.delivered, subscription.created, subscription.renewed, subscription.cancelled, subscription.expired, license.created, license.activated, license.banned, auth.user_registered.

License events contain licenses (id, app, key, level, status, expires_at, devices …), registrations additionally user (id, username).

Signature: X-Sellkeys-Signature: sha256=<HMAC-SHA256(Body, Webhook-Secret)>. Verify it before you use the body.

API keys

Under Settings → Webhooks & API you create an API key (Pro). Send it as Authorization: Bearer sk_…; bodies are JSON.

Call
GET /api/v1/productsProducts with variants and stock
POST /api/v1/products/{id}/stockTop up keys: {"keys": ["…"]}, up to 5000 per call
GET /api/v1/orders?limit=&before=Orders, newest first
POST /api/v1/license/verifyCheck a purchased key: {shop, key, hwid?}, no API key needed

MCP

sellkeys is an MCP server: https://sellkeys.cc/mcp (sign-in via OAuth). Connect it to Claude or another MCP client and manage products, stock, orders, customers, coupons, subscriptions, tickets and licenses in chat.

License tools: list_auth_apps, auth_stats, create_licenses, find_license, license_action, auth_user_action.

Auth: client API

License checking for your software: your program starts a session, signs in with a license key and the hardware ID, and re-checks from time to time. Licenses come from purchases (product type License) or are generated in the dashboard (Auth → Licenses). App ID and public key: Dashboard → Auth → Apps.

Endpoint: POST https://auth.sellkeys.cc/v1 with a form or JSON body. Every request contains type, app (app ID) and nonce (16–128 characters [A-Za-z0-9_-], new for every request).

Responses are JSON: success, code, message, further fields, nonce and time.

Verify responses (required)

Every response carries the header X-Sellkeys-Signature: the Base64 Ed25519 signature of the exact body bytes, created with your app's private key. Verify it with the app's public key and check that nonce matches the nonce you sent. Otherwise discard the response: this stops fake servers, proxies and replayed “login ok” responses.

Only errors that occur before the app is known (unknown_app, bad_nonce, rate_limited) come without a signature. Never treat an unsigned response as a success.

Calls

typeFields and result
initversion, optional hash (SHA-256 of your program file). Returns session and app (name, version, update_url).
licensesession, key, hwid. Checks the key, ban and expiry, binds the hardware ID up to the device limit and activates the key on first use. Returns license (level, expires_at, devices, device_limit).
registersession, username, password, key, hwid. Creates an account and redeems the key on it (one key = one account). Only if the app allows accounts.
loginsession, username, password, hwid. Requires at least one valid license on the account.
upgradesession, username, key. Redeems another key on an account (renewal, higher level).
checksession. Re-checks the license or account of the session; call it every few minutes.
varsession, name. Global variable from the dashboard; those marked “after login only” require a signed-in session.
getvar / setvarsession, name, value (max. 4000 characters). Variables per account, at most 50.
filesession, file. Returns name, size, sha256 and a download url valid for 5 minutes. Compare the SHA-256 before use.
webhooksession, webid, optional params and body. sellkeys calls the stored URL so that API keys never end up in your program. Returns status and response.
logsession, message (max. 500 characters). Appears under Auth → Logs.
logoutsession. Ends the session.

Error codes

codeMeaning
unknown_app, bad_noncewrong app ID or missing nonce (unsigned)
rate_limitedtoo many requests from this IP (unsigned, HTTP 429)
app_paused, app_disabledyou paused or disabled the app
update_requiredversion below the minimum version; see update_url
hash_mismatchprogram file hash not approved
invalid_sessionsession unknown or expired, call init again
invalid_keythe key does not exist for this app
hwid_required, hwid_mismatchhardware ID missing or device limit reached
blacklistedIP, country or hardware ID is on the app's blacklist
register_disabledthe app does not allow accounts
invalid_username, weak_password, username_takenregistration input
key_usedkey is already redeemed on an account
invalid_credentialswrong username or password
user_banned, no_active_licenseaccount banned or no valid license left
not_logged_inthe call requires a signed-in session
var_not_found, file_not_found, level_too_lowContent
webhook_not_found, webhook_failed, invalid_paramsWebhook proxy
license_banned, license_expiredLicense banned or expired

SDKs

All SDKs implement the complete protocol (signature and nonce checks, hashed device ID, file download with SHA-256 check), with the same method names and error codes. Each file starts with a short example.

LanguageFileDependencies
C# (.NET 6+)SellkeysAuth.csBouncyCastle.Cryptography
Unity 2021.2+ (C#)SellkeysAuthUnity.csSellkeysAuthExample.cscom.unity.nuget.newtonsoft-json, BouncyCastle.Cryptography.dll
C++17sellkeys_auth.hpplibcurl, libsodium, nlohmann/json
Python 3sellkeys_auth.pyrequests, cryptography
JavaScript (Node.js 18+)sellkeys-auth.mjsnone
TypeScript (Node.js 18+)sellkeys-auth.tsnone
PHP 7.4+SellkeysAuth.phpext-curl, ext-sodium
Rustsellkeys_auth.rsureq 2, ed25519-dalek 2, sha2, base64, getrandom, serde_json
Java 17+SellkeysAuth.javanone
Go 1.21+sellkeys_auth.gonone
Lua 5.1–5.4 / LuaJITsellkeys_auth.lualuasocket, lua-cjson, luasodium, luasec
Perl 5.14+SellkeysAuth.pmCryptX, IO::Socket::SSL

License API

Manage licenses from your own backend (Pro), with the same API key.

Call
GET /api/v1/auth/appsApps with ID, public key and totals
GET /api/v1/auth/licenses?app=&status=&limit=&offset=List, newest first; status = unused, active, expired or banned
GET /api/v1/auth/licenses?key=…look up a key
POST /api/v1/auth/licensesGenerate keys: {app, count?, level?, days?, devices?, mask?, note?}
GET · POST · DELETE /api/v1/auth/licenses/{id}read, change (reset, ban, unban, extend with days) or delete
GET /api/v1/auth/users · POST · DELETE /api/v1/auth/users/{id}List, reset, ban or delete accounts
GET · PUT · DELETE /api/v1/auth/varsglobal variables

Moving from KeyAuth

Export your licenses as CSV and import them under Auth → Licenses → Import. Recognized columns: key/license, level, days/duration, expires, note, hwid, banned/status; a file with one key per line works too.

Keys with a hardware ID are imported as active and bound to it. Accounts with passwords cannot be carried over: users register again with their key.