Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Recurring Payments

Subscription-based payments with configurable billing (monthly, weekly, etc.), max payment limits, and user-controlled cancellation.

API

Create subscription: requestRecurringPayment(mainKey, subkeys, paymentRequest) — returns subscription_id, authorized_amount, authorized_recurrence.

paymentRequest: amount, currency (Currency.Millisats), recurrence, expires_at.
recurrence: calendar, first_payment_due (Timestamp), max_payments, until (optional).
calendar: minutely, hourly, daily, weekly, monthly, quarterly, semiannually, yearly.

HTTP
# Request a recurring payment subscription
curl -s -X POST $BASE_URL/payments/recurring \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "main_key": "USER_PUBKEY_HEX",
    "subkeys": [],
    "description": "Monthly subscription",
    "amount": 10000,
    "currency": "millisats",
    "recurrence": {
      "calendar": "monthly",
      "first_payment_due": 1700000000,
      "max_payments": 12
    },
    "expires_at": 1700003600
  }'
# → { "stream_id": "xyz789" }

# Poll for result
curl -s "$BASE_URL/events/xyz789?after=0" \
  -H "Authorization: Bearer $AUTH_TOKEN"
# → { "events": [{ "data": { "subscription_id": "...", "authorized_amount": 10000 } }] }

# Close a subscription
curl -s -X POST $BASE_URL/payments/recurring/close \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"main_key": "USER_PUBKEY_HEX", "subkeys": [], "subscription_id": "SUB_ID"}'
JavaScript
const subscription = await client.requestRecurringPayment(userPubkey, [], {
  amount: 10000,
  currency: Currency.Millisats,
  recurrence: {
    calendar: 'monthly',
    first_payment_due: Timestamp.fromNow(86400),
    max_payments: 12
  },
  expires_at: Timestamp.fromNow(3600)
});
// subscription.subscription_id, subscription.authorized_amount, etc.
Java
import cc.getportal.command.request.RequestRecurringPaymentRequest;
import cc.getportal.command.response.RequestRecurringPaymentResponse;
import cc.getportal.model.RecurringPaymentRequestContent;
import cc.getportal.model.RecurrenceInfo;
import cc.getportal.model.Currency;
import java.util.List;

RecurrenceInfo recurrence = new RecurrenceInfo(
    null, "monthly", null, System.currentTimeMillis() / 1000
);
RecurringPaymentRequestContent payment = new RecurringPaymentRequestContent(
    "Monthly sub", 10_000L, Currency.MILLISATS, null, recurrence,
    System.currentTimeMillis() / 1000 + 3600
);
sdk.sendCommand(
    new RequestRecurringPaymentRequest("user-pubkey-hex", List.of(), payment),
    (res, err) -> {
        if (err != null) { System.err.println(err); return; }
        System.out.println("recurring: " + res);
    }
);

Listen for user cancellations: listenClosedRecurringPayment(onClosed) — callback receives subscription_id, main_key, reason; returns unsubscribe function. Java: ListenClosedRecurringPaymentRequest.

Close from provider: closeRecurringPayment(mainKey, subkeys, subscriptionId). Java: CloseRecurringPaymentRequest. HTTP: POST /payments/recurring/close.


Next: Profiles