Billing and limits

Plans, monthly API requests, retention, what happens without an active subscription, and every API limit.

Plans

You pay for API requests from the SDKs, not for notifications sent. Every plan starts with a 3-day free trial: you add a payment method at checkout and nothing is charged during the trial. Each organization gets one trial; an organization that already had a subscription checks out without one.

StarterGrowthScale
Monthly price$12$29$99
Yearly price$120 ($10/mo)$288 ($24/mo)$984 ($82/mo)
API requests per month500,0005,000,00030,000,000
Typical users≈ 1,250≈ 12,500≈ 75,000
Projects15Unlimited
Retention30 days90 days365 days
HighlightsWeb and mobile SDKs; broadcasts and user targetingRealtime updates; tags and segments; localization and templates; scheduled notificationsEverything in Growth; priority support

Yearly billing saves about two months per year.

Plan features

Starter sends to everyone and to specific users, in one language and right away. The rest needs the Growth plan and up (custom plans include everything):

FeatureWhat Starter can't send
Tags and segmentsa tags or segment audience; creating or updating a segment
Localizationcontents in more than one locale
Templates{{ … }} in a title, body or action label
Schedulinga publishAt more than a minute ahead
Realtimea connection to GET /v1/client/realtime

The API answers these with 403 forbidden, and the dashboard shows them locked. Drafts, expiry and segment previews work on every plan. After a downgrade, notifications you already saved keep their audience, languages and schedule: only the fields you change are checked, so you can still edit the rest or cancel them.

API requests

Plans limit the client API requests the SDKs make per calendar month (UTC), counted across all projects of your organization:

  • feed polls (GET /v1/client/feed), including 304 Not Modified replies;
  • realtime connections (GET /v1/client/realtime), one per connection; their messages don't count, the feed requests they trigger do;
  • actions (POST /v1/client/actions): read, unread, archive, unarchive, click, read all, seen all;
  • profile syncs (POST /v1/client/profile), sent only when the SDK's user profile changed.

Server API calls with a secret key don't count, and neither do CORS preflights or rejected requests: unknown publishable keys, invalid or expired user tokens, origins the project doesn't allow, 402 without an active subscription, and feed polls answered with 429 over the limit.

A typical user makes about 400 requests a month, which is how the "typical users" row above is estimated. The estimate assumes polling every minute (poll(60_000)), backing off to every 5 minutes while nothing changes; tabs share one poller and hidden apps don't poll. A longer interval lowers usage proportionally, and without polling the SDKs only fetch when users open or return to your app.

Realtime usually costs less than polling: opening the connection counts as one request, its messages and pings don't, and each change it reports costs one feed request. Reconnects count again, and a broadcast makes every connected user refetch, not only its recipients (see Request usage). Realtime is included in the Growth and Scale plans and in custom plans.

The dashboard shows the current month's requests against your plan on the project overview and Billing pages. Every request is counted exactly, and the dashboard shows the count within about 10 seconds.

Over the limit

Nothing breaks. Actions and profile syncs keep working, and each user's feed refreshes every 10 minutes instead of on every poll until the month resets (or within minutes of an upgrade or a request pack purchase). Other feed polls get 429 rate_limited with a Retry-After header, the number of seconds until that user's next refresh (RFC 9110 delay-seconds, exposed to browsers with Access-Control-Expose-Headers). The SDKs keep showing the notifications they have and retry after that delay. New realtime connections are refused meanwhile, and the SDKs try again every 10 minutes.

Request packs

Owners and admins can buy a pack of your plan from the Billing page, through a one-time Stripe checkout: the plan's monthly requests for the plan's monthly price. Custom plans can have their own pack. Packs are never bought automatically.

PlanPack
Starter500,000 requests for $12
Growth5,000,000 requests for $29
Scale30,000,000 requests for $99
  • Availability. You can buy packs while your organization has an active plan, including during the trial.
  • Credit. Requests come out of your plan first, then credit, then this month's packs. Whatever is left of your packs at the end of the month carries over to the next months as credit.
  • Over the limit. When your plan, credit and packs run out, feeds refresh every 10 minutes as above until the month resets, you buy a pack or you upgrade.

Monthly active users

The dashboard also shows monthly active users (project users whose SDK made a request during the calendar month, across all projects) for reference. Plans don't limit them.

Retention

Feeds show notifications published within your plan's retention window: 30, 90 or 365 days, or the window of your custom plan. Older notifications disappear from feeds (and from unread counts) but stay in your history until they are 365 days old, or as old as your custom plan's window if that is longer, when a daily job deletes them. Upgrading extends the window within a few minutes, for notifications that still exist. Without an active, trialing or past-due subscription, feeds use the smallest plan's window (30 days).

Stripe

Billing runs on Stripe Managed Payments. Link, Stripe's checkout and wallet, is the merchant of record: purchases show as "Sold through Link", and Link handles sales tax, VAT and GST, fraud prevention, disputes and support for your transactions. Subscriptions are per organization.

  • Prices. List prices are in USD; checkout shows them in your local currency where available and adds tax. You can pay with cards, Apple Pay, Google Pay, Link and, depending on your country, local payment methods.
  • Managing your subscription. Owners and admins start, switch and cancel plans from the dashboard's Billing page. Payment & invoices opens the Stripe customer portal for payment methods, billing address and invoices. You can also manage all of this on link.com. Custom plans are changed through support.
  • Canceling takes effect at the end of the current billing period (or trial); until then you keep your plan and can resume it.
  • Plan changes apply immediately, and the prorated difference goes on your next invoice. Switching between monthly and annual billing starts a new billing period and is charged right away.
  • Receipts and refunds. Link emails your receipts and invoices (PDFs attached) and refund notices. Charges show on your card statement as LINK.COM* NOTIFICATIONSTREAM. For refunds, contact Link support or us.

Without an active subscription

Access depends on the subscription status: trialing, active and past_due (while a failed payment is being retried) have full access. In any other state (no subscription, canceled, unpaid, paused):

  • Server write endpoints (POST, PUT, PATCH, DELETE with a secret key) return 402 payment_required. Segment previews still work.
  • Server read endpoints (GET) keep working, so you can still export your data.
  • Client endpoints used by the SDKs return 402 payment_required, with no grace period beyond the payment retries. The SDKs show an empty feed and stop polling (and close realtime connections), so your app keeps working but your users see no notifications.
  • Feeds read through the server API fall back to the smallest plan's retention (30 days).

A new or renewed subscription unlocks the API within about 30 seconds of Stripe confirming it.

{
  "error": {
    "code": "payment_required",
    "message": "This organization has no active subscription. Start or renew one at https://notificationstream.com."
  }
}

API limits

Requests

Server endpoints have no request quotas. Client endpoints count towards the monthly API requests of your plan; over the limit, feed polls return 429 rate_limited. Treat 429 like a temporary failure: keep what you have and retry after the Retry-After header (seconds, or an HTTP date). The official SDKs already do.

{
  "error": {
    "code": "rate_limited",
    "message": "This project reached its monthly request limit, so feeds refresh every 10 minutes. Keep showing the feed you have and retry after `Retry-After` seconds."
  }
}

Notifications

FieldLimit
contents1 to 50 locales
title1 to 200 characters
bodyup to 2,000 characters
actionLabelup to 60 characters
Locale keysBCP 47, 2 to 35 characters
audience.userIds1 to 1,000 user ids
audience.tags1 to 20 tags
category1 to 64 characters
actionUrl, imageUrlup to 2,048 characters, http(s) or a path starting with /
dataany JSON object, up to 8 KB serialized
idempotencyKey / Idempotency-Key1 to 255 characters

Project users

FieldLimit
userId1 to 255 characters
emailvalid email, up to 320 characters
nameup to 200 characters
avatarUrllike actionUrl
timezoneup to 64 characters
attributesup to 100 keys; keys 1 to 64 characters
Attribute valuesstring (up to 1,024 characters), number, boolean, null or a list of up to 100 strings (each up to 256)
tagsup to 100 per project user; each 1 to 64 characters of letters, digits, _, -, :, .

Segments

FieldLimit
Conditionsup to 50 in total
Nesting3 levels of groups
name1 to 100 characters
descriptionup to 500 characters

Feeds and lists

Limit
Feed page size (limit)1 to 50, default 20
Notification and project user list page size1 to 100, default 50
Client action idsup to 100 per request
Broadcast candidates per feedthe newest 500 broadcasts of the project
Direct notifications per feedall within the retention window
Feed counts (unreadCount, unseenCount)cover the newest 100 notifications, so at most 100
User token lifetime (exp)at most 7 days ahead
Signing keys per project2

Project settings

SettingLimit
Allowed originsup to 50
Theme colorsup to 64 characters each; radius 0 to 32