Subscription Payments API#
Merchants can create recurring subscription plans and customers can subscribe using EIP-712 signed spend permissions. Charges are automated via Azure Timer Trigger.
Base URL#
markuphttps://surge.basalthq.com/api/subscriptions
Plans#
List Plans#
markupGET /api/subscriptions/plans?wallet=0x...
Returns all active subscription plans for a merchant.
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
markup | string | Yes | Merchant wallet address |
Response:
json{ "success": true, "plans": [ { "planId": "abc123", "name": "Gold Membership", "description": "Premium access", "priceUsd": 29.99, "period": "MONTHLY", "active": true, "createdAt": 1707696000000 } ] }
Create Plan#
markupPOST /api/subscriptions/plans
Creates a new subscription plan. Requires authenticated merchant wallet.
Body:
json{ "wallet": "0x...", "name": "Gold Membership", "description": "Premium access", "priceUsd": 29.99, "period": "MONTHLY" }
Supported Periods:
markup
, WEEKLYmarkup
, BIWEEKLYmarkup
, MONTHLYmarkup
, QUARTERLYmarkup
YEARLYResponse:
markup
201 Createdjson{ "success": true, "plan": { "planId": "abc123", "..." } }
Update Plan#
markupPUT /api/subscriptions/plans
Updates an existing subscription plan.
Body:
json{ "planId": "abc123", "name": "Gold Membership (Updated)", "description": "New description", "priceUsd": 39.99, "period": "MONTHLY", "active": true }
Response:
markup
200 OKDeactivate Plan#
markupDELETE /api/subscriptions/plans
Deactivates a plan, preventing new subscriptions. Existing subscriptions are unaffected.
Body:
json{ "planId": "abc123", "wallet": "0x..." }
Response:
markup
200 OKSubscriptions#
Create Subscription (Customer)#
markupPOST /api/subscriptions/create
Customer subscribes to a plan. Requires an EIP-712 signed SpendPermission.
Body:
json{ "planId": "abc123", "customerWallet": "0x...", "permissionSignature": "0x...", "permissionData": { "account": "0x...", "spender": "0x...", "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "allowance": "29990000", "period": 2592000, "start": 1707696000, "end": 1739318400, "salt": "1707696000000001", "extraData": "0x" } }
Response:
markup
201 Createdjson{ "success": true, "subscription": { "subscriptionId": "xyz789", "status": "active", "nextChargeAt": 1707696000000 } }
Query Subscriptions#
markupGET /api/subscriptions/status?subscriptionId=xyz789 GET /api/subscriptions/status?customer=0x... GET /api/subscriptions/status?merchant=0x...
Cancel Subscription#
markupPOST /api/subscriptions/cancel
Body:
json{ "subscriptionId": "xyz789", "wallet": "0x..." }
Only the subscribing customer can cancel.
Charging (Internal)#
Charge Single Subscription#
markupPOST /api/subscriptions/charge
Executes a single charge via Thirdweb Engine. Requires
markup
.CRON_SECRETHeaders:
markup
x-cron-secret: <secret>Batch Charge (Cron)#
markupPOST /api/cron/charge-subscriptions
Charges all due subscriptions. Called by Azure Timer Trigger daily.
Headers:
markup
x-cron-secret: <secret>Response:
json{ "success": true, "processed": 5, "succeeded": 4, "failed": 1, "durationMs": 12340, "results": [...] }
Platform Fee#
A 0.5% platform fee is applied to every subscription charge, consistent with one-time payments. Each charge generates a
markup
in Cosmos DB.BillingEventContract#
- SpendPermissionManager: markup(Base mainnet)
0xf85210B21cC50302F477BA56686d2019dC9b67Ad - USDC: markup(Base mainnet, 6 decimals)
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913