Offers

An offer is a way to buy: which plans are for sale, at what price, with which extras and order bumps. You build it in the dashboard, publish it, and share its checkout link.

Offers live under Offers in the app nav (/apps/[appId]/offers). Buyers pay with PayPal through your own PayPal REST app, so the money goes straight to you. Buying sets the account's plan, records the offer on the account and adds the offer's extras. When an intro discount ends, PayPal bills the list price.

Offers need the Offer API. The in-memory mock doesn't sell anything, so the Offers nav item is hidden when the dashboard runs with OFFER_API_URL=mock.

Before you start

  • At least one paid plan (the Free plan switch off). Its pricing card supplies the list prices. A plan without one can still be sold, but you set its price in each offer. See Catalog.
  • PayPal connected for the app. You can build drafts without it, but you can't publish.
  • Optionally, your own checkout page built with the React SDK.

Connect PayPal

PayPal is set per app under App settings → Payments (/apps/[appId]/settings#payments). Until it's connected, the offer pages show Connect PayPal to publish offers and take payments with a link there.

  1. Create a REST app in PayPal

    At developer.paypal.com, open Apps & Credentials and create or open a REST app. Copy its client ID and secret.

  2. Connect it

    Pick Sandbox or Live, paste the Client ID and Secret, and click Connect PayPal. The API checks the credentials with PayPal, then stores the secret encrypted. The dashboard never shows it again.

  3. Check the webhook status

    The connected card shows the environment, the client ID and whether PayPal webhooks were registered. They register when the API is on a public HTTPS address, and then renewals and cancellations update accounts on their own. Without them, a checkout completes when the buyer returns to your page.

Replace swaps in new credentials. Disconnect stops new checkouts. Existing PayPal subscriptions keep billing, but their renewals and cancellations stop reaching the app.

Checkout page

The Checkout page field in the same section is the URL of your page that renders the checkout SDK, such as https://yourapp.com/checkout. Offer links and plan links send buyers there with ?offer=…, and over-limit upgrade links add plan, interval and account. Building that page is covered in Checkout.

Until you set it, offer and plan links open the dashboard's demo checkout at /demo/checkout, a sample storefront with its own branding. Set your own page before you share links with buyers. Over-limit upgrade links don't use the demo checkout: without a checkout page, the API makes a PayPal approval link for the upgrade, and with no PayPal connected there's no link.

The offers list

The list shows each offer's status, plans, deal, sales (with the cap, if any), end date and creation date. Click a row to open the offer. The row menu has Copy checkout link, Duplicate, Copy ID and Delete. The status is what a buyer would see right now:

Draft
Saved but never published.
Live
Published and taking buyers.
Ended
Published, but its end date has passed.
Sold out
Published, but it reached its maximum number of sales.
Archived
Taken down after being published.

Only a live offer sells at its own terms. A link to any other offer still opens the checkout, at your regular prices.

Build an offer

New offer opens a full-page editor at /apps/[appId]/offers/new, with the form on the left and a Checkout preview on the right. Duplicate opens the same editor filled in from an existing offer.

Details
Name and ID (used in ?offer= links and API calls, fixed after creation), plus an optional Headline, Subhead and Bullets (one per line) for the checkout page.
Pricing
One discount for every plan in the offer: Percent off, Amount off or No discount, and For how many payments (empty means it never ends). Billing options picks Monthly, Yearly and Lifetime. Lifetime needs one-time prices.
Plans
Tick each paid plan to include. Preselect one to have it chosen when the checkout opens. Each included plan opens a price row per billing option and an extras list (below).
Order bumps
One-time extras offered at checkout, like a setup call or a credit pack. Add bump, then set a Label, Price, optional Description, what it Gives (An add-on or Credits of a usage entitlement) and which plans it's Shown with (none selected means every plan).
Availability
Ends (a date and time) and Max sales. Both only stop new buyers. Existing buyers keep their price.

Prices per plan

For each billing option, the row shows the plan's list price struck through and an input for the offer price. Leave it empty to use the offer's discount, which the input shows in grey as a placeholder. For monthly and yearly prices you can also set how many payments the price lasts. A billing option the plan has no list price for shows Set a price.

Extra entitlements

Add extra gives buyers of that plan more than the plan does: pick an entitlement and a limit (empty means unlimited). Next to the limit you see the plan's own limit, or “not in plan”. A feature flag has no limit and shows “Included with this offer”. Extras last sets how long they apply:

  • While subscribed
  • During the discount
  • For 3 months, For 6 months or For 1 year

Extras sit between the plan and any incentive when the API resolves access. See How access is resolved.

Live preview

Each time you stop typing, the editor sends the unsaved fields to POST /apps/:appId/offers/draft-preview. The API validates them, prices every plan and billing option, and returns the same public offer the checkout page would receive. Nothing is stored. The preview is rendered with the checkout SDK's components, so it matches what buyers see apart from your styling.

If the API rejects a field, its error shows above the preview, the last valid preview stays visible, and Create draft (or Save offer when editing) is disabled until you fix it.

Publish and archive

Create draft saves the offer and opens its page. From there:

Publish
Re-validates the offer against the current catalog, creates the PayPal billing plan behind every recurring price, and makes the offer live. It fails if PayPal isn't connected.
Edit
Opens the editor at /offers/[offerId]/edit. Edits apply to future purchases. Every checkout keeps the price it was quoted.
Archive
Stops new purchases. The link falls back to your regular prices, and accounts that bought keep their price and extras. Publish again brings it back.
Delete offer
Same fallback for the link. Buyers keep their terms, but the offer's stats are gone. Archive instead if you want to keep them.

The offer page

Each offer has a page at /apps/[appId]/offers/[offerId] with four tabs:

Performance
Views, Checkouts, Sales (with conversion from views) and Revenue (first payments and bumps). Below that, By plan, By source (one row per ?ref= value, plus Direct) and Order bumps with each bump's take rate.
Checkout
The checkout as buyers see it, priced by the API.
Accounts
Accounts that bought through the offer, while their subscription is active.
Checkouts
Every checkout started from the offer, with buyer, plan, source and status: Started, Paid, Expired, Failed or Cancelled.

The side panel shows the offer's details (status, deal, billing options, sales, end date, source and publish date), the Share box, and the plans with their extras and bumps.

The Share box builds the offer's checkout link. Type a ref such as partner_x and the link gets ?ref=partner_x, so you can give each affiliate, campaign or email its own link. Sales then show up per ref under By source.

Link formats
# with a checkout page set in App settings → Payments
https://yourapp.com/checkout?offer=spring_sale&ref=partner_x

# without one: the dashboard's demo checkout
https://dashboard.example.com/demo/checkout?app=<appId>&key=<publicKey>&offer=spring_sale&ref=partner_x

Plans have a link too. A paid plan's page shows a Checkout link that sells it at its list price through the built-in default offer (?offer=default&plan=<planId>). Use an offer when you want a sale price, extras or bumps.

How PayPal subscriptions, plan changes and webhooks work underneath is covered in PayPal.