DevelopersAPI reference

Billing API

REST endpoints for billing in ServFlo: 4 operations with parameters, request and response fields, permissions and curl examples.

Base URL: https://app.servflo.ai/api. Every call needs Authorization: Bearer sfk_… (Authentication); {organizationId} ($ORGANIZATION_ID in the examples) is your business's id.

OperationEndpointRisk
Get the ServFlo planGET /organizations/{organizationId}/billing/planread
List the plans to choose fromGET /organizations/{organizationId}/billing/plan-optionsread
Choose a plan (first run)POST /organizations/{organizationId}/billing/choose-plansensitive
List AI credit packsGET /organizations/{organizationId}/billing/credit-packsread

Get the ServFlo plan

GET /organizations/{organizationId}/billing/plan

The business's ServFlo plan: tier, trial, which plan features are included, and this period's AI credits, texts and ServFlo emails (used, allowance, purchased credits, remaining). Also lists every plan for comparison. Read-only; any member.

Permissionorganization.read (Owner, Admin, Dispatcher, Technician, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolbilling_plan (toolset settings)

Parameters

NameInTypeRequiredDescription
freshquerybooleanNoAsk Base316 again instead of the cached minute (after returning from the billing portal; at most every 10 seconds per business).

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/billing/plan" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
tierenum or nullNull when billing is not set up on this server. One of core, connect, grow, pro.
planNamestring or null
statusstring or nullTRIALING, ACTIVE, PAST_DUE, CANCELED, ...
trialEndsAtstring or null
trialDaysLeftinteger or nullWhole days left in the trial; null when not trialing.
currentPeriodEndstring or null
cancelAtPeriodEndboolean
featuresobjectPlan feature key → included.
usageobject
usage.ai_creditsobject or null
usage.ai_credits.usednumber
usage.ai_credits.limitnumber or nullNull is unlimited.
usage.ai_credits.creditsnumberPurchased or granted on top of the plan's allowance.
usage.ai_credits.remainingnumber or nullBelow zero: past the allowance (texts are then billed per segment).
usage.ai_credits.overageboolean
usage.smsobject or null
usage.sms.usednumber
usage.sms.limitnumber or nullNull is unlimited.
usage.sms.creditsnumberPurchased or granted on top of the plan's allowance.
usage.sms.remainingnumber or nullBelow zero: past the allowance (texts are then billed per segment).
usage.sms.overageboolean
usage.emailsobject or nullServFlo emails this period (allowance, used); null when the plan version predates the email allowance (then see emails below).
usage.emails.usednumber
usage.emails.limitnumber or nullNull is unlimited.
usage.emails.creditsnumberPurchased or granted on top of the plan's allowance.
usage.emails.remainingnumber or nullBelow zero: past the allowance (texts are then billed per segment).
usage.emails.overageboolean
usage.ai_voice_minutesobject or nullAI receptionist minutes this period (billed at cost + 20%); null when the plan version does not price them.
usage.ai_voice_minutes.usednumber
usage.ai_voice_minutes.limitnumber or nullNull is unlimited.
usage.ai_voice_minutes.creditsnumberPurchased or granted on top of the plan's allowance.
usage.ai_voice_minutes.remainingnumber or nullBelow zero: past the allowance (texts are then billed per segment).
usage.ai_voice_minutes.overageboolean
usage.visit_safety_checksobject or nullVisit safety lookups this period ($0.25 each); null when the plan version does not price them.
usage.visit_safety_checks.usednumber
usage.visit_safety_checks.limitnumber or nullNull is unlimited.
usage.visit_safety_checks.creditsnumberPurchased or granted on top of the plan's allowance.
usage.visit_safety_checks.remainingnumber or nullBelow zero: past the allowance (texts are then billed per segment).
usage.visit_safety_checks.overageboolean
usage.telephony_usageobject or nullTelephony billed this period, in cents (numbers, call minutes, recordings at Twilio's cost + 20%); null when not priced.
usage.telephony_usage.usednumber
usage.telephony_usage.limitnumber or nullNull is unlimited.
usage.telephony_usage.creditsnumberPurchased or granted on top of the plan's allowance.
usage.telephony_usage.remainingnumber or nullBelow zero: past the allowance (texts are then billed per segment).
usage.telephony_usage.overageboolean
visitSafetyobject or nullVisit safety lookups counted here this month; null when they cannot be counted.
visitSafety.usedThisMonthnumberPaid visit safety lookups this calendar month (UTC).
visitSafety.monthlyCapnumberThe business's monthly limit (Settings → Visit safety).
emailsobject or nullServFlo email against the plan's allowance; null when it cannot be counted.
emails.usedThisMonthnumberEmails sent through ServFlo email this calendar month (UTC), counted here.
emails.allowancenumber or nullThe plan's monthly email allowance (null: unknown plan).
officeUsersobjectOwners, admins, dispatchers and office staff against the plan's number.
officeUsers.usedinteger or nullOffice members plus pending office invitations; null when it could not be counted.
officeUsers.limitinteger or nullOffice users allowed: the plan's included ones plus the extra ones bought. Null is unlimited. Technicians are never counted.
officeUsers.includedinteger or nullThe plan's own office users (null is unlimited).
officeUsers.extraintegerExtra office users bought ($35/month each; billing.setOfficeSeats).
officeUsers.extraMonthlyPricenumberUSD per extra office user per month.
officeUsers.extraYearlyPricenumberUSD per extra office user per year (yearly plans).
officeUsers.maxExtrainteger
spendobjectWhether ServFlo may spend money for the business now (the cost gate).
spend.standingenumPAYMENT_METHOD_REQUIRED: a trial without a card: everything can be explored, but numbers, registrations, texts and calls to customers, the AI receptionist, ad spend, visit safety checks and campaigns wait for a card (402 PAYMENT_METHOD_REQUIRED). Add one in the billing portal (billing.portal with page: "payment-methods"); nothing is charged until the trial ends. One of OK, PAYMENT_METHOD_REQUIRED, BILLING_UNAVAILABLE.
spend.cardOnFileboolean or nullA card is on file (read during the trial and on Core); null when not read.
spend.compedbooleanA 100% coupon: never needs a card.
spend.noCardAiCreditsintegerAI credits a trial without a card may use in all.
spend.noCardEmailsPerDayintegerTest emails a day to the team's own addresses without a card.
degradedbooleanBilling could not be reached: this is the last known plan, or (planSource outage) none, and paid add-ons and new office users are paused.
subscriptionRequiredbooleanThe business has no live subscription (cancelled, unpaid, expired): ServFlo is read-only until a plan is chosen (billing.choosePlan). Reads, exports, billing and winding down still work; other writes answer 402 SUBSCRIPTION_REQUIRED.
planSourceenumWhere the plan came from: live (Base316), memory or stored (the last answer, Base316 unreachable), outage (nothing known), fake (development). One of live, memory, stored, outage, fake.
tiersarray of objectEvery plan, cheapest first, for comparison and upgrade prompts.
tiers[].keystring
tiers[].namestring
tiers[].taglinestring
tiers[].monthlyPricenumber
tiers[].yearlyPricenumber
tiers[].featuresarray of string
tiers[].officeUsersnumber or null
tiers[].aiCreditsnumber
tiers[].smsSegmentsnumber
tiers[].emailsnumberServFlo emails a month.
trialobject
trial.tierstring
trial.daysnumber
addonsarray of objectPaid add-ons sold on any plan, and whether this business has each one.
addons[].keystringAdd-on key: phone, ai_receptionist, ads, service_reports or extra_office_user (seats: billing.setOfficeSeats).
addons[].featurestring or nullThe plan feature it includes; null for extra office users.
addons[].modelenumPER_UNIT: priced per unit (one per extra office user). One of FLAT, PER_UNIT.
addons[].includedInTiersarray of stringPlans that already include it (not sold to them).
addons[].soldOnPlanbooleanCan be added on this business's plan (false when the plan includes it).
addons[].quantityintegerUnits attached now (extra office users); 0 or 1 otherwise.
addons[].namestring
addons[].descriptionstring
addons[].monthlyPricenumberUSD per month on a monthly plan.
addons[].yearlyPricenumberUSD per year on a yearly plan.
addons[].includedInTrialbooleanThe free trial includes it, within the trial's telephony limits.
addons[].requiresstring or nullThe add-on it needs first (phone).
addons[].includedNumbersintegerLocal numbers it includes.
addons[].draftbooleanNot on sale yet: its price is not decided, and adding it is refused (409).
addons[].attachedbooleanOn this business's subscription now.
addons[].termsobjectThe fee and every usage rate today: shown and accepted before adding it.
addons[].terms.keystring
addons[].terms.namestring
addons[].terms.monthlyPricenumberUSD per month on a monthly plan.
addons[].terms.yearlyPricenumberUSD per year on a yearly plan.
addons[].terms.includedNumbersintegerLocal numbers whose monthly charge is included.
addons[].terms.requiresstring or nullThe add-on it needs (phone), or null.
addons[].terms.markupnumberUsage is billed at cost × this (1.2 = cost + 20%).
addons[].terms.ratesarray of objectEvery usage rate at the price the business pays.
addons[].terms.exampleobject
addons[].terms.trialobjectWhat the free trial includes before the phone and AI receptionist pause.
addons[].terms.ratesSourceenumTwilio's Pricing API today, or ServFlo's documented fallback table. One of twilio, fallback.
addons[].terms.priceVersionstringSend this back in acknowledgement.priceVersion.
addons[].acknowledgementobject or nullThe last acceptance of its terms (who, when, which version), or null.
addons[].acknowledgement.userIdstring
addons[].acknowledgement.userNamestring or null
addons[].acknowledgement.acceptedAtstring (date-time)
addons[].acknowledgement.priceVersionstring
addons[].acknowledgement.contextenumOne of ADD_ADDON, MANAGED_TELEPHONY, REVIEW.
addons[].acknowledgement.termsobject or nullExactly what was shown and accepted (“View terms”).
addons[].needsReviewbooleanAttached, and its prices changed since they were accepted: an owner should review and accept them again (billing.acknowledgeTerms). Nothing is removed.
billingIntervalenum or nullThe subscription's interval: usage is billed in arrears at the end of each. One of month, year.

List the plans to choose from

GET /organizations/{organizationId}/billing/plan-options

The ServFlo plans a business can choose, cheapest first, as Base316 sells them: name, description, monthly and yearly price (integer cents), office users included (null = unlimited), the features included, and the free-trial days on the trial plan. Also trial (the plan and days a new business starts on with no card) and whether this business still has to choose (needsChoice). Read-only; any member. Choose with POST /billing/choose-plan.

Permissionorganization.read (Owner, Admin, Dispatcher, Technician, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolbilling_planOptions (toolset settings)

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/billing/plan-options" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
plansarray of object
plans[].keystring
plans[].namestring
plans[].descriptionstring or null
plans[].monthlyCentsinteger or null
plans[].yearlyCentsinteger or null
plans[].officeUsersinteger or null
plans[].featuresarray of string
plans[].trialDaysinteger or null
trialobject
trial.tierstring
trial.daysinteger
needsChoiceboolean

Choose a plan (first run)

POST /organizations/{organizationId}/billing/choose-plan

Money: the owner's plan choice after sign-up. plan: "trial" keeps the free trial the business started on (no card, nothing billed) and returns url: null. A plan key (with interval month or year) returns a one-time Base316 checkout link for that plan, where the owner enters a card and pays; the trial ends once the paid plan starts. Either way the business no longer sees the plan screen. Owner only.

Permissionorganization.accessBillingPortal (Owner)
Risksensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolbilling_choosePlan (toolset settings)
ApprovalWaits for your approval in ServFlo when called with an API key or a connected app: the first call answers 428 APPROVAL_REQUIRED; once you approve it, repeat the call with the X-ServFlo-Approval header. See Approvals.

Request body

FieldTypeRequiredDescription
planenumYes"trial" to keep the free trial, or a plan key from GET /billing/plan-options. One of trial, core, connect, grow, pro.
intervalenumNoOne of month, year. Default month.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/billing/choose-plan" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"plan":"trial"}'

Response

200: the answer's fields
FieldTypeDescription
urlstring or nullThe Base316 checkout page to open; null when nothing is to be paid.

List AI credit packs

GET /organizations/{organizationId}/billing/credit-packs

The AI credit packs on sale (credits, price), cheapest first. Buy one with billing.buyCredits. Read-only.

Permissionorganization.read (Owner, Admin, Dispatcher, Technician, Member)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolbilling_creditPacks (toolset settings)

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/billing/credit-packs" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
packsarray of object
packs[].keystring
packs[].namestring
packs[].creditsnumber
packs[].pricestring
packs[].currencystring

On this page