DevelopersAPI reference

Memberships API

REST endpoints for memberships in ServFlo: 16 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
List membership plansGET /organizations/{organizationId}/membership-plansread
Create a membership planPOST /organizations/{organizationId}/membership-planswrite
Get a membership planGET /organizations/{organizationId}/membership-plans/{membershipPlanId}read
Update a membership planPATCH /organizations/{organizationId}/membership-plans/{membershipPlanId}write
Delete a membership planDELETE /organizations/{organizationId}/membership-plans/{membershipPlanId}sensitive
Membership settingsGET /organizations/{organizationId}/membership-settingsread
Change membership settingsPATCH /organizations/{organizationId}/membership-settingswrite
List membershipsGET /organizations/{organizationId}/membershipsread
Sign a customer up to a membership planPOST /organizations/{organizationId}/membershipswrite
Get a membershipGET /organizations/{organizationId}/memberships/{membershipId}read
Change auto-renew, property or notesPATCH /organizations/{organizationId}/memberships/{membershipId}write
Pause a membershipPOST /organizations/{organizationId}/memberships/{membershipId}/pausewrite
Reinstate a paused or cancelled membershipPOST /organizations/{organizationId}/memberships/{membershipId}/reinstatewrite
Renew a membershipPOST /organizations/{organizationId}/memberships/{membershipId}/renewwrite
Cancel a membershipPOST /organizations/{organizationId}/memberships/{membershipId}/cancelsensitive
Run the membership scheduler nowPOST /organizations/{organizationId}/memberships/ticksensitive

List membership plans

GET /organizations/{organizationId}/membership-plans

The organization's membership plans (price, frequency, term, included visits, discounts, priority) with memberCount (active and paused members). Retired plans only with includeInactive. Read-only.

Permissionmemberships.read (Owner, Admin, Dispatcher)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolmembershipPlans_list (toolset sales)

Parameters

NameInTypeRequiredDescription
includeInactivequerybooleanNoInclude retired plans.

Example

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

Response

200: the answer's fields

An array of objects:

FieldTypeDescription
idstring
organizationIdstring
namestring
descriptionstring or null
activeboolean
priceCentsintegerInteger cents.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
autoRenewDefaultboolean
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
createdAtstring (date-time)
updatedAtstring (date-time)
memberCountinteger

Create a membership plan

POST /organizations/{organizationId}/membership-plans

Creates a plan customers can sign up to. Included visits name service types from GET /service-types (400 for another organization's). The term must be a whole number of billing periods. Nothing is billed until a customer signs up.

Permissionmemberships.plans.manage (Owner, Admin)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmembershipPlans_create (toolset sales)

Request body

FieldTypeRequiredDescription
namestringYesUp to 200 characters.
descriptionstring or nullNoUp to 5000 characters.
activebooleanNoRetired plans (false) take no new members.
priceCentsintegerYesPrice per billing period, cents. 0–100000000.
billingFrequencyenumYesHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsintegerYesTerm length in months; a whole number of billing periods for MONTHLY to ANNUAL (week-based frequencies clip the last period). 1–60.
autoRenewDefaultbooleanNoNew members renew automatically by default.
includedVisitsarray of objectNoUp to 20 items.
includedVisits[].serviceTypeIdstringYesFrom GET /service-types.
includedVisits[].countintegerNoVisits of this service per term. Required unless everyWeeks is set (then it is derived from the cadence and the term). 1–52.
includedVisits[].monthsarray of integer or nullNoPreferred calendar months, 1–12 (e.g. [4, 10] for spring and fall tune-ups). Up to 12 items.
includedVisits[].spacingMonthsinteger or nullNoMonths between visits when no months are given; default spreads them evenly. 1–60.
includedVisits[].everyWeeksinteger or nullNoA week cadence: one visit every N weeks through the term (e.g. 2 = a wash every other week), from the term's first day or the first weekday on or after it. Overrides count, months and spacingMonths. 1–52.
includedVisits[].weekdayinteger or nullNoPreferred day of the week for an everyWeeks cadence: 0 = Sunday … 6 = Saturday. 0–6.
serviceDiscountPercentnumberNoMember discount on service / labour lines of quotes and invoices, percent. 0–100.
materialDiscountPercentnumberNoMember discount on material lines, percent. 0–100.
prioritybooleanNoMembers' work is flagged Priority on the dispatch board.
taxablebooleanNoMembership invoices are taxed at the property's rate (never for tax-exempt customers), as other invoices.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/membership-plans" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Dana Whitfield","priceCents":12500,"billingFrequency":"WEEKLY","termMonths":1}'

Response

201: the answer's fields
FieldTypeDescription
idstring
organizationIdstring
namestring
descriptionstring or null
activeboolean
priceCentsintegerInteger cents.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
autoRenewDefaultboolean
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
createdAtstring (date-time)
updatedAtstring (date-time)

Get a membership plan

GET /organizations/{organizationId}/membership-plans/{membershipPlanId}

One plan with its included visits and discounts. Read-only. Plan ids come from GET /membership-plans.

Permissionmemberships.read (Owner, Admin, Dispatcher)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolmembershipPlans_get (toolset sales)

Parameters

NameInTypeRequiredDescription
membershipPlanIdpathstringYes

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/membership-plans/{membershipPlanId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
organizationIdstring
namestring
descriptionstring or null
activeboolean
priceCentsintegerInteger cents.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
autoRenewDefaultboolean
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
createdAtstring (date-time)
updatedAtstring (date-time)

Update a membership plan

PATCH /organizations/{organizationId}/membership-plans/{membershipPlanId}

Changes a plan for NEW signups only: existing members keep the price, frequency, discounts and included visits frozen at their signup. active: false retires the plan.

Permissionmemberships.plans.manage (Owner, Admin)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmembershipPlans_update (toolset sales)

Parameters

NameInTypeRequiredDescription
membershipPlanIdpathstringYes

Request body

FieldTypeRequiredDescription
namestringNoUp to 200 characters.
descriptionstring or nullNoUp to 5000 characters.
activebooleanNoRetired plans (false) take no new members.
priceCentsintegerNoPrice per billing period, cents. 0–100000000.
billingFrequencyenumNoHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsintegerNoTerm length in months; a whole number of billing periods for MONTHLY to ANNUAL (week-based frequencies clip the last period). 1–60.
autoRenewDefaultbooleanNoNew members renew automatically by default.
includedVisitsarray of objectNoUp to 20 items.
includedVisits[].serviceTypeIdstringYesFrom GET /service-types.
includedVisits[].countintegerNoVisits of this service per term. Required unless everyWeeks is set (then it is derived from the cadence and the term). 1–52.
includedVisits[].monthsarray of integer or nullNoPreferred calendar months, 1–12 (e.g. [4, 10] for spring and fall tune-ups). Up to 12 items.
includedVisits[].spacingMonthsinteger or nullNoMonths between visits when no months are given; default spreads them evenly. 1–60.
includedVisits[].everyWeeksinteger or nullNoA week cadence: one visit every N weeks through the term (e.g. 2 = a wash every other week), from the term's first day or the first weekday on or after it. Overrides count, months and spacingMonths. 1–52.
includedVisits[].weekdayinteger or nullNoPreferred day of the week for an everyWeeks cadence: 0 = Sunday … 6 = Saturday. 0–6.
serviceDiscountPercentnumberNoMember discount on service / labour lines of quotes and invoices, percent. 0–100.
materialDiscountPercentnumberNoMember discount on material lines, percent. 0–100.
prioritybooleanNoMembers' work is flagged Priority on the dispatch board.
taxablebooleanNoMembership invoices are taxed at the property's rate (never for tax-exempt customers), as other invoices.

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/membership-plans/{membershipPlanId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Dana Whitfield","description":"string","active":true}'

Response

200: the answer's fields
FieldTypeDescription
idstring
organizationIdstring
namestring
descriptionstring or null
activeboolean
priceCentsintegerInteger cents.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
autoRenewDefaultboolean
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
createdAtstring (date-time)
updatedAtstring (date-time)

Delete a membership plan

DELETE /organizations/{organizationId}/membership-plans/{membershipPlanId}

Destructive: deletes a plan nobody ever joined. Refused (409) when it has or had members: retire it with PATCH active: false instead.

Permissionmemberships.plans.manage (Owner, Admin)
Risksensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolmembershipPlans_delete (toolset sales)
ApprovalOver MCP, this tool always waits for your approval in ServFlo. See Approvals.

Parameters

NameInTypeRequiredDescription
membershipPlanIdpathstringYes

Example

curl -X DELETE "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/membership-plans/{membershipPlanId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
oktrue

Membership settings

GET /organizations/{organizationId}/membership-settings

The status the scheduler gives membership invoices (DRAFT or SENT) and the lead time, in days, before a member visit's due month that its job is created. Read-only.

Permissionmemberships.read (Owner, Admin, Dispatcher)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolmembershipSettings_get (toolset settings)

Example

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

Response

200: the answer's fields
FieldTypeDescription
invoiceStatusenumStatus of the invoices the scheduler creates on each billing date. One of DRAFT, SENT.
visitLeadDaysintegerDays before a member visit's due month that its unscheduled job is created.

Change membership settings

PATCH /organizations/{organizationId}/membership-settings

Sets the status of future membership invoices (invoiceStatus: DRAFT to review first, SENT to issue them directly; nothing is emailed either way) and the visit lead time (visitLeadDays, 0–180). Applies from the next scheduler run.

Permissionmemberships.plans.manage (Owner, Admin)
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmembershipSettings_update (toolset settings)

Request body

FieldTypeRequiredDescription
invoiceStatusenumNoOne of DRAFT, SENT.
visitLeadDaysintegerNo0–180.

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/membership-settings" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"invoiceStatus":"DRAFT","visitLeadDays":1}'

Response

200: the answer's fields
FieldTypeDescription
invoiceStatusenumStatus of the invoices the scheduler creates on each billing date. One of DRAFT, SENT.
visitLeadDaysintegerDays before a member visit's due month that its unscheduled job is created.

List memberships

GET /organizations/{organizationId}/memberships

Memberships newest first (by end date for a renewal window), filtered by status, plan, customer, property or renewalWithinDays (ACTIVE ones whose term ends within that many days: the Renewals view), with total and a summary strip: active members, MRR (normalised to a month), renewals due in 30 days, member visits waiting for a date. Read-only.

Permissionmemberships.read (Owner, Admin, Dispatcher)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolmemberships_list (toolset sales, in the default set)

Parameters

NameInTypeRequiredDescription
queryquerystringNoFree-text search over the list's names, numbers and contact details. Up to 200 characters.
statusqueryenumNoACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
planIdquerystringNo
customerIdquerystringNo
propertyIdquerystringNo
businessUnitIdquerystringNoOnly this business unit (GET /business-units), or "none" for records without one. Up to 100 characters.
renewalWithinDaysqueryintegerNoOnly ACTIVE memberships ending within this many days (30, 60, 90). 1–366.
todayquerystringNoThe business's today (YYYY-MM-DD) for date checks; used only within a day of the organization's own date (its timezone). Default: that date.
limitqueryintegerNoPage size, 1–200. Default 50.
offsetqueryintegerNoRows to skip; the answer's total counts every match. Default 0.

Example

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

Response

200: the answer's fields
FieldTypeDescription
itemsarray of object
items[].idstring
items[].identifierstringMEM-n
items[].customerIdstring
items[].propertyIdstring or null
items[].planIdstring
items[].planNamestringSnapshot at signup.
items[].priceCentsintegerPrice per billing period, frozen at signup.
items[].billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
items[].termMonthsinteger
items[].serviceDiscountPercentnumber
items[].materialDiscountPercentnumber
items[].priorityboolean
items[].taxableboolean
items[].statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
items[].startDatestringSignup date, YYYY-MM-DD.
items[].termNumberintegerCurrent term, 1 = the first.
items[].termStartDatestring
items[].endDatestringLast day of the current term.
items[].autoRenewboolean
items[].nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
items[].cancelledAtstring (date-time) or null
items[].cancelReasonstring or null
items[].pausedUntilstring or null
items[].pausedAtstring (date-time) or null
items[].sourceQuoteIdstring or null
items[].businessUnitIdstring or nullBusiness unit; null = none.
items[].notesstring or null
items[].createdAtstring (date-time)
items[].updatedAtstring (date-time)
items[].monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
items[].visitUsageobjectIncluded visits of the current term.
items[].visitUsage.includedinteger
items[].visitUsage.usedintegerCompleted this term.
items[].visitUsage.remainingintegerDue or scheduled this term.
items[].customerobject
items[].customer.idstring
items[].customer.namestring
items[].propertyobject or null
items[].property.idstring
items[].property.namestring or null
items[].property.addressstring or null
items[].property.citystring or null
items[].planobject
items[].plan.idstring
items[].plan.namestring
items[].plan.activeboolean
totalinteger
summaryobject
summary.activeMembersinteger
summary.mrrCentsintegerMonthly recurring revenue of ACTIVE memberships.
summary.renewalsDue30integerACTIVE memberships whose term ends within 30 days.
summary.memberVisitsDueintegerGenerated member visits still waiting for a date (Dispatch Needs scheduling).

Sign a customer up to a membership plan

POST /organizations/{organizationId}/memberships

Creates an ACTIVE membership (MEM-n) on an active plan, freezing the plan's price, frequency, discounts and included visits, and lays out the first term's visits. A membership starting today is processed at once: its first billing period is invoiced (status per GET /membership-settings; nothing is charged or emailed) and visits whose window is open become unscheduled jobs. Customer from GET /customers, property (optional; one of the customer's) from GET /customers/{customerId}, plan from GET /membership-plans.

Permission: memberships.write (Owner, Admin, Dispatcher, Technician (own jobs)); risk write (OAuth scope servflo.write).

Permissionmemberships.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmemberships_create (toolset sales)

Request body

FieldTypeRequiredDescription
customerIdstringYes
planIdstringYes
propertyIdstring or nullNoOptional; without one, member pricing covers all the customer's properties.
startDatestringNoDefaults to today.
autoRenewbooleanNoDefaults to the plan's setting.
sourceQuoteIdstring or nullNoThe customer's quote that sold the membership, kept as a link.
soldByTechnicianIdstring or nullNoThe technician who sold it, for membership-sale commissions (else the source quote's seller).
businessUnitIdstring or nullNoBusiness unit (GET /business-units). Omitted: the selling technician's home unit; null = none. Its billing invoices and member visits follow it. Up to 100 characters.
notesstring or nullNo
agreementobject or nullNoThe customer's signed agreement, when they signed up on a technician's phone.
agreement.termsstringYesThe agreement shown (GET /signing-terms resolved.membershipTerms). Up to 5000 characters.
agreement.signedBystringYesUp to 200 characters.
agreement.signatureDataUrlstring or nullNoA data:image/png;base64 URL.
todaystringNoThe business's today (YYYY-MM-DD) for date checks; used only within a day of the organization's own date (its timezone). Default: that date.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"customerId":"customer_id","planId":"plan_id"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
identifierstringMEM-n
customerIdstring
propertyIdstring or null
planIdstring
planNamestringSnapshot at signup.
priceCentsintegerPrice per billing period, frozen at signup.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
startDatestringSignup date, YYYY-MM-DD.
termNumberintegerCurrent term, 1 = the first.
termStartDatestring
endDatestringLast day of the current term.
autoRenewboolean
nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
cancelledAtstring (date-time) or null
cancelReasonstring or null
pausedUntilstring or null
pausedAtstring (date-time) or null
sourceQuoteIdstring or null
businessUnitIdstring or nullBusiness unit; null = none.
notesstring or null
createdAtstring (date-time)
updatedAtstring (date-time)
monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
visitUsageobjectIncluded visits of the current term.
visitUsage.includedinteger
visitUsage.usedintegerCompleted this term.
visitUsage.remainingintegerDue or scheduled this term.
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
soldByTechnicianIdstring or nullThe technician credited with the sale.
agreementTermsstring or nullThe agreement the customer signed on a technician's phone.
agreementSignedBystring or null
agreementSignedAtstring (date-time) or null
agreementSignaturestring or nullTheir drawn signature (PNG data URL).
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
planobject
plan.idstring
plan.namestring
plan.activeboolean
sourceQuoteobject or null
sourceQuote.idstring
sourceQuote.identifierstring
sourceQuote.statusstring
visitsarray of object
visits[].idstring
visits[].termNumberinteger
visits[].sequenceinteger
visits[].serviceTypeIdstring or null
visits[].serviceNamestring
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].dueMonthstringYYYY-MM
visits[].dueDatestring or nullYYYY-MM-DD for a visit on a week cadence; null for month-based visits.
visits[].statusenumDUE (not booked yet; its job may already wait in Dispatch Needs scheduling), SCHEDULED (the job has a date), COMPLETED, SKIPPED (cancelled or expired). One of DUE, SCHEDULED, COMPLETED, SKIPPED.
visits[].jobIdstring or null
visits[].generatedAtstring (date-time) or null
visits[].jobobject or null
visits[].job.idstring
visits[].job.identifierstring
visits[].job.statusstring
visits[].job.scheduledDatestring or nullNull while the visit has no date.
visits[].job.completedAtstring (date-time) or null
billingsarray of object
billings[].idstring
billings[].periodStartstring
billings[].periodEndstring
billings[].amountCentsintegerInteger cents.
billings[].invoiceIdstring or null
billings[].createdAtstring (date-time)
billings[].invoiceobject or null
billings[].invoice.idstring
billings[].invoice.identifierstring
billings[].invoice.statusstring
billings[].invoice.totalCentsintegerInteger cents.
billings[].invoice.amountPaidCentsintegerInteger cents.

Get a membership

GET /organizations/{organizationId}/memberships/{membershipId}

One membership: the plan snapshot, every included visit by term (due month, status, the job it became), billing history with invoices, and status. Read-only. Ids come from GET /memberships.

Permissionmemberships.read (Owner, Admin, Dispatcher)
Riskread, OAuth scope servflo.read. Read: reads only.
MCP toolmemberships_get (toolset sales)

Parameters

NameInTypeRequiredDescription
membershipIdpathstringYes

Example

curl "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships/{membershipId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
identifierstringMEM-n
customerIdstring
propertyIdstring or null
planIdstring
planNamestringSnapshot at signup.
priceCentsintegerPrice per billing period, frozen at signup.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
startDatestringSignup date, YYYY-MM-DD.
termNumberintegerCurrent term, 1 = the first.
termStartDatestring
endDatestringLast day of the current term.
autoRenewboolean
nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
cancelledAtstring (date-time) or null
cancelReasonstring or null
pausedUntilstring or null
pausedAtstring (date-time) or null
sourceQuoteIdstring or null
businessUnitIdstring or nullBusiness unit; null = none.
notesstring or null
createdAtstring (date-time)
updatedAtstring (date-time)
monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
visitUsageobjectIncluded visits of the current term.
visitUsage.includedinteger
visitUsage.usedintegerCompleted this term.
visitUsage.remainingintegerDue or scheduled this term.
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
soldByTechnicianIdstring or nullThe technician credited with the sale.
agreementTermsstring or nullThe agreement the customer signed on a technician's phone.
agreementSignedBystring or null
agreementSignedAtstring (date-time) or null
agreementSignaturestring or nullTheir drawn signature (PNG data URL).
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
planobject
plan.idstring
plan.namestring
plan.activeboolean
sourceQuoteobject or null
sourceQuote.idstring
sourceQuote.identifierstring
sourceQuote.statusstring
visitsarray of object
visits[].idstring
visits[].termNumberinteger
visits[].sequenceinteger
visits[].serviceTypeIdstring or null
visits[].serviceNamestring
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].dueMonthstringYYYY-MM
visits[].dueDatestring or nullYYYY-MM-DD for a visit on a week cadence; null for month-based visits.
visits[].statusenumDUE (not booked yet; its job may already wait in Dispatch Needs scheduling), SCHEDULED (the job has a date), COMPLETED, SKIPPED (cancelled or expired). One of DUE, SCHEDULED, COMPLETED, SKIPPED.
visits[].jobIdstring or null
visits[].generatedAtstring (date-time) or null
visits[].jobobject or null
visits[].job.idstring
visits[].job.identifierstring
visits[].job.statusstring
visits[].job.scheduledDatestring or nullNull while the visit has no date.
visits[].job.completedAtstring (date-time) or null
billingsarray of object
billings[].idstring
billings[].periodStartstring
billings[].periodEndstring
billings[].amountCentsintegerInteger cents.
billings[].invoiceIdstring or null
billings[].createdAtstring (date-time)
billings[].invoiceobject or null
billings[].invoice.idstring
billings[].invoice.identifierstring
billings[].invoice.statusstring
billings[].invoice.totalCentsintegerInteger cents.
billings[].invoice.amountPaidCentsintegerInteger cents.

Change auto-renew, property or notes

PATCH /organizations/{organizationId}/memberships/{membershipId}

Turns auto-renew on or off, moves the membership to another of the customer's properties (or none) and edits its notes. The plan snapshot cannot change.

Permission: memberships.write (Owner, Admin, Dispatcher, Technician (own jobs)); risk write (OAuth scope servflo.write).

Permissionmemberships.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmemberships_update (toolset sales)

Parameters

NameInTypeRequiredDescription
membershipIdpathstringYes

Request body

FieldTypeRequiredDescription
autoRenewbooleanNo
propertyIdstring or nullNo
notesstring or nullNo
businessUnitIdstring or nullNoMove the membership to another business unit (GET /business-units), or null for none. Up to 100 characters.

Example

curl -X PATCH "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships/{membershipId}" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"autoRenew":true,"propertyId":"property_id","notes":"string"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
identifierstringMEM-n
customerIdstring
propertyIdstring or null
planIdstring
planNamestringSnapshot at signup.
priceCentsintegerPrice per billing period, frozen at signup.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
startDatestringSignup date, YYYY-MM-DD.
termNumberintegerCurrent term, 1 = the first.
termStartDatestring
endDatestringLast day of the current term.
autoRenewboolean
nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
cancelledAtstring (date-time) or null
cancelReasonstring or null
pausedUntilstring or null
pausedAtstring (date-time) or null
sourceQuoteIdstring or null
businessUnitIdstring or nullBusiness unit; null = none.
notesstring or null
createdAtstring (date-time)
updatedAtstring (date-time)
monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
visitUsageobjectIncluded visits of the current term.
visitUsage.includedinteger
visitUsage.usedintegerCompleted this term.
visitUsage.remainingintegerDue or scheduled this term.
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
soldByTechnicianIdstring or nullThe technician credited with the sale.
agreementTermsstring or nullThe agreement the customer signed on a technician's phone.
agreementSignedBystring or null
agreementSignedAtstring (date-time) or null
agreementSignaturestring or nullTheir drawn signature (PNG data URL).
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
planobject
plan.idstring
plan.namestring
plan.activeboolean
sourceQuoteobject or null
sourceQuote.idstring
sourceQuote.identifierstring
sourceQuote.statusstring
visitsarray of object
visits[].idstring
visits[].termNumberinteger
visits[].sequenceinteger
visits[].serviceTypeIdstring or null
visits[].serviceNamestring
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].dueMonthstringYYYY-MM
visits[].dueDatestring or nullYYYY-MM-DD for a visit on a week cadence; null for month-based visits.
visits[].statusenumDUE (not booked yet; its job may already wait in Dispatch Needs scheduling), SCHEDULED (the job has a date), COMPLETED, SKIPPED (cancelled or expired). One of DUE, SCHEDULED, COMPLETED, SKIPPED.
visits[].jobIdstring or null
visits[].generatedAtstring (date-time) or null
visits[].jobobject or null
visits[].job.idstring
visits[].job.identifierstring
visits[].job.statusstring
visits[].job.scheduledDatestring or nullNull while the visit has no date.
visits[].job.completedAtstring (date-time) or null
billingsarray of object
billings[].idstring
billings[].periodStartstring
billings[].periodEndstring
billings[].amountCentsintegerInteger cents.
billings[].invoiceIdstring or null
billings[].createdAtstring (date-time)
billings[].invoiceobject or null
billings[].invoice.idstring
billings[].invoice.identifierstring
billings[].invoice.statusstring
billings[].invoice.totalCentsintegerInteger cents.
billings[].invoice.amountPaidCentsintegerInteger cents.

Pause a membership

POST /organizations/{organizationId}/memberships/{membershipId}/pause

Stops billing and visit generation until pausedUntil (it resumes on that day; periods that fell due while paused are not billed) or until reinstated. The term end does not move. Only ACTIVE memberships (409).

Permission: memberships.write (Owner, Admin, Dispatcher, Technician (own jobs)); risk write (OAuth scope servflo.write).

Permissionmemberships.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmemberships_pause (toolset sales)

Parameters

NameInTypeRequiredDescription
membershipIdpathstringYes

Request body

FieldTypeRequiredDescription
pausedUntilstring or nullNoResume on this date; omit to pause until reinstated.
todaystringNoThe business's today (YYYY-MM-DD) for date checks; used only within a day of the organization's own date (its timezone). Default: that date.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships/{membershipId}/pause" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pausedUntil":"string","today":"2026-11-03"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
identifierstringMEM-n
customerIdstring
propertyIdstring or null
planIdstring
planNamestringSnapshot at signup.
priceCentsintegerPrice per billing period, frozen at signup.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
startDatestringSignup date, YYYY-MM-DD.
termNumberintegerCurrent term, 1 = the first.
termStartDatestring
endDatestringLast day of the current term.
autoRenewboolean
nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
cancelledAtstring (date-time) or null
cancelReasonstring or null
pausedUntilstring or null
pausedAtstring (date-time) or null
sourceQuoteIdstring or null
businessUnitIdstring or nullBusiness unit; null = none.
notesstring or null
createdAtstring (date-time)
updatedAtstring (date-time)
monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
visitUsageobjectIncluded visits of the current term.
visitUsage.includedinteger
visitUsage.usedintegerCompleted this term.
visitUsage.remainingintegerDue or scheduled this term.
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
soldByTechnicianIdstring or nullThe technician credited with the sale.
agreementTermsstring or nullThe agreement the customer signed on a technician's phone.
agreementSignedBystring or null
agreementSignedAtstring (date-time) or null
agreementSignaturestring or nullTheir drawn signature (PNG data URL).
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
planobject
plan.idstring
plan.namestring
plan.activeboolean
sourceQuoteobject or null
sourceQuote.idstring
sourceQuote.identifierstring
sourceQuote.statusstring
visitsarray of object
visits[].idstring
visits[].termNumberinteger
visits[].sequenceinteger
visits[].serviceTypeIdstring or null
visits[].serviceNamestring
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].dueMonthstringYYYY-MM
visits[].dueDatestring or nullYYYY-MM-DD for a visit on a week cadence; null for month-based visits.
visits[].statusenumDUE (not booked yet; its job may already wait in Dispatch Needs scheduling), SCHEDULED (the job has a date), COMPLETED, SKIPPED (cancelled or expired). One of DUE, SCHEDULED, COMPLETED, SKIPPED.
visits[].jobIdstring or null
visits[].generatedAtstring (date-time) or null
visits[].jobobject or null
visits[].job.idstring
visits[].job.identifierstring
visits[].job.statusstring
visits[].job.scheduledDatestring or nullNull while the visit has no date.
visits[].job.completedAtstring (date-time) or null
billingsarray of object
billings[].idstring
billings[].periodStartstring
billings[].periodEndstring
billings[].amountCentsintegerInteger cents.
billings[].invoiceIdstring or null
billings[].createdAtstring (date-time)
billings[].invoiceobject or null
billings[].invoice.idstring
billings[].invoice.identifierstring
billings[].invoice.statusstring
billings[].invoice.totalCentsintegerInteger cents.
billings[].invoice.amountPaidCentsintegerInteger cents.

Reinstate a paused or cancelled membership

POST /organizations/{organizationId}/memberships/{membershipId}/reinstate

A PAUSED membership resumes now; a CANCELLED one whose term has not ended becomes ACTIVE again (skipped visits still ahead return to DUE, billing picks up at the next unbilled period on or after today and may create an invoice). 409 otherwise (an ended term is renewed instead).

Permission: memberships.write (Owner, Admin, Dispatcher, Technician (own jobs)); risk write (OAuth scope servflo.write).

Permissionmemberships.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmemberships_reinstate (toolset sales)

Parameters

NameInTypeRequiredDescription
membershipIdpathstringYes

Request body

FieldTypeRequiredDescription
todaystringNoThe business's today (YYYY-MM-DD) for date checks; used only within a day of the organization's own date (its timezone). Default: that date.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships/{membershipId}/reinstate" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"today":"2026-11-03"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
identifierstringMEM-n
customerIdstring
propertyIdstring or null
planIdstring
planNamestringSnapshot at signup.
priceCentsintegerPrice per billing period, frozen at signup.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
startDatestringSignup date, YYYY-MM-DD.
termNumberintegerCurrent term, 1 = the first.
termStartDatestring
endDatestringLast day of the current term.
autoRenewboolean
nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
cancelledAtstring (date-time) or null
cancelReasonstring or null
pausedUntilstring or null
pausedAtstring (date-time) or null
sourceQuoteIdstring or null
businessUnitIdstring or nullBusiness unit; null = none.
notesstring or null
createdAtstring (date-time)
updatedAtstring (date-time)
monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
visitUsageobjectIncluded visits of the current term.
visitUsage.includedinteger
visitUsage.usedintegerCompleted this term.
visitUsage.remainingintegerDue or scheduled this term.
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
soldByTechnicianIdstring or nullThe technician credited with the sale.
agreementTermsstring or nullThe agreement the customer signed on a technician's phone.
agreementSignedBystring or null
agreementSignedAtstring (date-time) or null
agreementSignaturestring or nullTheir drawn signature (PNG data URL).
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
planobject
plan.idstring
plan.namestring
plan.activeboolean
sourceQuoteobject or null
sourceQuote.idstring
sourceQuote.identifierstring
sourceQuote.statusstring
visitsarray of object
visits[].idstring
visits[].termNumberinteger
visits[].sequenceinteger
visits[].serviceTypeIdstring or null
visits[].serviceNamestring
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].dueMonthstringYYYY-MM
visits[].dueDatestring or nullYYYY-MM-DD for a visit on a week cadence; null for month-based visits.
visits[].statusenumDUE (not booked yet; its job may already wait in Dispatch Needs scheduling), SCHEDULED (the job has a date), COMPLETED, SKIPPED (cancelled or expired). One of DUE, SCHEDULED, COMPLETED, SKIPPED.
visits[].jobIdstring or null
visits[].generatedAtstring (date-time) or null
visits[].jobobject or null
visits[].job.idstring
visits[].job.identifierstring
visits[].job.statusstring
visits[].job.scheduledDatestring or nullNull while the visit has no date.
visits[].job.completedAtstring (date-time) or null
billingsarray of object
billings[].idstring
billings[].periodStartstring
billings[].periodEndstring
billings[].amountCentsintegerInteger cents.
billings[].invoiceIdstring or null
billings[].createdAtstring (date-time)
billings[].invoiceobject or null
billings[].invoice.idstring
billings[].invoice.identifierstring
billings[].invoice.statusstring
billings[].invoice.totalCentsintegerInteger cents.
billings[].invoice.amountPaidCentsintegerInteger cents.

Renew a membership

POST /organizations/{organizationId}/memberships/{membershipId}/renew

Appends the next term now: an ACTIVE membership ending within 90 days gets its next term after the current end date (new included visits; billing continues); an EXPIRED one starts a new term today and its first period is invoiced. 409 for other states or earlier than 90 days before the end. Use GET /memberships?renewalWithinDays=30 for the Renewals view.

Permission: memberships.write (Owner, Admin, Dispatcher, Technician (own jobs)); risk write (OAuth scope servflo.write).

Permissionmemberships.write
Riskwrite, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolmemberships_renew (toolset sales)

Parameters

NameInTypeRequiredDescription
membershipIdpathstringYes

Request body

FieldTypeRequiredDescription
todaystringNoThe business's today (YYYY-MM-DD) for date checks; used only within a day of the organization's own date (its timezone). Default: that date.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships/{membershipId}/renew" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"today":"2026-11-03"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
identifierstringMEM-n
customerIdstring
propertyIdstring or null
planIdstring
planNamestringSnapshot at signup.
priceCentsintegerPrice per billing period, frozen at signup.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
startDatestringSignup date, YYYY-MM-DD.
termNumberintegerCurrent term, 1 = the first.
termStartDatestring
endDatestringLast day of the current term.
autoRenewboolean
nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
cancelledAtstring (date-time) or null
cancelReasonstring or null
pausedUntilstring or null
pausedAtstring (date-time) or null
sourceQuoteIdstring or null
businessUnitIdstring or nullBusiness unit; null = none.
notesstring or null
createdAtstring (date-time)
updatedAtstring (date-time)
monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
visitUsageobjectIncluded visits of the current term.
visitUsage.includedinteger
visitUsage.usedintegerCompleted this term.
visitUsage.remainingintegerDue or scheduled this term.
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
soldByTechnicianIdstring or nullThe technician credited with the sale.
agreementTermsstring or nullThe agreement the customer signed on a technician's phone.
agreementSignedBystring or null
agreementSignedAtstring (date-time) or null
agreementSignaturestring or nullTheir drawn signature (PNG data URL).
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
planobject
plan.idstring
plan.namestring
plan.activeboolean
sourceQuoteobject or null
sourceQuote.idstring
sourceQuote.identifierstring
sourceQuote.statusstring
visitsarray of object
visits[].idstring
visits[].termNumberinteger
visits[].sequenceinteger
visits[].serviceTypeIdstring or null
visits[].serviceNamestring
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].dueMonthstringYYYY-MM
visits[].dueDatestring or nullYYYY-MM-DD for a visit on a week cadence; null for month-based visits.
visits[].statusenumDUE (not booked yet; its job may already wait in Dispatch Needs scheduling), SCHEDULED (the job has a date), COMPLETED, SKIPPED (cancelled or expired). One of DUE, SCHEDULED, COMPLETED, SKIPPED.
visits[].jobIdstring or null
visits[].generatedAtstring (date-time) or null
visits[].jobobject or null
visits[].job.idstring
visits[].job.identifierstring
visits[].job.statusstring
visits[].job.scheduledDatestring or nullNull while the visit has no date.
visits[].job.completedAtstring (date-time) or null
billingsarray of object
billings[].idstring
billings[].periodStartstring
billings[].periodEndstring
billings[].amountCentsintegerInteger cents.
billings[].invoiceIdstring or null
billings[].createdAtstring (date-time)
billings[].invoiceobject or null
billings[].invoice.idstring
billings[].invoice.identifierstring
billings[].invoice.statusstring
billings[].invoice.totalCentsintegerInteger cents.
billings[].invoice.amountPaidCentsintegerInteger cents.

Cancel a membership

POST /organizations/{organizationId}/memberships/{membershipId}/cancel

DESTRUCTIVE for the customer's service: cancels with a reason, stops billing, marks every future DUE visit SKIPPED and cancels its unscheduled job. MONEY: finalInvoiceCents > 0 raises a final DRAFT invoice (e.g. an early-cancellation fee). Invoices already issued are untouched. Only ACTIVE, PAUSED or PENDING memberships (409).

Permissionmemberships.cancel (Owner, Admin)
Risksensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolmemberships_cancel (toolset sales)
ApprovalOver MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in ServFlo). See Approvals.

Parameters

NameInTypeRequiredDescription
membershipIdpathstringYes

Request body

FieldTypeRequiredDescription
reasonstringYesWhy the customer cancelled. Up to 2000 characters.
finalInvoiceCentsinteger or nullNoOptional final invoice amount in cents; 0 or omitted for none. 0–100000000.
todaystringNoThe business's today (YYYY-MM-DD) for date checks; used only within a day of the organization's own date (its timezone). Default: that date.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships/{membershipId}/cancel" \
  -H "Authorization: Bearer $SERVFLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"string"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
identifierstringMEM-n
customerIdstring
propertyIdstring or null
planIdstring
planNamestringSnapshot at signup.
priceCentsintegerPrice per billing period, frozen at signup.
billingFrequencyenumHow often the plan bills: WEEKLY (every 7 days), BIWEEKLY (every 2 weeks), EVERY_4_WEEKS (every 28 days), MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, or ONE_TIME (once per term, at signup or renewal). Week-based periods run in days from the term's first day; the last one is clipped to the term and prorated by days. One of WEEKLY, BIWEEKLY, EVERY_4_WEEKS, MONTHLY, QUARTERLY, SEMI_ANNUAL, ANNUAL, ONE_TIME.
termMonthsinteger
serviceDiscountPercentnumber
materialDiscountPercentnumber
priorityboolean
taxableboolean
statusenumACTIVE (billing and visits run), PENDING (not started), PAUSED (nothing runs until pausedUntil or reinstated), CANCELLED, EXPIRED (term ended without renewal). One of ACTIVE, PENDING, PAUSED, CANCELLED, EXPIRED.
startDatestringSignup date, YYYY-MM-DD.
termNumberintegerCurrent term, 1 = the first.
termStartDatestring
endDatestringLast day of the current term.
autoRenewboolean
nextBillingDatestring or nullStart of the next period to bill; null when nothing more is due in the committed terms.
cancelledAtstring (date-time) or null
cancelReasonstring or null
pausedUntilstring or null
pausedAtstring (date-time) or null
sourceQuoteIdstring or null
businessUnitIdstring or nullBusiness unit; null = none.
notesstring or null
createdAtstring (date-time)
updatedAtstring (date-time)
monthlyRecurringCentsintegerThe price normalised to a month (MRR contribution).
visitUsageobjectIncluded visits of the current term.
visitUsage.includedinteger
visitUsage.usedintegerCompleted this term.
visitUsage.remainingintegerDue or scheduled this term.
includedVisitsarray of object
includedVisits[].serviceTypeIdstring
includedVisits[].countinteger
includedVisits[].monthsarray of integer or null
includedVisits[].spacingMonthsinteger or null
includedVisits[].everyWeeksinteger or null
includedVisits[].weekdayinteger or null
soldByTechnicianIdstring or nullThe technician credited with the sale.
agreementTermsstring or nullThe agreement the customer signed on a technician's phone.
agreementSignedBystring or null
agreementSignedAtstring (date-time) or null
agreementSignaturestring or nullTheir drawn signature (PNG data URL).
customerobject
customer.idstring
customer.namestring
customer.emailstring or null
customer.phonestring or null
propertyobject or null
property.idstring
property.namestring or null
property.addressstring or null
property.citystring or null
planobject
plan.idstring
plan.namestring
plan.activeboolean
sourceQuoteobject or null
sourceQuote.idstring
sourceQuote.identifierstring
sourceQuote.statusstring
visitsarray of object
visits[].idstring
visits[].termNumberinteger
visits[].sequenceinteger
visits[].serviceTypeIdstring or null
visits[].serviceNamestring
visits[].serviceTypeobject or null
visits[].serviceType.idstring
visits[].serviceType.namestring
visits[].serviceType.colorstring
visits[].dueMonthstringYYYY-MM
visits[].dueDatestring or nullYYYY-MM-DD for a visit on a week cadence; null for month-based visits.
visits[].statusenumDUE (not booked yet; its job may already wait in Dispatch Needs scheduling), SCHEDULED (the job has a date), COMPLETED, SKIPPED (cancelled or expired). One of DUE, SCHEDULED, COMPLETED, SKIPPED.
visits[].jobIdstring or null
visits[].generatedAtstring (date-time) or null
visits[].jobobject or null
visits[].job.idstring
visits[].job.identifierstring
visits[].job.statusstring
visits[].job.scheduledDatestring or nullNull while the visit has no date.
visits[].job.completedAtstring (date-time) or null
billingsarray of object
billings[].idstring
billings[].periodStartstring
billings[].periodEndstring
billings[].amountCentsintegerInteger cents.
billings[].invoiceIdstring or null
billings[].createdAtstring (date-time)
billings[].invoiceobject or null
billings[].invoice.idstring
billings[].invoice.identifierstring
billings[].invoice.statusstring
billings[].invoice.totalCentsintegerInteger cents.
billings[].invoice.amountPaidCentsintegerInteger cents.

Run the membership scheduler now

POST /organizations/{organizationId}/memberships/tick

Money: runs the membership scheduler for this organization now (it also runs hourly): invoices billing periods that are due (once per period, never twice), turns member visits whose window opened into unscheduled jobs, renews or expires memberships at their end date and resumes ended pauses. Idempotent: running it again changes nothing until something falls due.

Permissionmemberships.plans.manage (Owner, Admin)
Risksensitive, OAuth scope servflo.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolmemberships_runTick (toolset sales)
ApprovalOver MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in ServFlo). See Approvals.

Example

curl -X POST "https://app.servflo.ai/api/organizations/$ORGANIZATION_ID/memberships/tick" \
  -H "Authorization: Bearer $SERVFLO_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
todaystringThe UTC day the run used.
processedinteger
billedintegerInvoices created (one per billing period, never twice).
invoiceIdsarray of string
visitsGeneratedintegerMember visits turned into unscheduled jobs.
renewedinteger
expiredinteger
resumedintegerPaused memberships whose pause ended.
failedinteger

On this page