List active plans
curl https://api.ai.aikynetix.app/api/plans/import requestsr = requests.get("https://api.ai.aikynetix.app/api/plans/", timeout=30)r.raise_for_status()catalog = r.json()const r = await fetch("https://api.ai.aikynetix.app/api/plans/");if (!r.ok) throw new Error(`HTTP ${r.status}`);const catalog = await r.json();Returns every active plan: name, price in minor units (amount_cents), billing interval (month / year), per-period session_quota, ceilings (max_seats / max_client_profiles), and the FE rendering hint (display_mode). Public endpoint — no auth required so a marketing-page iframe can render the pricing grid before sign-in.
Plan catalog (v1)
role |
name |
Monthly | Sessions/mo | Seats | Clients | display_mode |
|---|---|---|---|---|---|---|
free |
Free | $0 | 3 | 1 | 1 | default |
starter |
Starter | $39 | 20 | 1 | 50 | default |
professional |
Professional | $99 | 75 | 3 | 250 | default |
organization |
Organization | $249 | 250 | 10 | 1000 | default |
strategic |
Strategic | (custom) | (custom) | (custom) | (custom) | custom |
Notes
- Free is the registration default — every new team lands on it automatically without touching Stripe. There is no Stripe SKU for Free; signup creates an
is_managed_externally=TrueSubscription locally and the monthly cron refreshes its 5-session quota. - Strategic ships with
display_mode="custom"and zero price / quota / ceilings. The FE branches on this value and renders a sales-contact CTA in place of price + quota + ceiling rows. - Yearly variants exist for Starter / Pro / Org only (10× monthly = two months free). Free + Strategic are monthly-only.
- Plans live in Postgres and are kept in sync with Stripe by
manage.py sync_plans— never hardcode prices in client code. Passstripe_price_id(from this serializer) toPOST /api/billing/checkout/+GET /api/billing/portal/update-plan/?price=<id>.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Number of results to return per page.
The initial index from which to return the results.
Responses
Section titled “Responses”object
object
Plan UUID. Internal identifier — stable across price + name changes within a tier. For Stripe-touching endpoints (POST /api/billing/checkout/, GET /api/billing/portal/update-plan/), pass stripe_price_id instead.
Stripe price_… id that uniquely identifies this (tier × interval) row in Stripe. This is what POST /api/billing/checkout/ + GET /api/billing/portal/update-plan/?price=<id> consume — pass this value, not the Plan UUID. Free + Strategic carry synthetic non-Stripe ids (bundled_free_month / bundled_strategic_month) because they have no Stripe SKU; the FE should never POST those to the Stripe-touching endpoints (filter on role !== 'free' && role !== 'strategic' client-side, mirroring how the BE views 400 those targets).
Display name shown to the buyer (Free, Starter, Professional, Organization, Strategic).
Billing cadence — month or year. Free + Strategic are monthly-only (Decision H + I); yearly variants exist only for Starter / Pro / Org.
month- Monthlyyear- Yearly
Price in minor units (cents/kopecks). Divide by 100 for the headline price. 0 for Free and Strategic — for Strategic the actual contract is sales-managed off-platform and display_mode=custom tells the FE not to render the price block.
ISO 4217 currency code (lowercase, e.g. usd). v1 ships USD-only; multi-currency is a v1.6 follow-up.
Canonical tier identifier: free / starter / professional / organization / strategic. Use name for display and role for tier-based feature gating server-side. Stable across price + name changes within a tier.
How the FE should render this row. default shows price + quota + ceilings (the four paid tiers + Free). custom skips those fields and shows the sales-contact CTA (Strategic). Branching key for the pricing grid and SubscriptionPanel — see ADR-0019 §2 + §3.
default- Defaultcustom- Custom
Sessions per billing period. Quota refreshes to exactly this number each renewal — leftover does NOT roll over (Decision 6). 0 for Strategic (engagement-specific, off-platform).
Team-membership ceiling. Inviting past this returns 402 with detail="seat_limit_reached". Free=1, Starter=1, Pro=3, Org=10, Strategic=0 (gate skipped for display_mode=custom).
Client-row ceiling. Creating past this returns 402 with detail="client_limit_reached". Free=1, Starter=50, Pro=250, Org=1000, Strategic=0 (gate skipped for display_mode=custom).
Reserved for downstream pricing differentiation (segment-aware plans, ADR-0019 Decision J). Ships inert in v1.5 — PlanListView does NOT filter by team segment, so the field is informational only. Empty list = applies to all segments. v1.6 will activate the filter without an additional migration.
Examples
Catalog (every tier, monthly)
{ "count": 123, "next": "http://api.example.org/accounts/?offset=400&limit=100", "previous": "http://api.example.org/accounts/?offset=200&limit=100", "results": [ [ { "id": "11111111-1111-1111-1111-111111111111", "stripe_price_id": "bundled_free_month", "name": "Free", "interval": "month", "amount_cents": 0, "currency": "usd", "role": "free", "display_mode": "default", "session_quota": 5, "max_seats": 1, "max_client_profiles": 1, "allowed_segments": [] }, { "id": "22222222-2222-2222-2222-222222222222", "stripe_price_id": "price_1TX5ja3IwNiuriuFdQ5MTTcZ", "name": "Starter", "interval": "month", "amount_cents": 3900, "currency": "usd", "role": "starter", "display_mode": "default", "session_quota": 20, "max_seats": 1, "max_client_profiles": 50, "allowed_segments": [] }, { "id": "33333333-3333-3333-3333-333333333333", "stripe_price_id": "price_1TX5kL3IwNiuriuFabcdefgh", "name": "Professional", "interval": "month", "amount_cents": 9900, "currency": "usd", "role": "professional", "display_mode": "default", "session_quota": 75, "max_seats": 3, "max_client_profiles": 250, "allowed_segments": [] }, { "id": "44444444-4444-4444-4444-444444444444", "stripe_price_id": "price_1TX64W3IwNiuriuFlSDw2Scy", "name": "Organization", "interval": "month", "amount_cents": 24900, "currency": "usd", "role": "organization", "display_mode": "default", "session_quota": 250, "max_seats": 10, "max_client_profiles": 1000, "allowed_segments": [] }, { "id": "55555555-5555-5555-5555-555555555555", "stripe_price_id": "bundled_strategic_month", "name": "Strategic", "interval": "month", "amount_cents": 0, "currency": "usd", "role": "strategic", "display_mode": "custom", "session_quota": 0, "max_seats": 0, "max_client_profiles": 0, "allowed_segments": [] } ] ]}