All posts

Sell licence keys automatically: SellAuth, Stripe, Shoppex or your own store

Connect the shop you sell from and every paid order gets its licence keys at once, with nobody pressing anything. Refunds and chargebacks ban the keys by themselves. Setup for SellAuth, Stripe, Shoppex and your own server

3 min read

Selling software by hand gets old fast: a payment arrives, you open the panel, make a key, copy it, send it, and hope you didn't mix up two buyers. And a refund at 3 a.m. means a key that keeps working until you wake up. Connect your store to PWF Auth and that whole loop runs by itself: every paid order gets its keys straight away, and refunds take them back

PWF Auth never touches the money. Your store takes the payment and tells PWF Auth, which makes the keys and hands them back

Connect a store

  1. Open Stores in your panel, pick the application and choose the store. It gets its own address, like https://pwfauth.com/api/store/webhook.php?c=sc_…
  2. Follow the steps shown under that store (below) and paste the store's webhook secret in Settings. Every call must be signed with it: unsigned or wrongly signed calls are refused and counted on the page
  3. Add every product you sell there: its id in the store, and the keys it makes (length, PCs per key, and keys per item bought)

SellAuth

  • Copy your shop's webhook secret from Storefront → Configure → Miscellaneous and paste it in Settings
  • Set each product's deliverables to Dynamic, with the store's address as the dynamic webhook
  • The product id is SellAuth's product id, or productId:variantId for a single variant

SellAuth shows the keys to the buyer right after paying. It has no refund call, so when you refund there, mark the order Refunded in PWF Auth and its keys are banned

Stripe

  • In Stripe, Developers → Webhooks → Add endpoint with the store's address. Pick checkout.session.completed, checkout.session.async_payment_succeeded, charge.refunded and charge.dispute.created
  • Paste the endpoint's signing secret (whsec_…) in Settings
  • The product id is the Payment Link id (plink_…). With your own Checkout Sessions, set metadata.pwf_product

Stripe has no page to show the keys on, so they go to the buyer by email. A full refund or a chargeback bans the order's keys by itself, and test-mode orders work too, marked Test

Shoppex

  • Turn on dynamic delivery on the product, with the store's address as its webhook
  • Shoppex gives each product its own signing secret: paste it when you add that product in PWF Auth

Your own server

Selling from your own website, a script or an automation tool? Send one signed POST per paid order:

POST https://pwfauth.com/api/store/webhook.php?c=sc_…
Content-Type: application/json
X-PWF-Timestamp: 1760262000
X-PWF-Signature: <hex HMAC-SHA256(timestamp + "." + body, your secret)>

{"type": "paid", "order_id": "1001", "product": "pro-30", "email": "buyer@mail.com", "quantity": 1, "amount": 9.99, "currency": "USD"}

The answer is {"success": true, "keys": ["…"]}. Sending the same order_id again returns the same keys, so a retry never makes two sets. A refund is the same call with "type": "refund"

Every order on the record

The Stores page lists the last 50 orders and refunds, with the product, the buyer's email, the amount and the keys. From there you can deliver an order that waited for a missing product, email the keys again, or mark an order refunded, which bans its keys and closes the running copies. Keys from a store carry the store and the order in their note, and start counting the first time they're used

Every delivered order also reaches your webhooks as order.completed, so your own sales sheet stays up to date. Selling through people instead of a shop? See resellers

The full guide is in Stores

Protect your app for free

Licence keys, customer accounts and the kill switch, in every language. Make an account and sign in with your first key in a few minutes

Create a free account