Skip to content

Add a yearly plan

Say "add a yearly plan at $290" and get a yearly Offer beside the monthly one, a toggle on the pricing page and revenue recognized month by month.

For developers

A yearly Offer sits beside the monthly one on the same Product. Price it at ten months, so the customer gets two free and you get the cash up front.

For developers

Needs Charge monthly · Open a bank account

What you get

  • 1Offer with a $290 yearly PriceOffer
  • 1yearly price on the same Stripe productPrice
  • 1monthly and yearly toggle on the pricing pageOffer
  • 1renewal notice 30 days before each yearly chargeMessage
  • 12monthly revenue lines per yearly payment, each counted as that month is earnedEntry

Your agent does

Offer.create → Offer.publish
You, to your agent

Add a yearly plan at $290.

Let customers pay once a year.

Offer an annual plan with two months free.

# 1. Offer.create
OFFER=$(curl -X POST https://api.sb/leaseline.app/offers \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"price":{"amount":290,"currency":"USD"},"interval":"year","terms":"Yearly, billed in advance. Cancel any time; access runs to the end of the year paid for."}' | jq -r '.offer["$id"] | split("/") | last')

# 2. Offer.publish
curl -X POST https://api.sb/leaseline.app/offers/$OFFER/publish \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const offer = await $.Offer.create({ price: { amount: 290, currency: 'USD' }, interval: 'year', terms: 'Yearly, billed in advance. Cancel any time; access runs to the end of the year paid for.' })
await $.Offer.publish({ offer: offer.$id })
OFFER=$(npx startup-builder do Offer.create --json '{"price":{"amount":290,"currency":"USD"},"interval":"year","terms":"Yearly, billed in advance. Cancel any time; access runs to the end of the year paid for."}' | jq -r '.offer["$id"] | split("/") | last')
npx startup-builder do Offer.publish --json '{"offer":"'"$OFFER"'"}'
{
  "name": "do",
  "arguments": {
    "code": "const offer = await $.Offer.create({ price: { amount: 290, currency: 'USD' }, interval: 'year', terms: 'Yearly, billed in advance. Cancel any time; access runs to the end of the year paid for.' })\nreturn await $.Offer.publish({ offer: offer.$id })"
  }
}

Change it

  • Show yearly first on the pricing page.
  • Give yearly customers priority support.
  • Move a monthly customer to yearly.

Under the hood

Systems
Billing, Ledger
Nouns
Offer, Price, Subscription
Events
Offer.created, Offer.published
Stripe objects
Product, Price, Pricing Table