Stripe Connect & Sanctum

Enable monetization for realm owners through Stripe Connect and subscription-based access control.

What is Sanctum?

Sanctum is Autonomy's subscription and access control system. It allows realm owners to:

  • Monetize their realms — Create subscription tiers with custom pricing
  • Control access — Gate signals by visibility level (PUBLIC, PRIVATE, SANCTUM)
  • Own their revenue — Payments go directly to realm owners via Stripe Connect
  • Customize branding — Name their subscription area whatever they want

Unlike traditional platforms where you're a user on someone else's system, Sanctum gives each realm owner their own Stripe account and complete control over pricing and access.

How Stripe Connect Works

Stripe Connect allows platforms to facilitate payments between users. Each realm owner connects their own Stripe account, and payments go directly to them—not through the platform.

1

Platform Setup

The platform owner (you, if self-hosting) enables Stripe Connect on their Stripe account. This is a one-time setup that authorizes your platform to create connected accounts.

2

Realm Owner Onboarding

Realm owners click "Connect Stripe" in their Sanctum settings. They're redirected to Stripe's onboarding flow where they create/connect their Stripe account and verify their identity.

3

Account Connection Stored

After onboarding, Stripe returns the connected account ID. This is stored in the realm's settings at realm_settings.sanctum.stripe.account_id

4

Subscription Creation

When users subscribe to a realm, payments are processed on the realm owner's connected Stripe account. The platform can optionally take an application fee (e.g., 5%) for providing infrastructure.

Platform Setup (One-Time)

Step 1: Enable Stripe Connect

  1. Go to Stripe Dashboard → Connect Settings
  2. Click "Get started" or "Enable Connect"
  3. Select industry (e.g., "Website building or hosting")
  4. Complete platform application form
  5. Verify your identity with government ID
  6. Wait for approval (usually instant)

Step 2: Configure Environment Variables

Add your Stripe keys to .env:

# Stripe API Keys
STRIPE_SECRET="sk_live_..."  # Your secret key
STRIPE_KEY="pk_live_..."     # Your publishable key (for client-side)
STRIPE_WEBHOOK_SECRET="whsec_..."  # For webhook signature verification

# Public URL (required for redirects)
NEXT_PUBLIC_APP_URL="https://yourdomain.com"

Important: Use live keys (sk_live_) for production. Use test keys (sk_test_) for development.

Step 3: Configure Branding

Customize what realm owners see during onboarding:

  1. Go to Connect Settings → Branding
  2. Set platform name (e.g., "Autonomy Realms")
  3. Upload platform logo/icon
  4. Set brand colors

Realm Owner Setup

Step 1: Navigate to Sanctum Settings

  1. Go to Admin → Realms
  2. Click "Sanctum" button on your realm
  3. Or navigate to Settings tab → Sanctum tab

Step 2: Connect Stripe Account

  1. Click "Connect Stripe" button
  2. You'll be redirected to Stripe's onboarding
  3. Create new account or sign in to existing
  4. Complete identity verification (government ID required)
  5. Add bank account for payouts
  6. Review and accept Stripe's terms
  7. You'll be redirected back to Sanctum settings

Note: If using live Stripe keys, this creates a real Stripe account. Test keys create test-mode accounts for development.

Step 3: Enable Sanctum

After Stripe is connected, configure your Sanctum:

  1. Toggle "Enable Sanctum" on
  2. Set display name (default: "Sanctum", can be "Supporters", "Members", etc.)
  3. Click "Add Tier" to create subscription tiers

Step 4: Create Subscription Tiers

Define how users can subscribe to your realm:

Fixed Price Tier

Set a specific monthly or yearly price

  • Name: "Supporter", "Patron", "Inner Circle"
  • Price: $5.00, $10.00, $25.00, etc.
  • Interval: Monthly or Yearly
  • Description: What subscribers get

Custom Amount Tier

"Pay what you want" with optional minimum

  • Pricing Type: Select "Custom Amount"
  • Minimum: $1.00 (or 0 for truly optional)
  • Suggested: $10.00 (pre-filled for user)
  • Interval: Monthly or Yearly

Free Tier

Access control without payment

  • Price: $0.00
  • Use case: Invite-only access, beta testers, manual approvals
  • Note: Users still need to "subscribe" (no charge), giving you control

Access Control with Signal Visibility

Sanctum uses signal visibility levels to control who can see what:

PUBLIC

Anyone can see these signals, even without an account. Perfect for marketing content, blog posts, public transmissions.

PRIVATE

Only authenticated users with any Sanctum tier can see these. Good for member-only content that doesn't need highest tier.

SANCTUM

Only users with specific Sanctum tier(s) can see these. This is your premium content, gated by subscription.

Flexible Control

You can set visibility on a per-signal basis. Mix PUBLIC transmissions (to attract subscribers) with SANCTUM transmissions (to reward them). Or keep everything PRIVATE for a community-only realm.

Technical: How It's Stored

Realm Settings

Sanctum configuration is stored in realm_settings.sanctum:

{
  "sanctum": {
    "enabled": true,
    "display_name": "Inner Circle",
    "stripe": {
      "account_id": "acct_...",
      "onboarding_complete": true,
      "charges_enabled": true,
      "payouts_enabled": true
    },
    "tiers": [
      {
        "id": "uuid-here",
        "name": "Supporter",
        "price": 1000,  // $10.00 in cents
        "interval": "month",
        "description": "Support my work"
      },
      {
        "id": "uuid-here",
        "name": "Custom",
        "price": "custom",
        "price_minimum": 100,  // $1.00 minimum
        "price_suggested": 1000,  // $10.00 suggested
        "interval": "month",
        "description": "Pay what you want"
      }
    ]
  }
}

User Subscriptions

When a user subscribes, they're added to realm_users with Sanctum data:

{
  "realm_id": "01ABC...",
  "user_id": "01XYZ...",
  "user_role": "SANCTUM",
  "sanctum_tier": "uuid-of-tier",
  "stripe_subscription_id": "sub_...",
  "stripe_subscription_status": "active",
  "stamp_joined": "2026-01-06T..."
}

Webhook Configuration

Stripe sends webhooks when subscription events occur (created, canceled, payment failed). Configure these to keep subscriptions in sync:

Step 1: Add Webhook Endpoint

  1. Go to Stripe Dashboard → Webhooks
  2. Click "Add endpoint"
  3. Enter URL: https://yourdomain.com/api/stripe/webhooks
  4. Select events:
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.payment_failed
  5. Click "Add endpoint"
  6. Copy the webhook signing secret

Step 2: Add Signing Secret to Environment

STRIPE_WEBHOOK_SECRET="whsec_..."

Note: Webhook handlers will be implemented in future updates to automatically update stripe_subscription_status when subscriptions change.

Platform Revenue (Optional)

As the platform operator, you can optionally take an application fee from each transaction:

Application Fees

When creating a subscription, you can specify an application fee percentage or fixed amount:

Example:

  • • User subscribes for $10/month
  • • Stripe takes 2.9% + $0.30 = $0.59
  • • Platform takes 5% = $0.50
  • • Realm owner receives $8.91

This is configured when creating the subscription in Stripe. Set to 0% if you want realm owners to receive full amount (minus Stripe fees).

Security Considerations

Never expose secret keys

STRIPE_SECRET must only exist server-side in .env file. Never commit to git, never send to client.

Verify webhook signatures

Always verify webhook signatures using STRIPE_WEBHOOK_SECRET to ensure requests are from Stripe.

HTTPS required for live mode

Stripe requires HTTPS for all live-mode redirect URLs and webhooks. Use test mode for local development.

Troubleshooting

"You can only create new accounts if you've signed up for Connect"

Enable Stripe Connect in your dashboard first (Step 1 of Platform Setup above)

"Livemode requests must always be redirected via HTTPS"

Check that NEXT_PUBLIC_APP_URL uses https:// not http://. Or use test keys for development.

Redirects to localhost instead of production domain

Update callback route to use NEXT_PUBLIC_APP_URL instead of req.url for redirect construction

Subscription status not updating

Verify webhook endpoint is configured and receiving events. Check webhook logs in Stripe dashboard.

Next Steps