curl --request PUT \
--url https://api.decodahealth.com/inventory/memberships/bulk \
--header 'API-KEY: <api-key>' \
--header 'Content-Type: application/json' \
--header 'TENANT: <tenant>' \
--data '
[
{
"id": "<string>",
"name": "<string>",
"description": "<string>",
"price": 123,
"automaticallySendReceipts": true
}
]
'import requests
url = "https://api.decodahealth.com/inventory/memberships/bulk"
payload = [
{
"id": "<string>",
"name": "<string>",
"description": "<string>",
"price": 123,
"automaticallySendReceipts": True
}
]
headers = {
"TENANT": "<tenant>",
"API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {TENANT: '<tenant>', 'API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify([
{
id: '<string>',
name: '<string>',
description: '<string>',
price: 123,
automaticallySendReceipts: true
}
])
};
fetch('https://api.decodahealth.com/inventory/memberships/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.decodahealth.com/inventory/memberships/bulk",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
[
'id' => '<string>',
'name' => '<string>',
'description' => '<string>',
'price' => 123,
'automaticallySendReceipts' => true
]
]),
CURLOPT_HTTPHEADER => [
"API-KEY: <api-key>",
"Content-Type: application/json",
"TENANT: <tenant>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.decodahealth.com/inventory/memberships/bulk"
payload := strings.NewReader("[\n {\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"price\": 123,\n \"automaticallySendReceipts\": true\n }\n]")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("TENANT", "<tenant>")
req.Header.Add("API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.decodahealth.com/inventory/memberships/bulk")
.header("TENANT", "<tenant>")
.header("API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("[\n {\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"price\": 123,\n \"automaticallySendReceipts\": true\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.decodahealth.com/inventory/memberships/bulk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["TENANT"] = '<tenant>'
request["API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "[\n {\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"price\": 123,\n \"automaticallySendReceipts\": true\n }\n]"
response = http.request(request)
puts response.read_body[
{
"name": "<string>",
"price": 123,
"id": "<string>",
"externalId": "<string>",
"description": "<string>",
"patientCreditAmount": 0,
"patientCreditFrequency": "MONTHLY",
"patientCreditExpiryDays": 123,
"maxRenewals": 0,
"autoRenew": true,
"setupFee": 0,
"freezeFee": 0,
"applySurcharge": false,
"automaticallySendReceipts": false,
"minimumBillingCycles": 0,
"earlyCancellationFee": 0,
"nonRefundableAmount": 0,
"billingFrequency": "MONTHLY",
"benefitType": "PREPAYMENT_DISCOUNT",
"recognitionMode": "CASH",
"expectedUsesPerCycle": 1,
"textColor": "<string>",
"isArchived": false,
"commissionable": true,
"hiddenInPatientPortal": false,
"hiddenInOnlineShop": true,
"ruleSetId": "<string>",
"formId": "<string>",
"form": {
"name": "<string>",
"pathName": "<string>",
"isArchived": true,
"defaultSendingText": "<string>"
},
"merchantAccountId": "<string>",
"depositStrategy": "MEMBERSHIP_ACCOUNT",
"shopBillingStart": "ENROLLMENT_DAY",
"feeSchedule": [
{
"cycleNumber": 2,
"price": 1,
"id": "<string>",
"membershipId": ""
}
],
"tags": [
{
"id": "<string>",
"name": "<string>",
"color": "<string>"
}
],
"discountTemplates": [
{
"id": "<string>",
"createdByItemId": "<string>",
"discountChoiceId": "<string>",
"itemId": "<string>",
"category": "<string>",
"itemType": "ITEM",
"type": "GLOBAL",
"percentage": 123,
"amount": 123,
"quantity": 123,
"expiryTimeDays": 123,
"renewalCycleInterval": 2,
"isStackable": true,
"isPrepayment": false,
"group": "<string>",
"isArchived": false,
"createdDate": "2023-11-07T05:31:56Z",
"updatedDate": "2023-11-07T05:31:56Z"
}
],
"memberCount": 0,
"totalRevenue": 0,
"accountingBasis": "CASH"
}
]{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Bulk Update Memberships
Bulk update memberships (name, description, price).
curl --request PUT \
--url https://api.decodahealth.com/inventory/memberships/bulk \
--header 'API-KEY: <api-key>' \
--header 'Content-Type: application/json' \
--header 'TENANT: <tenant>' \
--data '
[
{
"id": "<string>",
"name": "<string>",
"description": "<string>",
"price": 123,
"automaticallySendReceipts": true
}
]
'import requests
url = "https://api.decodahealth.com/inventory/memberships/bulk"
payload = [
{
"id": "<string>",
"name": "<string>",
"description": "<string>",
"price": 123,
"automaticallySendReceipts": True
}
]
headers = {
"TENANT": "<tenant>",
"API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {TENANT: '<tenant>', 'API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify([
{
id: '<string>',
name: '<string>',
description: '<string>',
price: 123,
automaticallySendReceipts: true
}
])
};
fetch('https://api.decodahealth.com/inventory/memberships/bulk', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.decodahealth.com/inventory/memberships/bulk",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
[
'id' => '<string>',
'name' => '<string>',
'description' => '<string>',
'price' => 123,
'automaticallySendReceipts' => true
]
]),
CURLOPT_HTTPHEADER => [
"API-KEY: <api-key>",
"Content-Type: application/json",
"TENANT: <tenant>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.decodahealth.com/inventory/memberships/bulk"
payload := strings.NewReader("[\n {\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"price\": 123,\n \"automaticallySendReceipts\": true\n }\n]")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("TENANT", "<tenant>")
req.Header.Add("API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.decodahealth.com/inventory/memberships/bulk")
.header("TENANT", "<tenant>")
.header("API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("[\n {\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"price\": 123,\n \"automaticallySendReceipts\": true\n }\n]")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.decodahealth.com/inventory/memberships/bulk")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["TENANT"] = '<tenant>'
request["API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "[\n {\n \"id\": \"<string>\",\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"price\": 123,\n \"automaticallySendReceipts\": true\n }\n]"
response = http.request(request)
puts response.read_body[
{
"name": "<string>",
"price": 123,
"id": "<string>",
"externalId": "<string>",
"description": "<string>",
"patientCreditAmount": 0,
"patientCreditFrequency": "MONTHLY",
"patientCreditExpiryDays": 123,
"maxRenewals": 0,
"autoRenew": true,
"setupFee": 0,
"freezeFee": 0,
"applySurcharge": false,
"automaticallySendReceipts": false,
"minimumBillingCycles": 0,
"earlyCancellationFee": 0,
"nonRefundableAmount": 0,
"billingFrequency": "MONTHLY",
"benefitType": "PREPAYMENT_DISCOUNT",
"recognitionMode": "CASH",
"expectedUsesPerCycle": 1,
"textColor": "<string>",
"isArchived": false,
"commissionable": true,
"hiddenInPatientPortal": false,
"hiddenInOnlineShop": true,
"ruleSetId": "<string>",
"formId": "<string>",
"form": {
"name": "<string>",
"pathName": "<string>",
"isArchived": true,
"defaultSendingText": "<string>"
},
"merchantAccountId": "<string>",
"depositStrategy": "MEMBERSHIP_ACCOUNT",
"shopBillingStart": "ENROLLMENT_DAY",
"feeSchedule": [
{
"cycleNumber": 2,
"price": 1,
"id": "<string>",
"membershipId": ""
}
],
"tags": [
{
"id": "<string>",
"name": "<string>",
"color": "<string>"
}
],
"discountTemplates": [
{
"id": "<string>",
"createdByItemId": "<string>",
"discountChoiceId": "<string>",
"itemId": "<string>",
"category": "<string>",
"itemType": "ITEM",
"type": "GLOBAL",
"percentage": 123,
"amount": 123,
"quantity": 123,
"expiryTimeDays": 123,
"renewalCycleInterval": 2,
"isStackable": true,
"isPrepayment": false,
"group": "<string>",
"isArchived": false,
"createdDate": "2023-11-07T05:31:56Z",
"updatedDate": "2023-11-07T05:31:56Z"
}
],
"memberCount": 0,
"totalRevenue": 0,
"accountingBasis": "CASH"
}
]{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Headers
The tenant you are making this request on behalf of
Your api key
Body
Response
Successful Response
Name of the membership
Price of the membership in cents
Unique identifier for the membership
External system identifier for the membership
Optional description of the membership
Amount of patient credit in cents
Frequency of patient credit
DAILY, WEEKLY, BIWEEKLY, MONTHLY, EVERY_FOUR_WEEKS, EVERY_SIX_WEEKS, EVERY_TEN_WEEKS, EVERY_TWELVE_WEEKS, QUARTERLY, EVERY_FOUR_MONTHS, SEMI_ANNUALLY, YEARLY Days until patient credit expires
Maximum number of renewals (null means unlimited)
Whether the membership auto-renews
Setup fee for the membership in cents
Fee to freeze the membership in cents
Whether to apply credit card surcharge to membership charges
Whether recurring/renewal charges for this membership automatically send an itemized receipt to the patient. Still gated by the clinic's automatic-receipt setting.
Minimum number of billing cycles required
Fee in cents charged when cancelling before minimum_billing_cycles is reached
Cents of a membership charge that can never be refunded. 0 means refunds are uncapped. Capped at refund time by what the charge actually billed, so an amount larger than the charge returns nothing rather than reaching further.
x >= 0Billing frequency for the membership
DAILY, WEEKLY, BIWEEKLY, MONTHLY, EVERY_FOUR_WEEKS, EVERY_SIX_WEEKS, EVERY_TEN_WEEKS, EVERY_TWELVE_WEEKS, QUARTERLY, EVERY_FOUR_MONTHS, SEMI_ANNUALLY, YEARLY What the cycle billing creates: PREPAYMENT_DISCOUNT, PATIENT_CREDIT_GRANT, or NONE
PREPAYMENT_DISCOUNT, PATIENT_CREDIT_GRANT, NONE How cycle revenue is recognized: PER_REDEMPTION, STRAIGHT_LINE, CASH, or AS_CONSUMED. Defaults to CASH (whole cycle recognized at billing); other modes are an explicit opt-in.
PER_REDEMPTION, STRAIGHT_LINE, CASH, AS_CONSUMED PER_REDEMPTION only: how many redemptions a typical member makes per cycle, used as the recognition divisor. Leave blank when the redemption limit (quantity) already reflects expected usage; set it when the limit is a high cap (e.g. 100) rather than a typical count.
x > 0Text color for the membership
Whether the membership is archived
Whether this membership is eligible for commissions
Whether this membership is hidden from the patient portal
Whether this membership is hidden from the online shop
ID of the rule set for the membership
ID of the form associated with this membership
Form associated with this membership
Show child attributes
Show child attributes
Bank account (merchant account) that membership deposits go to
How to pick the merchant account at billing time. MEMBERSHIP_ACCOUNT always routes to merchant_account_id. LOCATION_ACCOUNT routes to the sold-at location's merchant account (falling back to merchant_account_id when the location has none).
MEMBERSHIP_ACCOUNT, LOCATION_ACCOUNT When billing starts for patient self-enrollment and the default for staff enrollment.
ENROLLMENT_DAY, FIRST_OF_MONTH, FIFTEENTH_OF_MONTH Cycle-specific price overrides
Show child attributes
Show child attributes
Tags assigned to this membership
Show child attributes
Show child attributes
Discount templates for the membership
Show child attributes
Show child attributes
Number of active members
Total revenue from this membership, in cents
Basis the total_revenue reflects: ACCRUAL = recognized revenue (earned as benefits are delivered), CASH = billed revenue (collected at cycle billing). Set only on responses that compute total_revenue; null otherwise. Lets the FE label what it shows.
CASH, ACCRUAL 
