From 2a0e179c43dc3bc7a9998c9a7e338e9d4219d96f Mon Sep 17 00:00:00 2001 From: Keysat Date: Wed, 17 Jun 2026 15:24:55 -0500 Subject: [PATCH] Fix change-tier API example and move install steps to the admin UI --- agent.html | 13 +++++++------ install.html | 14 +++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/agent.html b/agent.html index 89f872b..fd6f61b 100644 --- a/agent.html +++ b/agent.html @@ -64,8 +64,8 @@ curl -X POST https://your-keysat-host/v1/admin/api-keys \ -d '{"label":"Support bot","role":"support"}' # Response includes `token: ks_...`. Save it. It's only shown once. -# 3. Use the scoped key -curl https://your-keysat-host/v1/admin/licenses?status=active \ +# 3. Use the scoped key (admin/licenses requires a product_id) +curl "https://your-keysat-host/v1/admin/licenses?product_id=<uuid>" \ -H "Authorization: Bearer ks_..."

Authentication

@@ -245,11 +245,12 @@ curl -X POST $KS/v1/admin/subscriptions/$SUB_ID/cancel \
curl -X POST $KS/v1/admin/licenses/$LICENSE_ID/change-tier \
   -H "Authorization: Bearer ks_..." \
   -d '{
-    "target_policy_slug": "pro",
+    "to_policy_slug": "pro",
+    "skip_payment": true,
     "reason": "support resolution"
   }'
-

Always applies as comp (no invoice) from the admin path. Buyer-initiated paid upgrades go through /v1/upgrade (different endpoint, signed-license auth).

-

Scope required: licenses:write.

+

With skip_payment: true this applies as a comp (no invoice). Omit it (defaults to false) and the admin path behaves like the buyer path: it creates an invoice for the prorated charge and returns the checkout URL. Buyer-initiated paid upgrades go through /v1/upgrade (different endpoint, signed-license auth).

+

Master admin key required.

Connect BTCPay programmatically (sandbox)

On a sandbox daemon (KEYSAT_SANDBOX_MODE=1), a scoped key carrying payment_providers:write can connect a BTCPay store over the API with no browser step, as long as the store settles on a non-mainnet network (regtest / testnet / signet). On a production daemon, or for a mainnet store, connect stays master-only. This is the path a delegated setup agent uses to stand up a disposable test instance end to end. You need a BTCPay API key for the target store (the operator's BTCPay access, delegated to you) carrying the same store and invoice permissions the browser flow grants (see Install & setup): the store-settings permissions complete the connect, and the invoice permissions let settled purchases issue licenses.

@@ -375,7 +376,7 @@ def verify(body_bytes: bytes, signature_header: str, secret: str) -> bool:

List endpoints return up to ~100 rows by default. Use ?limit=N and ?offset=N for larger result sets. The OpenAPI spec documents the limits per endpoint.

Rate limits

-

The admin endpoints have no per-IP rate limit today. Operators are trusted. The public endpoints (/v1/validate, /v1/recover) are rate-limited per client IP (10/min for /recover; /validate is unlimited but a reasonable agent calls it once per app boot + once per hour).

+

The admin endpoints have no per-IP rate limit today. Operators are trusted. The public endpoints (/v1/validate, /v1/recover) are rate-limited per client IP (10/min for /recover; /validate allows a 60/min burst per client IP, which a reasonable agent stays well under by calling it once per app boot + once per hour).

Master key handling

If your automation needs full-admin because it touches operator-only operations (creating other API keys, changing payment providers), use the master key from a secret manager. If it can stay within license / product / policy operations, always use a scoped key. Operators can revoke a compromised scoped key without rotating the master credential.

diff --git a/install.html b/install.html index eb69ab4..37d04f8 100644 --- a/install.html +++ b/install.html @@ -71,7 +71,7 @@

Option B: sideload

    -
  1. Download keysat_x86_64.s9pk from the GitHub releases page.
  2. +
  3. Download keysat.s9pk from the GitHub releases page.
  4. In your StartOS dashboard, go to Sideload and drag the file in.
  5. Click Install.
@@ -79,13 +79,13 @@

BTCPay Server is declared as a required dependency. If you don’t have it installed yet, StartOS will prompt you to install it as part of the same flow.

Step 2: Set your operator name

-

Open the Keysat service page in StartOS. Go to Actions → Set operator name. Pick a short label that identifies you as the seller, e.g. "aurora-software", "northpath", "my-name". This shows up on the public purchase pages and in the audit log.

+

Open the admin web UI (Step 5) and go to Settings. Set your operator name there: a short label that identifies you as the seller, e.g. "aurora-software", "northpath", "my-name". This shows up on the public purchase pages and in the audit log.

This change is live-reloaded; you don’t need to restart the service.

Step 3: Connect BTCPay

Make sure BTCPay Server is running and has at least one store with a configured payment method (on-chain wallet or Lightning node). Without a payment method, BTCPay will reject Keysat’s invoice creation.

-

In Keysat’s service page, click Actions → Connect BTCPay. You’ll be redirected to BTCPay’s authorize page, where you grant Keysat the permissions it needs:

+

In the admin web UI, go to Settings → Payment providers and click Connect BTCPay (agents can drive the same connect over the API with POST /v1/admin/btcpay/connect). You’ll be redirected to BTCPay’s authorize page, where you grant Keysat the permissions it needs: