Stores

SellAuth, Stripe, Shoppex or your own site: paid orders get their keys at once.

Connect the shop you sell from, and every paid order gets its keys at once, with nobody pressing anything. PWF Auth never touches the money: your store takes the payment and tells PWF Auth, which makes the keys and hands them back. It works with SellAuth, Stripe, Shoppex and your own server (any site, script or Zapier-like tool). Everything is on the Stores page.

Connect a store

  1. On the Stores page pick the application, choose the store and press Connect. The store gets its own address, https://pwfauth.com/api/store/webhook.php?c=sc_….
  2. Follow the steps shown under the store (they differ per store; see 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. Press Add product for every product you sell there: its id in the store, and the keys it makes (length, PCs per key, and keys per item bought).
An order of a product you have not added yet is not lost: it waits under Orders as "Waiting for you". Add the product, then press Deliver on the order (or use the store's own "redo delivery").

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 (that one wins when both are added).

SellAuth shows the keys to the buyer right after paying, one per line. SellAuth has no refund call: when you refund there, press Refunded on the order here 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 (and pwf_quantity for several).

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; a partial refund keeps them. Test-mode orders work and are 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, shown once when you save it there. Paste it when you add that product here.

Shoppex shows the keys to the buyer right after paying. Like SellAuth, mark refunds on the order here.

Your own server

Connecting it makes a secret for you (shown once; New secret in Settings replaces it). Send one signed POST per paid order:

HTTP
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" and the order id. The timestamp must be within 5 minutes.

PHP
$body = json_encode(['type' => 'paid', 'order_id' => $id, 'product' => 'pro-30', 'email' => $email]);
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, getenv('PWF_STORE_SECRET'));
// POST $body with the headers X-PWF-Timestamp: $ts and X-PWF-Signature: $sig

Orders

The 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 a waiting order, Email the keys again, or mark an order Refunded (its keys are banned and running copies close). Keys from a store show in Licences with the store and order in their note, and start counting the first time they are used. A store that is switched off in Settings tells the buyer delivery is paused.

Every delivered order also goes to your Webhooks as order.completed (and order.refunded), and keys from a store take the Discord buyer role back once they are banned.

Something missing or unclear? Tell us on Telegram.