Stripe Integration
Aerostack uses Stripe for all payment processing: platform plan subscriptions, wallet deposits, and marketplace creator payouts. This page explains how Stripe integrates with your Aerostack account and how to configure webhooks for self-hosted or custom setups.
How Stripe is Used
| Feature | Stripe Product | Description |
|---|---|---|
| Platform plans | Subscriptions | Monthly/yearly recurring billing for plan tiers |
| Wallet deposits | Checkout Sessions | One-time payments to fund the prepaid wallet |
| Creator payouts | Connect | Transfer marketplace earnings to creator bank accounts |
| Customer portal | Customer Portal | Self-service billing management (invoices, payment methods) |
Platform Plan Checkout
When a user upgrades their plan, Aerostack creates a Stripe Checkout Session and redirects them to complete payment.
Flow
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 Stripe Checkout Session with the correct Price ID
4. API returns { url: "https://checkout.stripe.com/..." }
5. Frontend redirects user to Stripe Checkout
6. User completes payment on Stripe
7. Stripe redirects to success_url with session_id
8. Frontend calls GET /api/billing/verify-session?session_id=...
9. API verifies payment and upgrades the plan immediately
10. Stripe also sends webhook for redundancyBilling Intervals
Each paid plan has two Price IDs in Stripe — one for monthly and one for yearly:
# Monthly checkout
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": "monthly",
"success_url": "https://app.aerostack.dev/settings/billing?success=true",
"cancel_url": "https://app.aerostack.dev/settings/billing"
}'
# Yearly checkout (25% discount)
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 Stripe checkout.
Webhook Configuration
Stripe webhooks keep Aerostack in sync with subscription changes that happen outside the API (e.g. failed payments, subscription renewals, cancellations from the Stripe dashboard).
Endpoint
POST https://api.aerostack.dev/api/billing/webhookThis endpoint:
- Requires no authentication (it is public)
- Validates the
stripe-signatureheader against your webhook signing secret - Processes the event and updates the account plan accordingly
Setting Up Webhooks in Stripe
- Go to Stripe Dashboard > Developers > Webhooks
- Click Add endpoint
- Enter the URL:
https://api.aerostack.dev/api/billing/webhook - Select these events:
checkout.session.completedcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
- Click Add endpoint
- Copy the Signing secret (
whsec_...) and configure it in your Aerostack deployment
Use Snapshot payload, not Thin. When configuring the webhook in Stripe, ensure the payload type is set to “Snapshot” (default). Thin payloads require an additional API call to retrieve the full event, which is not supported.
Customer Portal
The Stripe Customer Portal lets users manage their subscription without leaving the Aerostack app:
- View and download invoices
- Update payment methods
- Switch billing intervals (monthly/yearly)
- Cancel subscription
Get Portal URL
curl "https://api.aerostack.dev/api/billing/portal?return_url=https://app.aerostack.dev/settings/billing" \
-H "Authorization: Bearer YOUR_JWT"Response:
{
"url": "https://billing.stripe.com/p/session/..."
}Redirect the user to this URL. After they finish managing their billing, Stripe redirects them back to the return_url.
The Stripe Customer Portal must be configured in your Stripe Dashboard. Go to Settings > Customer portal and enable the features you want (invoice history, payment method updates, subscription cancellation, etc.).
Wallet Deposits via Stripe
Wallet deposits use Stripe Checkout Sessions in “payment” mode (one-time payment, not subscription).
Flow
1. User clicks "Add Funds" in dashboard
2. Frontend calls POST /api/balance/deposit
Body: { amount_cents: 2500, success_url, cancel_url }
3. API creates Stripe Checkout Session (mode: "payment")
4. API returns { url: "https://checkout.stripe.com/..." }
5. User completes payment
6. Stripe redirects to success_url with session_id
7. Frontend calls GET /api/balance/verify?session_id=...
8. API verifies payment and credits the walletDeposit Limits
| Constraint | Value |
|---|---|
| Minimum deposit | $5.00 (500 cents) |
| Maximum deposit | $500.00 (50,000 cents) |
Stripe Connect for Creators
Marketplace creators earn revenue when consumers use their paid tools, functions, and agents. Payouts are processed via Stripe Connect.
How it Works
- Creator publishes a paid tool to the marketplace
- Consumer calls the tool, and wallet is debited
- Marketplace fee is retained by Aerostack
- Remainder credited to the creator’s developer balance
- Payout transferred to the creator’s bank via Stripe Connect
Onboarding
Before receiving payouts, creators must complete Stripe Connect onboarding:
- Navigate to Settings > Payouts in the Aerostack Dashboard
- Click Connect with Stripe
- Complete Stripe’s identity verification and banking setup
- Once verified, payouts are enabled
Payout Configuration
| Setting | Options |
|---|---|
| Payout frequency | Manual, Weekly, Monthly |
| Minimum payout | $10.00 |
| Currency | USD |
Verify Session After Redirect
After any Stripe checkout redirect (plan upgrade or wallet deposit), verify the session to ensure the payment was processed:
Plan Upgrade Verification
curl "https://api.aerostack.dev/api/billing/verify-session?session_id=cs_live_..." \
-H "Authorization: Bearer YOUR_JWT"Response:
{
"tier": "pro"
}Wallet Deposit Verification
curl "https://api.aerostack.dev/api/balance/verify?session_id=cs_live_..." \
-H "Authorization: Bearer YOUR_JWT"Response:
{
"deposited": true,
"amount_cents": 2500
}Session verification is idempotent. Calling it multiple times with the same session_id will not duplicate the plan upgrade or wallet deposit.
Redirect URL Security
All Stripe redirect URLs (success_url, cancel_url, return_url) are validated against an allowlist:
| Allowed Origin | Purpose |
|---|---|
https://app.aerostack.dev | Production dashboard |
https://aerostack-admin.pages.dev | Cloudflare Pages deploys |
https://*.aerostack-admin.pages.dev | Preview deploys |
http://localhost:5173 | Local development |
Requests with redirect URLs on other origins are rejected with a 400 error. This prevents open redirect attacks.
Testing with Stripe Test Mode
During development, use Stripe test mode keys (sk_test_...) instead of live keys. Test mode:
- Uses test credit card numbers (e.g.
4242 4242 4242 4242) - Does not charge real money
- Sends webhooks to your test endpoint
- Creates test subscriptions that behave like real ones
Never use live Stripe keys (sk_live_...) in development. Always use test keys locally and configure live keys only in production.
Troubleshooting
Webhook Not Receiving Events
- Verify the webhook URL is correct:
https://api.aerostack.dev/api/billing/webhook - Check the webhook signing secret is set:
aerostack secrets list - In Stripe Dashboard > Webhooks, check the event delivery logs for errors
- Ensure payload type is “Snapshot” (not “Thin”)
Plan Not Updating After Checkout
- Call
GET /api/billing/verify-session?session_id=...to force verification - Check Stripe Dashboard for the checkout session status
- If the webhook failed, the verify endpoint handles plan updates as a fallback
Wallet Balance Not Credited
- Call
GET /api/balance/verify?session_id=...to force verification - Ensure the checkout session completed successfully in Stripe
- Check for duplicate verification (the endpoint is idempotent)