Skip to main content

List plans

plans() accepts either pk_ or sk_ credentials.
The Plan typed dictionary declares code, name, amount_cents, amount_currency, and interval. At runtime each item is the full plan dictionary from the API, including charges, entitlements, taxes and credit_grant_rules, and the list includes trial, pay-in-arrears and pending-deletion plans. See the public plan catalog. With a pk_ key, all of it is readable by anyone who has the key.

Create checkout

checkout() requires an sk_ key and returns a typed dictionary. Handle each type explicitly: A paid upgrade returns plan_upgrade_intent_id instead of invoice_id on stripe and razorpay results. On scheduled, subscription_id is the pending subscription. pending_subscription_id was removed from the result type in 0.10.0 because the API never returns it; earlier versions declared it. Do not handle all non-Stripe responses as scheduled changes. See the React checkout components for the browser integration. Validate the exact HTTPS return origin before passing a browser-provided URL to this method.

Checkout errors

The SDK raises NozleValidationError before any request when register_mandate is not a bool, or when quote_id is given without subscription_id. See Create checkout for the HTTP contract.

Deprecated success_url

success_url= remains a deprecated alias for return_url=. The SDK emits DeprecationWarning, sends only return_url, and rejects conflicting values with NozleValidationError.
Nozle payment fulfillment is authoritative. Browser callbacks and redirects do not prove activation; Razorpay upgrades require capture and Stripe requires backend settlement.

Manage a payment method

Stripe only. Requires an sk_ key. A pk_ key is refused with 403 (no error code, only a message). Nozle stores no card data: the customer changes their payment method in the Stripe Billing Portal. Razorpay customers pay each invoice through a Razorpay payment link, so for them the call fails with 422 razorpay_pays_by_link. See Manage Payment Method for the HTTP contract and error codes.

Direct subscription

The customer must already exist, so call customers.upsert() first. An unknown customer returns 404 customer_not_found and nothing is created. Calling subscribe() again for the same customer and plan returns the same subscription. subscribe() accepts a paid plan without collecting payment. Use checkout for payment-gated changes. Use direct subscription only when the configured flow does not require interactive payment.
subscribe() to another plan adds a second active subscription. It does not replace the first, and plan credit grants are granted again. To move a customer, call checkout() with subscription_id (needs a transition policy), or cancel and then subscribe. Pass the new subscription ID to track(): cached clients keep the old ID.

Cancellation

The policy defaults to end_of_period and also accepts immediate.

Subscription self-service

The following subscription-management methods are available from nozle-sdk 0.10.0. The matching hosted endpoints are available; see the Python merchant example for a complete integration.
These methods power the React billing portal. Derive customer_id from the authenticated application user and validate the selected external subscription_id. Do not substitute the Core internal UUID for that external identifier.
Changing an existing subscription’s plan needs a transition policy for that source and target plan pair. Without one, preview, checkout, and transitions return 422 plan_transition_policy_required. Exception: from a $0 plan to a paid plan, the organization’s free-to-paid default applies without a pair policy.

Load eligible plans and preview a quote

SubscriptionOptions is a typed dictionary with subscription, pending_change, eligible_plans, and optional checkout. Plans contain code, name, amount_cents, currency, and interval; eligible plans add direction and timing. A pending change has its own internal id and effective_at. SubscriptionChangePreview contains quote_id, transition_direction, timing, currency, credit_amount_cents, debit_amount_cents, net_amount_cents, amount_due_now_cents, amount_due_at_effective_cents, effective_at, and renewal_at. The API also returns transition_policy, billing_anchor, proration_behavior, and credit_action, which the type omits. Show these exact amounts and dates before confirmation. Minor-unit amounts may be integers or strings; preserve their precision. Eligibility comes from configured transition policies, not a client-side price comparison.

Confirm a paid upgrade

After the customer confirms, use the saved quote and a stable action key:
quote_id requires subscription_id. Quotes expire after five minutes or become invalid when their bound state changes. On HTTP 409, request a new preview and confirmation. For an uncertain response, retry the same confirmed request and key; an accepted request can replay after quote expiry. A $0 to $0 immediate upgrade returns completed with payment_source: "credits" and creates a $0 invoice. An upgrade checkout to a pay-in-arrears plan returns 422 plan_upgrade_invoice_missing.

Schedule or withdraw a downgrade

For a confirmed quote with transition_direction == "downgrade":
Reload options to display the pending change separately from the current plan. Retain the exact pending_change["id"] shown in the customer’s withdrawal confirmation:
The result is {"subscription": {"id", "external_id", "plan_code", "status"}, "withdrawn_pending_subscription_id", "replayed"}. The same key returns the same body with replayed: True. Withdrawal preserves the active plan. A new scheduled change while a change is pending replaces it with a new pending ID. A paid upgrade checkout is refused with 409 subscription_change_pending while a downgrade or cancellation is scheduled: withdraw the downgrade, or keep the subscription, first. Scheduling a change or cancelling at period end cancels an open upgrade checkout. Withdrawing the replaced ID returns 409 pending_subscription_changed. An unknown ID returns 404 pending_subscription_not_found.

Cancel at period end and Keep

Preview through the existing transition method:
After displaying and confirming the ending date, forward the exact timestamp:
Keep uses uncancel with a separate confirmed action key and no settlement overrides:
Keep is available only before the ending is due. Cancellation clears a pending downgrade; Keep does not recreate it. Preserve the preview’s full timestamp, including timezone and fractional seconds.

Scope payment recovery and verification

Forward the genuine Razorpay callback’s razorpay_order_id, razorpay_payment_id, and razorpay_signature; a missing field raises before any request. The optional scope fields must be supplied together. Existing calls without them remain compatible; include both for customer-specific recovery. An unknown checkout ID returns 404 checkout_session_not_found. Status distinguishes awaiting_payment, processing, succeeded, failed, expired, and needs_review, with a separate fulfillment_status. Reload the selected subscription before reporting activation. Keep the existing checkout for recoverable retries and use your support route for uncertain payments before another collection. The merchant example maps these dictionaries to React’s camelCase action types and persists retry context. Replace its demo login/file store with your application’s authentication and transactional storage for production workers. See the HTTP contract.

Entity subscriptions

Change or cancel only that Entity:
Every method requires an sk_ key. See Entity Subscriptions for lifecycle and payment behavior.
  • billing_time accepts only calendar or anniversary.
  • Single Entity checkout also accepts free, trial, and pay-in-arrears plans. It returns completed with payment_source: "none".
  • change_plan() needs a transition policy for the plan pair. From 0.13.0 it accepts billing_time; earlier versions take none. It returns scheduled or completed, plus external_entity_id and external_subscription_id.
  • cancel() requires idempotency_key. On a pay-in-arrears plan without credit_action it returns 422 with credit_action: not_supported_for_pay_in_arrears.
  • remove() on an Entity with billing history returns 403 entity_subscription_has_billing_history.

Buy several Entity plans together

checkout_many() buys plans for several Entities with one payment. Do not loop over entity_subscriptions.checkout(): each call creates an independent checkout instead of one combined invoice.
The result contains id, type (stripe, razorpay, processing, or completed), status (pending, open, completed, failed, or expired), client_secret, invoice_id, amount_cents, currency, replayed, expires_at, and items with external_entity_id, external_subscription_id, plan_code, and subscription_status. Razorpay results add the Razorpay fields.
  • Send 1 to 100 unique external_entity_id values. The SDK checks this before any request.
  • idempotency_key is required, up to 255 bytes, and sent as the Idempotency-Key header. The same key and request returns replayed: True and reuses the open session. Replaying a failed or expired batch returns checkout_not_available.
  • The checkout expires after 23 hours.
  • Every plan must require up-front payment: pay in advance with an amount above 0 and no trial, or pay-in-advance fixed charges. Otherwise the whole batch fails with 422 validation_errors and error_details["items"] == ["paid_plan_required"]. Other item errors are mixed_currencies and mixed_intervals.
  • An untrusted return_url returns 422 with return_url: invalid_or_untrusted.
  • With no payment provider connected, the call returns 422 payment_provider_required, as single checkout does.
See bulk Entity checkout.

Settlement transitions

Apply requires an idempotency key up to 255 UTF-8 bytes. These methods use the timing you pass even when the pair’s transition policy says otherwise; checkout always follows the policy. A downgrade on a pair whose policy direction is upgrade returns 422 target_plan_is_not_a_downgrade. See Subscriptions for settlement options and validation rules.

Upsert the customer first

See Customers and Entities for lifecycle details.

Read usage

From 0.13.0.
Each period is a CustomerUsage with from_datetime, to_datetime, currency, amount_cents, total_amount_cents and charges_usage (units and amount per charge and feature). Pass subscription_id to read a specific subscription. Without a subscription ID, the customer’s one active subscription is used, and a customer with none or several gets an error.

Invoices

From 0.13.0.
invoices.list returns the newest invoices first and takes these keyword filters:
Pay an open invoice with checkout_invoice. A PDF is generated the first time it is asked for, so the download call returns no URL until it exists; ask again a few seconds later, or wait for the invoice.generated webhook.

Alerts

From 0.13.0.
Usage alert types are current_usage_amount, feature_current_usage_amount and feature_current_usage_units (the feature_* ones need a feature code). Wallet alert types are wallet_balance_amount, wallet_credits_balance, wallet_ongoing_balance_amount and wallet_credits_ongoing_balance. Threshold values are cents, units or credits by type, and at most one threshold is recurring. Nozle sends the alert.triggered webhook when a threshold is crossed; verify it before acting.