Billing
Payment methods, subscriptions and purchases. Anything that charges is confirmed by a person.
Privacy and analytics
We use necessary technical cookies and, only with your consent, analytics and marketing pixels to improve the website and measure campaigns.
Payment methods, subscriptions and purchases. Anything that charges is confirmed by a person.
Nömad team only: creates a draft quote for the brand (createKey makes a retry return the same one) or saves changes to a draft (id and the version that was read).
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.quotes.save |
| MCP tool | billing_quotes_save |
| Scope | billing.write |
| Minimum role | Billing |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps |
| Status | Available |
Input
{
id?: string // uuid
version?: integer // –9007199254740991
createKey?: string // uuid
name: string // ≤ 200
currency: "eur" | "usd" | "gbp"
validUntil: string | null
items: Array<{
id: string // uuid
productId: string // ≤ 120
title: string // ≤ 240
quantity: integer // –1000000
unitAmount: integer // 0–2147483647
components: Array<{
serviceId: string // uuid
title: string // ≤ 240
quantity: number // –1000000
unit: string // ≤ 30
unitPrice: integer | null
}> // ≤ 100 items
}> // ≤ 100 items
}Output
{
id: string // uuid
}Nömad team only: marks a draft or sent quote as sent, accepted, rejected or expired (version is the one that was read).
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.quotes.transition |
| MCP tool | billing_quotes_transition |
| Scope | billing.write |
| Minimum role | Billing |
| Human confirmation | No |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
quoteId: string // uuid
version: integer // -9007199254740991–9007199254740991
status: "sent" | "accepted" | "rejected" | "expired"
}Output
{
id: string // uuid
}Nömad team only: turns an accepted quote into an order and returns the order id.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.quotes.convert |
| MCP tool | billing_quotes_convert |
| Scope | billing.write |
| Minimum role | Billing |
| Human confirmation | No |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
quoteId: string // uuid
}Output
{
orderId: string
}Nömad team only: creates an order for the brand from the given lines, without a quote (createKey makes a retry return the same order).
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.orders.create_manual |
| MCP tool | billing_orders_create_manual |
| Scope | billing.write |
| Minimum role | Billing |
| Human confirmation | No |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
id?: string // uuid
version?: integer // –9007199254740991
createKey?: string // uuid
name: string // ≤ 200
currency: "eur" | "usd" | "gbp"
validUntil: string | null
items: Array<{
id: string // uuid
productId: string // ≤ 120
title: string // ≤ 240
quantity: integer // –1000000
unitAmount: integer // 0–2147483647
components: Array<{
serviceId: string // uuid
title: string // ≤ 240
quantity: number // –1000000
unit: string // ≤ 30
unitPrice: integer | null
}> // ≤ 100 items
}> // ≤ 100 items
}Output
{
orderId: string
}Opens a Stripe SetupIntent for the brand's payer (card or SEPA debit) and returns the client secret the browser completes it with. Only brand members with billing access; Nömad staff never change a client's card. Never charges anything by itself.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.payment_methods.start_setup |
| MCP tool | billing_payment_methods_start_setup |
| Scope | billing.write |
| Minimum role | Billing |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{}Output
{
clientSecret: string
publishableKey: string
preferSepa: boolean
}After the browser completes the SetupIntent, saves the method as the default of the brand's payer and returns the saved method. Only accepts a SetupIntent created for that payer (forbidden otherwise).
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.payment_methods.confirm_setup |
| MCP tool | billing_payment_methods_confirm_setup |
| Scope | billing.write |
| Minimum role | Billing |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
setupIntentId: string
}Output
{
method: {
id: string
methodType: "card" | "sepa_debit" | "other"
displayBrand: string | null
last4: string | null
expMonth: integer | null
expYear: integer | null
wallet: string | null
createdAt: string
}
| null
}Changes the brand's paid plan or its billing interval. An upgrade is charged now with proration (it may return requiresAction with a client secret for 3DS); a downgrade is scheduled for the renewal and returns its effectiveDate.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.plan.change |
| MCP tool | billing_plan_change |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
productId: string // ≤ 80
interval: "month" | "year"
}Output
{
type: "upgrade" | "downgrade" | "interval_change"
effectiveDate?: string
requiresAction?: boolean
clientSecret?: string
}Undoes the downgrade or the move to Free scheduled for the renewal, so the current paid plan keeps renewing. Fails with not_found when the brand has no Stripe subscription.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.plan.cancel_scheduled_change |
| MCP tool | billing_plan_cancel_scheduled_change |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Turns automatic renewal of the paid plan at the end of the period on or off. Fails with not_found when the brand has no Stripe subscription.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.plan.set_auto_renewal |
| MCP tool | billing_plan_set_auto_renewal |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
enabled: boolean
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Cancels the paid Stripe subscription right away and puts the brand on the Free plan, with its Nödo budget. Not reversible from here: going back to a paid plan is a new checkout.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.plan.downgrade_to_free |
| MCP tool | billing_plan_downgrade_to_free |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Schedules the move to Free at the end of the paid period (or moves to Free now when there is no Stripe subscription). Returns the date it takes effect, when known; billing.plan.cancel_scheduled_change undoes it.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.plan.cancel |
| MCP tool | billing_plan_cancel |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{}Output
{
effectiveDate: string | null
}Opens hosted Stripe Checkout for a paid plan for the brand (after the Genome, or from «Plan») and returns its address. The plan only starts when Stripe confirms the payment through its webhook.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.plan.start_checkout |
| MCP tool | billing_plan_start_checkout |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
brandShortId: string // ≤ 40 · The brand's short id, checked against the brand being paid for.
productId: string // ≤ 80
interval: "month" | "year"
}Output
{
url: string // uri · The Stripe page to send the person to.
}Opens the Stripe customer portal of the brand's payer (plan, payment method, invoices) and returns its address. Fails with not_found when the payer has no Stripe customer yet.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.portal.open |
| MCP tool | billing_portal_open |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
brandShortId: string // ≤ 40
}Output
{
url: string // uri · The Stripe page to send the person to.
}Opens Stripe Checkout for a Nödo credit pack and returns its address. The credits only arrive when Stripe confirms the payment; fails with unavailable (purchase_disabled) while purchases are off.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.credits.start_checkout |
| MCP tool | billing_credits_start_checkout |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
packId: string // ≤ 80
returnTo?: string | null // A path inside this brand's app to come back to.
checkoutAttemptId?: string | null // Same id on a retry: the same Stripe page comes back.
}Output
{
url: string // uri · The Stripe page to send the person to.
}Freezes the accepted contract of a Store product (price and optional extras) and opens its Stripe Checkout, one-time or as a subscription. Returns the page address; prices always come from the catalogue, never from the caller.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.store.start_checkout |
| MCP tool | billing_store_start_checkout |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
productId: string // ≤ 120
successUrl: string // ≤ 2000 · An address inside the app; the session id is appended.
cancelUrl: string // ≤ 2000 · An address inside the app.
paymentType?: "full" | "remaining" // default "full"
billingMode?: "auto" | "one_time" | "recurring" // default "auto"
selectedPriceId?: string // ≤ 120
checkoutAttemptId?: string // ≤ 64
selectedExtras?: Array<{
lineKey: string // ≤ 120
quantity: integer // -9007199254740991–9007199254740991
}> // ≤ 50 items
attribution?: unknown // Campaign attribution the browser consented to; analytics only.
}Output
{
url: string | null
}Opens Stripe Checkout for the amount still due on one of the brand's orders and returns its address. Fails with conflict (nothing_remaining) when nothing is due; the return page is always the brand's orders page.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.orders.pay_remaining |
| MCP tool | billing_orders_pay_remaining |
| Scope | billing.write |
| Minimum role | Admin |
| Human confirmation | Yes |
| Doors | API, Screens, Apps |
| Status | Available |
Input
{
orderId: string // uuid
}Output
{
url: string | null
}Someone who hit a usage limit without billing rights notifies the brand's payers, with a direct link to the plan. One notice per person and day; the asker is never notified. Changes nothing by itself.
| Field | Value |
|---|---|
| Kind | Write |
| HTTP method | POST /api/v1/billing.usage.ask_for_more |
| MCP tool | billing_usage_ask_for_more |
| Scope | billing.write |
| Minimum role | Viewer |
| Human confirmation | No |
| Doors | API, MCP, Screens, Apps |
| Status | Available |
Input
{
reason: "feature_not_in_plan" | "allowance_exhausted" | "spend_cap_reached" | "payment_required" | "operation_too_large" | "ai_paused" | "rate_limited" | "provider_unavailable"
feature: "chat" | "voice" | "image" | "video" | "research" | "brand_setup" | "publishing" | "heartbeat" | "embedding" | "capability" | "library_export"
}Output
{
ok: true
id?: string
revision?: integer // -9007199254740991–9007199254740991
}Updated on January 1, 1970