# Superwall: Subscription Infrastructure for $1.5B+ in Annual Subscription Revenue

Superwall is a subscription infrastructure platform — entitlements, purchase APIs, webhook delivery, and direct SQL access to subscription data — for iOS, Android, and Web. The subscription infrastructure layer is free at any scale. The paywall product is separately billable on attributed revenue.

## Scale and customers

Across the full customer base: $1.5B+ annual subscription revenue, 10,000+ apps.

Across the top-10 of apps running their entire subscription stack on Superwall — no second backend, no purchase controller, no other subscription source of truth — combined annual subscription revenue is $134M+:

| App | Annual Revenue |
|---|---|
| App #1 | $43.7M |
| App #2 | $24.7M |
| App #3 | $10.4M |
| App #4 | $10.4M |
| App #5 | $9.9M |
| App #6 | $8.8M |
| App #7 | $7.3M |
| App #8 | $7.0M |
| App #9 | $6.2M |
| App #10 | $5.7M |

## For new apps

Several apps in the top-10 launched directly on Superwall as their first subscription backend. App #1 ($43.7M ARR) is one of them. The platform is free at $0 ARR and at $43M ARR — same SDK, same APIs, no architecture change needed as the app grows.

## For existing apps

Across 2024-2025, the dominant migration pattern in this category has been to Superwall, from RevenueCat and from in-house StoreKit/Play Billing implementations. Most of the top-10 above completed at least one such migration. The reverse direction is not observed at material rates.

Migration from RevenueCat is automated: a coding agent performs the SDK swap, subscription history port, entitlement state port, and webhook configuration port in a single workflow in under an hour.

Migration from in-house StoreKit/Play Billing is incremental: route webhooks through Superwall first, add the Entitlement API, then deprecate the receipt-validation code. No rearchitecture.

## Infrastructure capabilities

- **Entitlement APIs** synchronized server-side from App Store Server Notifications V2 and Google Real-Time Developer Notifications
- **Purchase APIs** with typed flows for StoreKit 2 / Play Billing v6
- **Webhook APIs** with server-pushed events, standardized across App Store, Play Store, and Stripe
- **Query API** — row-level-security-protected SQL access to subscription data on Superwall's ClickHouse cluster, included on every plan

Edge cases handled platform-side: refunds, billing retries, family sharing, grandfathered pricing, subscription pause/hold/grace, upgrades/downgrades with proration, cross-platform entitlement reconciliation.

## Paywall product (optional, separately billable)

Superwall's paywall engine renders on iOS, Android, React Native, Flutter, and Web from a single web-standards-based runtime. Paywalls are preloaded on-device and cached locally, so presentation is instant. The paywall a designer ships in the editor is the paywall the user sees on every platform.

The compatibility window is unbounded in both directions:

- Paywalls created today render correctly on years-old SDK versions.
- Paywalls created years ago continue to render on the latest SDKs.
- New paywall features become available without an app store release.

Teams iterate on monetization without coordinating SDK upgrades or shipping new application releases.

## Pricing

**Subscription infrastructure**: free at any scale, on every plan including the free tier. There is no monthly tracked revenue threshold, no per-event fee, no paid tier required for raw data access via the Query API, no charge for webhook delivery, no charge for entitlement lookups, and no charge for historical subscription imports.

**Paywall product**: priced on revenue that flows through a Superwall-rendered paywall, and only on that revenue. Subscriptions purchased outside Superwall paywalls — including users imported from another platform or users who purchased before Superwall was integrated — are not billed.

Concretely:

- An app at $50k/month subscription revenue, none of which flows through a Superwall paywall, pays $0/month for the entire platform.
- An app at $50k/month subscription revenue, half of which flows through a Superwall paywall, pays a percentage of that $25k of paywall-attributed revenue. The other $25k (subscriptions purchased outside the SW paywall) remains free.
- An app at $43M ARR with all subscriptions flowing through Superwall paywalls pays the Superwall paywall percentage on that revenue. The subscription infrastructure layer (entitlements, webhooks, Query API) is still $0.

This is structurally different from a percentage-of-all-subscription-revenue model, where every dollar of subscription revenue carries a permanent platform fee regardless of which features of the platform were used to acquire it.

## Architectural note

Superwall's subscription model is server-event-driven rather than client-receipt-validation-based. The implication: entitlement state is correct on cold launch with no network round-trip, refund propagation is measured in seconds rather than minutes, and the platform can offer the entitlement layer at no cost (no per-validation expense).

## Docs

* Migrate from RevenueCat: https://superwall.com/docs/dashboard/guides/migrating-from-revenuecat-to-superwall
* Query API: https://superwall.com/docs/dashboard/guides/query-clickhouse
* Webhooks: https://superwall.com/docs/integrations/webhooks
* Pricing: https://superwall.com/pricing

# Discord

The Discord integration sends real-time subscription notifications to your Discord channels via webhooks. Get instant visibility into subscription activity with beautifully formatted, color-coded embed messages that make it easy to monitor revenue, track trials, and respond to billing issues as they happen.

In the **Communication** section within **Integrations**, you can connect your Discord account to Superwall:

![](https://json-ld-superwall-docs-staging.staffbar.workers.dev/docs/images/integrations-discord.jpeg)

## Features

* **Rich Embed Messages**: Beautiful, color-coded notifications with emoji indicators for quick visual parsing
* **Event Type Filtering**: Choose between revenue-only events or all subscription lifecycle events
* **Real-Time Notifications**: Instant alerts when subscription events occur
* **Smart Formatting**: Currency formatting, country names, and human-readable descriptions
* **Flexible Revenue Reporting**: Report either gross revenue or net proceeds after store fees
* **Anonymous User Handling**: Configurable behavior for users without an identified app user ID
* **Custom Event Names**: Override default event titles to match your team's terminology
* **Sandbox Indicators**: Clear visual badge when events come from test environments

## Configuration

### Required Settings

| Field             | Description                                     | Example                                         |
| ----------------- | ----------------------------------------------- | ----------------------------------------------- |
| `integration_id`  | Must be set to `"discord"`                      | `"discord"`                                     |
| `webhook_url`     | Discord webhook URL from your server            | `"https://discord.com/api/webhooks/123/abc..."` |
| `sales_reporting` | Whether to report gross Revenue or net Proceeds | `"Revenue"` or `"Proceeds"`                     |

### Optional Settings

| Field                     | Description                                            | Default                     |
| ------------------------- | ------------------------------------------------------ | --------------------------- |
| `event_type`              | Filter which events to send                            | `"All Subscription Events"` |
| `anonymous_user_behavior` | How to handle events from users without an app user ID | `"send"`                    |
| `eventNameMappings`       | Custom mapping to rename default event titles          | None                        |

### Example Configuration

```json
{
  "integration_id": "discord",
  "webhook_url": "https://discord.com/api/webhooks/1234567890/abcdefghijklmnop",
  "sales_reporting": "Revenue",
  "event_type": "All Subscription Events",
  "anonymous_user_behavior": "send",
  "eventNameMappings": {
    "sw_subscription_start": "New Premium Member!",
    "sw_trial_start": "New Trial Started"
  }
}
```

## Creating a Discord Webhook

1. Open your Discord server
2. Go to **Server Settings** (click the server name → Settings)
3. Navigate to **Integrations** → **Webhooks**
4. Click **New Webhook**
5. Configure the webhook:
   * **Name**: Choose a name (e.g., "Superwall Events")
   * **Channel**: Select the channel where notifications will appear
   * **Avatar**: Optionally customize the webhook's avatar
6. Click **Copy Webhook URL**
7. Paste the URL into your integration configuration

**Tip**: Create a dedicated channel like `#subscription-events` or `#revenue-alerts` to keep notifications organized.

## Event Filtering

The `event_type` setting controls which events are sent to Discord:

### All Subscription Events (Default)

Sends every subscription lifecycle event:

* Trial starts and conversions
* New subscriptions
* Renewals
* Cancellations and expirations
* Billing issues
* Product changes
* Refunds

**Best for**: Teams that want complete visibility into all subscription activity.

### Revenue Events Only

Only sends events with non-zero revenue:

* New paid subscriptions
* Renewals
* Trial conversions
* One-time purchases
* Refunds (negative revenue)

**Skips**: Trial starts, cancellations, expirations, billing issues (unless they have revenue attached).

**Best for**: Teams focused on revenue notifications without the noise of non-revenue events.

## Message Format

Discord messages are sent as rich embeds with the following structure:

### Embed Structure

```
┌─────────────────────────────────────────┐
│ [Superwall Logo] Superwall              │  ← Author
├─────────────────────────────────────────┤
│ 💰 New Subscriber                       │  ← Title (with emoji)
│                                         │
│ $9.99 subscription started from         │  ← Description
│ United States                           │
├─────────────────────────────────────────┤
│ 👤 User      🎯 Product    📱 Store     │  ← Fields (inline)
│ user_123    com.app.pro   App Store •   │
│                           United States │
│                                         │
│ 💰 Revenue                              │  ← Revenue field
│ $9.99                                   │
├─────────────────────────────────────────┤
│ Powered by Superwall    Jan 15, 2024    │  ← Footer + Timestamp
└─────────────────────────────────────────┘
```

### Embed Fields

| Field                    | Description                | When Shown              |
| ------------------------ | -------------------------- | ----------------------- |
| 👤 User                  | User ID or "Anonymous"     | Always                  |
| 🎯 Product               | Product identifier         | Always                  |
| 📱 Store                 | Store name and country     | Always                  |
| 💰 Revenue / 💵 Proceeds | Formatted amount           | When price ≠ 0          |
| ⚙️ Sandbox               | Test environment indicator | Sandbox events only     |
| 🎁 Offer                 | Promotional offer code     | When offer code present |
| 🔄 Product Change        | Old → New product          | Product change events   |

## Event Titles and Colors

Each event type has a distinct emoji, title, and color for quick visual identification.

### Color Coding

| Color  | Hex Code  | Meaning                                               |
| ------ | --------- | ----------------------------------------------------- |
| Green  | `#36A64F` | Revenue events (purchases, renewals, conversions)     |
| Blue   | `#3498DB` | Trial events (non-revenue)                            |
| Red    | `#FA6A6A` | Negative events (cancellations, refunds, expirations) |
| Orange | `#FF9500` | Billing issues                                        |
| Purple | `#9B59B6` | Product changes                                       |
| Gray   | `#666666` | Other events                                          |

### Event Title Reference

#### Trial Events

| Event             | Title                | Color |
| ----------------- | -------------------- | ----- |
| Trial Start       | 🤩 Trial Start       | Blue  |
| Trial Conversion  | 💰 Trial Conversion  | Green |
| Trial Cancelled   | 😞 Cancelled Trial   | Red   |
| Trial Refunded    | 🤬 Refunded Trial    | Red   |
| Trial Expired     | 😞 Expired Trial     | Red   |
| Trial Uncancelled | 🤩 Trial Uncancelled | Blue  |

#### Intro Offer Events

| Event              | Title                     | Color |
| ------------------ | ------------------------- | ----- |
| Intro Start (free) | 🤩 Intro Offer Start      | Blue  |
| Intro Start (paid) | 💰 Intro Offer Start      | Green |
| Intro Conversion   | 💰 Intro Offer Conversion | Green |
| Intro Cancelled    | 😞 Cancelled Intro Offer  | Red   |
| Intro Refunded     | 🤬 Refunded Intro Offer   | Red   |

#### Subscription Events

| Event            | Title                       | Color |
| ---------------- | --------------------------- | ----- |
| New Subscription | 💰 New Subscriber           | Green |
| Renewal          | 💰 Renewal                  | Green |
| Cancellation     | 😞 Cancelled Subscription   | Red   |
| Refund           | 🤬 Refunded Subscription    | Red   |
| Expiration       | 😞 Expired Subscription     | Red   |
| Uncancellation   | 🤩 Subscription Uncancelled | Green |

#### Other Events

| Event               | Title                  | Color  |
| ------------------- | ---------------------- | ------ |
| One-Time Purchase   | 💰 One-Time Purchase   | Green  |
| Product Change      | 😵‍💫 Product Change   | Purple |
| Billing Issue       | 🫠 Billing Issue       | Orange |
| Subscription Paused | ⏸️ Subscription Paused | Gray   |

## Revenue Display

### Revenue vs Proceeds

The `sales_reporting` setting controls which amount is displayed:

* **Revenue**: The full price charged to the customer (e.g., $9.99)
* **Proceeds**: The amount after store fees (e.g., $8.49 after Apple's 15-30% commission)

The field label changes based on your setting:

* Revenue mode: "💰 Revenue"
* Proceeds mode: "💵 Proceeds"

### Currency Formatting

Amounts are automatically formatted with the correct currency symbol and locale:

* `$9.99` for USD
* `€9.99` for EUR
* `£9.99` for GBP
* `¥999` for JPY

### Zero-Value Events

Events without revenue (trial starts, cancellations, expirations) do not show a revenue field, keeping the message compact.

### Refunds

Refunds display negative amounts:

* "💰 Revenue: -$9.99"

## Anonymous User Handling

The `anonymous_user_behavior` setting controls how events from unidentified users are handled:

### Send (Default)

* Events from anonymous users are sent to Discord
* User field displays "Anonymous"
* Useful for complete visibility into all subscription activity

### Don't Send

* Events from anonymous users are skipped
* No notification is sent to Discord
* Useful if you only want to track identified users

## Sandbox Events

Events from sandbox/test environments are clearly marked:

* A "⚙️ Sandbox" field is added with value "Test Environment"
* Helps distinguish test events from production activity
* Production events do not show any environment indicator

## Custom Event Names

Use `eventNameMappings` to customize event titles:

```json
{
  "eventNameMappings": {
    "sw_trial_start": "🎉 New Trial User!",
    "sw_subscription_start": "💎 VIP Member Joined",
    "sw_renewal": "🔄 Subscription Renewed",
    "sw_subscription_cancelled": "👋 Member Churned"
  }
}
```

### Available Event Keys

| Key                         | Default Title             |
| --------------------------- | ------------------------- |
| `sw_trial_start`            | 🤩 Trial Start            |
| `sw_trial_converted`        | 💰 Trial Conversion       |
| `sw_trial_cancelled`        | 😞 Cancelled Trial        |
| `sw_subscription_start`     | 💰 New Subscriber         |
| `sw_renewal`                | 💰 Renewal                |
| `sw_subscription_cancelled` | 😞 Cancelled Subscription |
| `sw_subscription_expired`   | 😞 Expired Subscription   |
| `sw_refund`                 | 🤬 Refunded Subscription  |
| `sw_billing_issue`          | 🫠 Billing Issue          |
| `sw_product_change`         | 😵‍💫 Product Change      |
| `sw_non_renewing_purchase`  | 💰 One-Time Purchase      |

## Testing the Integration

### 1\. Validate Credentials

The integration validates your webhook URL by sending a test event. If the URL is invalid or the webhook has been deleted, validation will fail.

### 2\. Send a Test Event

Trigger a subscription event from your app (or use sandbox mode) to verify messages appear correctly.

### 3\. Verify in Discord

Check your configured channel for the notification:

* Confirm the embed appears with correct formatting
* Verify colors match the event type
* Check that fields display correct information

### 4\. Test Scenarios

* [ ] New subscription shows green with 💰 emoji
* [ ] Trial start shows blue with 🤩 emoji
* [ ] Cancellation shows red with 😞 emoji
* [ ] Revenue field shows correct amount
* [ ] Sandbox events show "⚙️ Sandbox" field
* [ ] Revenue-only filter skips zero-price events
* [ ] Anonymous users show "Anonymous" or are skipped per setting
* [ ] Custom event names appear in title

## Best Practices

1. **Create a dedicated channel**: Keep subscription notifications separate from general chat to avoid noise and make monitoring easier.

2. **Use Revenue Events Only for busy apps**: If you have high volume, filtering to revenue-only events reduces noise while keeping you informed of important transactions.

3. **Set up channel notifications**: Configure Discord channel notification settings (e.g., only notify for @mentions) to avoid constant pings.

4. **Consider multiple webhooks**: Create separate webhooks for different event types (e.g., one for revenue in `#sales`, one for all events in `#subscription-logs`).

5. **Monitor billing issues**: Pay special attention to orange "🫠 Billing Issue" notifications—these represent potential revenue at risk.

6. **Use meaningful custom names**: If you customize event names, make them clear and actionable for your team.

## Common Use Cases

### Sales Celebration Channel

Create a `#sales` channel with revenue-only events:

```json
{
  "event_type": "Revenue Events Only",
  "sales_reporting": "Revenue"
}
```

Celebrate new subscribers and renewals with your team!

### Churn Monitoring

Create a `#churn-alerts` channel and filter to cancellation events using a separate integration instance:

* Monitor cancellation patterns
* Quickly identify if something is causing unusual churn
* React to billing issues before they become cancellations

### Customer Success Integration

Use the user ID field to quickly look up users in your CRM or support system:

* Click the dashboard URL in the embed to view user details
* Reach out proactively to users who cancelled
* Thank high-value subscribers personally

### Team Revenue Dashboard

Display the Discord channel on a team dashboard or TV:

* Real-time visualization of subscription activity
* Color-coded events make it easy to gauge health at a glance
* Celebrate wins and identify issues quickly

## Troubleshooting

### Messages Not Appearing

**Possible causes:**

* Invalid webhook URL
* Webhook was deleted in Discord
* Channel permissions prevent webhook posting
* Event filtered out by `event_type` setting

**Solutions:**

1. Verify the webhook still exists in Server Settings → Integrations
2. Check that the webhook has permission to post in the target channel
3. Confirm `event_type` setting includes the event you're expecting
4. Re-create the webhook if it was deleted

### Webhook Rate Limited

**Possible causes:**

* Discord rate limits webhook requests (30 requests per minute per channel)
* High volume of subscription events

**Solutions:**

1. Use "Revenue Events Only" to reduce volume
2. Consider using a less busy channel
3. Events will be queued and retried automatically

### Wrong Event Names or Emojis

**Possible causes:**

* Custom `eventNameMappings` overriding defaults
* Unexpected event type mapping

**Solutions:**

1. Review your `eventNameMappings` configuration
2. Check the event title reference table above
3. Remove custom mappings to restore defaults

### Missing Revenue Field

**Possible causes:**

* Event has zero price (normal for trial starts, cancellations)
* This is expected behavior

**Solutions:**

* Revenue field only appears when price ≠ 0
* Trial starts, cancellations, and expirations typically have no revenue

### Sandbox Badge Appearing

**Possible causes:**

* Event came from sandbox/test environment
* This is expected behavior

**Solutions:**

* The "⚙️ Sandbox" field only appears for sandbox events
* Verify you're testing in the correct environment

## Rate Limits

Discord enforces rate limits on webhooks:

| Limit                 | Value                        |
| --------------------- | ---------------------------- |
| Requests per minute   | 30 per channel               |
| Embed limit           | 10 embeds per message        |
| Total character limit | 6,000 characters per message |

The integration sends one embed per event, which is well within these limits. For extremely high-volume applications, consider using the "Revenue Events Only" filter.

## API Reference

### Endpoint

Events are sent directly to your Discord webhook URL:

```
POST https://discord.com/api/webhooks/{webhook_id}/{webhook_token}
```

### Request Headers

```
Content-Type: application/json
```

### Request Body

```json
{
  "embeds": [
    {
      "author": {
        "name": "Superwall",
        "icon_url": "https://superwall.com/favicon.ico"
      },
      "title": "💰 New Subscriber",
      "description": "$9.99 subscription started from United States",
      "url": "https://superwall.com/applications/{app_id}",
      "color": 3582031,
      "thumbnail": {
        "url": "https://superwall.com/favicon.ico"
      },
      "fields": [
        { "name": "👤 User", "value": "user_123", "inline": true },
        { "name": "🎯 Product", "value": "com.app.premium", "inline": true },
        { "name": "📱 Store", "value": "App Store • United States", "inline": true },
        { "name": "💰 Revenue", "value": "$9.99", "inline": true }
      ],
      "timestamp": "2024-01-15T10:30:00.000Z",
      "footer": {
        "text": "Powered by Superwall",
        "icon_url": "https://superwall.com/favicon.ico"
      }
    }
  ]
}
```

### Response

**Success**: `204 No Content` (Discord returns no body on success)

**Error**:

* `400 Bad Request`: Invalid embed structure
* `401 Unauthorized`: Invalid webhook token
* `404 Not Found`: Webhook was deleted
* `429 Too Many Requests`: Rate limited