Skip to content

Payment Providers

Aerostack uses a dual payment gateway system that automatically selects the right provider for each user based on their country:

RegionProviderWhy
IndiaRazorpayUPI, net banking, INR pricing
All other countriesStripeGlobal card processing, USD pricing

Your payment provider is auto-detected on signup and stored in your account. All billing flows (plan checkout, wallet deposits, creator payouts) route through your assigned provider.


1. User signs up → country detected (from IP or profile)
2. India → Razorpay assigned
3. Other → Stripe assigned
4. Provider stored in account_plans.payment_gateway
5. All future billing uses this provider

You can see your assigned provider in the billing API response:

Terminal window
curl https://api.aerostack.dev/api/billing \
-H "Authorization: Bearer YOUR_JWT"
{
"plan_tier": "starter",
"payment_gateway": "razorpay",
"status": "active"
}

Razorpay handles all payment processing for Indian users: plan subscriptions, wallet deposits, and creator payouts.

  • UPI (Google Pay, PhonePe, Paytm)
  • Net Banking
  • Debit/Credit Cards
  • Wallets

All plans are displayed in INR for Indian users. The conversion rate is applied at billing time.

Razorpay webhooks keep Aerostack in sync with subscription changes:

Endpoint:

POST https://api.aerostack.dev/api/billing/webhook/razorpay

Events handled:

  • payment.captured — payment successful
  • subscription.activated — plan subscription started
  • subscription.charged — recurring payment succeeded
  • subscription.cancelled — subscription cancelled
  • payment.failed — payment failed

Stripe handles payment processing for users outside India: plan subscriptions, wallet deposits, and creator payouts via Stripe Connect.

FeatureStripe ProductDescription
Platform plansSubscriptionsMonthly/yearly recurring billing for plan tiers
Wallet depositsCheckout SessionsOne-time payments to fund the prepaid wallet
Creator payoutsConnectTransfer marketplace earnings to creator bank accounts
Customer portalCustomer PortalSelf-service billing management (invoices, payment methods)

Stripe webhooks keep Aerostack in sync with subscription changes:

Endpoint:

POST https://api.aerostack.dev/api/billing/webhook

This endpoint:

  • Requires no authentication (it is public)
  • Validates the stripe-signature header against your webhook signing secret
  • Processes the event and updates the account plan accordingly

Events to configure:

  • checkout.session.completed
  • customer.subscription.updated
  • customer.subscription.deleted
  • invoice.payment_succeeded
  • invoice.payment_failed

Stripe users can manage their subscription through the Stripe Customer Portal:

  • View and download invoices
  • Update payment methods
  • Switch billing intervals (monthly/yearly)
  • Cancel subscription
Terminal window
curl "https://api.aerostack.dev/api/billing/portal?return_url=https://app.aerostack.dev/settings/billing" \
-H "Authorization: Bearer YOUR_JWT"

The checkout flow is the same regardless of provider — only the redirect URL changes:

1. User clicks "Upgrade to Pro" in dashboard
2. Frontend calls POST /api/billing/checkout
Body: { tier: "pro", billing_interval: "yearly", success_url, cancel_url }
3. API creates checkout session with the user's assigned provider
4. API returns { url: "..." } (Razorpay or Stripe checkout URL)
5. User completes payment on the provider's page
6. Provider redirects to success_url with session_id
7. Frontend calls GET /api/billing/verify-session?session_id=...
8. API verifies payment and upgrades the plan immediately
9. Provider also sends webhook for redundancy

Each paid plan supports monthly and yearly billing:

Terminal window
curl -X POST https://api.aerostack.dev/api/billing/checkout \
-H "Authorization: Bearer YOUR_JWT" \
-H "Content-Type: application/json" \
-d '{
"tier": "pro",
"billing_interval": "yearly",
"success_url": "https://app.aerostack.dev/settings/billing?success=true",
"cancel_url": "https://app.aerostack.dev/settings/billing"
}'

Valid tiers: starter, pro, business. The free tier does not require checkout.


Wallet deposits use one-time payment sessions (not subscriptions).

Terminal window
curl -X POST https://api.aerostack.dev/api/balance/deposit \
-H "Authorization: Bearer YOUR_JWT" \
-H "Content-Type: application/json" \
-d '{
"amount_cents": 2500,
"success_url": "https://app.aerostack.dev/settings/billing?deposit=success",
"cancel_url": "https://app.aerostack.dev/settings/billing"
}'
ConstraintValue
Minimum deposit$5.00 (500 cents)
Maximum deposit$500.00 (50,000 cents)

Marketplace creators earn revenue when consumers use their paid tools, functions, and agents.

  1. Creator publishes a paid tool to the marketplace
  2. Consumer calls the tool, and their wallet is debited
  3. Marketplace fee is retained by Aerostack
  4. Remainder credited to the creator’s developer balance
  5. Payout transferred to the creator’s bank via the provider’s payout system
SettingOptions
Payout frequencyManual, Weekly, Monthly
Minimum payout$10.00
CurrencyUSD (Stripe) / INR (Razorpay)

All redirect URLs (success_url, cancel_url, return_url) are validated against an allowlist:

Allowed OriginPurpose
https://app.aerostack.devProduction dashboard
https://aerostack-admin.pages.devCloudflare Pages deploys
https://*.aerostack-admin.pages.devPreview deploys
http://localhost:5173Local development

Requests with redirect URLs on other origins are rejected with a 400 error.


After any checkout redirect (plan upgrade or wallet deposit), verify the session:

Terminal window
# Plan upgrade
curl "https://api.aerostack.dev/api/billing/verify-session?session_id=..." \
-H "Authorization: Bearer YOUR_JWT"
# Wallet deposit
curl "https://api.aerostack.dev/api/balance/verify?session_id=..." \
-H "Authorization: Bearer YOUR_JWT"

  1. Verify the webhook URL is correct for your provider
  2. Check the webhook signing secret is configured
  3. In your provider’s dashboard, check event delivery logs for errors
  1. Call GET /api/billing/verify-session?session_id=... to force verification
  2. Check your payment provider’s dashboard for the checkout session status
  3. If the webhook failed, the verify endpoint handles plan updates as a fallback
  1. Call GET /api/balance/verify?session_id=... to force verification
  2. Ensure the checkout session completed successfully
  3. Check for duplicate verification (the endpoint is idempotent)