curl --request PATCH \
--url https://api.1club.ai/v1/platform/plans/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"clubId": 123,
"planCategoryId": 123,
"revenueAccountId": 123,
"price": 1,
"signupFee": 1,
"customPeriod": 2,
"isActive": true,
"maxUses": 1,
"validityPeriod": 2,
"autoRenews": true,
"renewalDaysInAdvance": 30,
"requirePaymentUpfront": true,
"sports": [
"<string>"
],
"features": [
"<string>"
],
"validFor": {
"scopes": [],
"classTypes": [
123
],
"areaTypes": [
123
],
"instructorTypes": [
123
]
}
}
'import requests
url = "https://api.1club.ai/v1/platform/plans/{id}"
payload = {
"name": "<string>",
"description": "<string>",
"clubId": 123,
"planCategoryId": 123,
"revenueAccountId": 123,
"price": 1,
"signupFee": 1,
"customPeriod": 2,
"isActive": True,
"maxUses": 1,
"validityPeriod": 2,
"autoRenews": True,
"renewalDaysInAdvance": 30,
"requirePaymentUpfront": True,
"sports": ["<string>"],
"features": ["<string>"],
"validFor": {
"scopes": [],
"classTypes": [123],
"areaTypes": [123],
"instructorTypes": [123]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
description: '<string>',
clubId: 123,
planCategoryId: 123,
revenueAccountId: 123,
price: 1,
signupFee: 1,
customPeriod: 2,
isActive: true,
maxUses: 1,
validityPeriod: 2,
autoRenews: true,
renewalDaysInAdvance: 30,
requirePaymentUpfront: true,
sports: ['<string>'],
features: ['<string>'],
validFor: {scopes: [], classTypes: [123], areaTypes: [123], instructorTypes: [123]}
})
};
fetch('https://api.1club.ai/v1/platform/plans/{id}', 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.1club.ai/v1/platform/plans/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'description' => '<string>',
'clubId' => 123,
'planCategoryId' => 123,
'revenueAccountId' => 123,
'price' => 1,
'signupFee' => 1,
'customPeriod' => 2,
'isActive' => true,
'maxUses' => 1,
'validityPeriod' => 2,
'autoRenews' => true,
'renewalDaysInAdvance' => 30,
'requirePaymentUpfront' => true,
'sports' => [
'<string>'
],
'features' => [
'<string>'
],
'validFor' => [
'scopes' => [
],
'classTypes' => [
123
],
'areaTypes' => [
123
],
'instructorTypes' => [
123
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.1club.ai/v1/platform/plans/{id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"clubId\": 123,\n \"planCategoryId\": 123,\n \"revenueAccountId\": 123,\n \"price\": 1,\n \"signupFee\": 1,\n \"customPeriod\": 2,\n \"isActive\": true,\n \"maxUses\": 1,\n \"validityPeriod\": 2,\n \"autoRenews\": true,\n \"renewalDaysInAdvance\": 30,\n \"requirePaymentUpfront\": true,\n \"sports\": [\n \"<string>\"\n ],\n \"features\": [\n \"<string>\"\n ],\n \"validFor\": {\n \"scopes\": [],\n \"classTypes\": [\n 123\n ],\n \"areaTypes\": [\n 123\n ],\n \"instructorTypes\": [\n 123\n ]\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.patch("https://api.1club.ai/v1/platform/plans/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"clubId\": 123,\n \"planCategoryId\": 123,\n \"revenueAccountId\": 123,\n \"price\": 1,\n \"signupFee\": 1,\n \"customPeriod\": 2,\n \"isActive\": true,\n \"maxUses\": 1,\n \"validityPeriod\": 2,\n \"autoRenews\": true,\n \"renewalDaysInAdvance\": 30,\n \"requirePaymentUpfront\": true,\n \"sports\": [\n \"<string>\"\n ],\n \"features\": [\n \"<string>\"\n ],\n \"validFor\": {\n \"scopes\": [],\n \"classTypes\": [\n 123\n ],\n \"areaTypes\": [\n 123\n ],\n \"instructorTypes\": [\n 123\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.1club.ai/v1/platform/plans/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"clubId\": 123,\n \"planCategoryId\": 123,\n \"revenueAccountId\": 123,\n \"price\": 1,\n \"signupFee\": 1,\n \"customPeriod\": 2,\n \"isActive\": true,\n \"maxUses\": 1,\n \"validityPeriod\": 2,\n \"autoRenews\": true,\n \"renewalDaysInAdvance\": 30,\n \"requirePaymentUpfront\": true,\n \"sports\": [\n \"<string>\"\n ],\n \"features\": [\n \"<string>\"\n ],\n \"validFor\": {\n \"scopes\": [],\n \"classTypes\": [\n 123\n ],\n \"areaTypes\": [\n 123\n ],\n \"instructorTypes\": [\n 123\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"planId": 123,
"name": "<string>",
"description": "<string>",
"clubId": 123,
"seasonId": 123,
"planCategoryId": 123,
"revenueAccountId": 123,
"price": 123,
"signupFee": 123,
"billingFrequency": "<string>",
"isActive": true,
"maxUses": 123,
"sessionUnit": "<string>",
"validityPeriod": 123,
"autoRenews": true,
"renewalDaysInAdvance": 123,
"requirePaymentUpfront": true,
"customPeriod": 123,
"customPeriodUnit": "<string>",
"features": [
"<string>"
],
"visibility": "Private",
"validFor": {},
"sports": [
"<string>"
]
}{
"error": "<string>",
"code": "<string>",
"details": {}
}Update a membership plan
Updates a membership plan. Send only what changes; an omitted field is left alone.
A season plan can be reached here even though GET /v1/platform/plans never lists one, because an id resolves by GET /v1/platform/plans/. Those carry rules an ordinary plan does not: a season plan must bill one_time, belong to the season’s own club, and count sessions in hours. An edit that would break one is refused with a 400 naming the rule (SEASON_PLAN_BILLING_FREQUENCY, SEASON_PLAN_CLUB_MISMATCH, SEASON_PLAN_SESSION_UNIT, …) rather than saved - a mis-set season plan does not error later, it sells a season pass with the wrong renewal behaviour or at the wrong venue. Renaming one, or retiring it with isActive, is unaffected.
curl --request PATCH \
--url https://api.1club.ai/v1/platform/plans/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"clubId": 123,
"planCategoryId": 123,
"revenueAccountId": 123,
"price": 1,
"signupFee": 1,
"customPeriod": 2,
"isActive": true,
"maxUses": 1,
"validityPeriod": 2,
"autoRenews": true,
"renewalDaysInAdvance": 30,
"requirePaymentUpfront": true,
"sports": [
"<string>"
],
"features": [
"<string>"
],
"validFor": {
"scopes": [],
"classTypes": [
123
],
"areaTypes": [
123
],
"instructorTypes": [
123
]
}
}
'import requests
url = "https://api.1club.ai/v1/platform/plans/{id}"
payload = {
"name": "<string>",
"description": "<string>",
"clubId": 123,
"planCategoryId": 123,
"revenueAccountId": 123,
"price": 1,
"signupFee": 1,
"customPeriod": 2,
"isActive": True,
"maxUses": 1,
"validityPeriod": 2,
"autoRenews": True,
"renewalDaysInAdvance": 30,
"requirePaymentUpfront": True,
"sports": ["<string>"],
"features": ["<string>"],
"validFor": {
"scopes": [],
"classTypes": [123],
"areaTypes": [123],
"instructorTypes": [123]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
description: '<string>',
clubId: 123,
planCategoryId: 123,
revenueAccountId: 123,
price: 1,
signupFee: 1,
customPeriod: 2,
isActive: true,
maxUses: 1,
validityPeriod: 2,
autoRenews: true,
renewalDaysInAdvance: 30,
requirePaymentUpfront: true,
sports: ['<string>'],
features: ['<string>'],
validFor: {scopes: [], classTypes: [123], areaTypes: [123], instructorTypes: [123]}
})
};
fetch('https://api.1club.ai/v1/platform/plans/{id}', 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.1club.ai/v1/platform/plans/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'description' => '<string>',
'clubId' => 123,
'planCategoryId' => 123,
'revenueAccountId' => 123,
'price' => 1,
'signupFee' => 1,
'customPeriod' => 2,
'isActive' => true,
'maxUses' => 1,
'validityPeriod' => 2,
'autoRenews' => true,
'renewalDaysInAdvance' => 30,
'requirePaymentUpfront' => true,
'sports' => [
'<string>'
],
'features' => [
'<string>'
],
'validFor' => [
'scopes' => [
],
'classTypes' => [
123
],
'areaTypes' => [
123
],
'instructorTypes' => [
123
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.1club.ai/v1/platform/plans/{id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"clubId\": 123,\n \"planCategoryId\": 123,\n \"revenueAccountId\": 123,\n \"price\": 1,\n \"signupFee\": 1,\n \"customPeriod\": 2,\n \"isActive\": true,\n \"maxUses\": 1,\n \"validityPeriod\": 2,\n \"autoRenews\": true,\n \"renewalDaysInAdvance\": 30,\n \"requirePaymentUpfront\": true,\n \"sports\": [\n \"<string>\"\n ],\n \"features\": [\n \"<string>\"\n ],\n \"validFor\": {\n \"scopes\": [],\n \"classTypes\": [\n 123\n ],\n \"areaTypes\": [\n 123\n ],\n \"instructorTypes\": [\n 123\n ]\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.patch("https://api.1club.ai/v1/platform/plans/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"clubId\": 123,\n \"planCategoryId\": 123,\n \"revenueAccountId\": 123,\n \"price\": 1,\n \"signupFee\": 1,\n \"customPeriod\": 2,\n \"isActive\": true,\n \"maxUses\": 1,\n \"validityPeriod\": 2,\n \"autoRenews\": true,\n \"renewalDaysInAdvance\": 30,\n \"requirePaymentUpfront\": true,\n \"sports\": [\n \"<string>\"\n ],\n \"features\": [\n \"<string>\"\n ],\n \"validFor\": {\n \"scopes\": [],\n \"classTypes\": [\n 123\n ],\n \"areaTypes\": [\n 123\n ],\n \"instructorTypes\": [\n 123\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.1club.ai/v1/platform/plans/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"clubId\": 123,\n \"planCategoryId\": 123,\n \"revenueAccountId\": 123,\n \"price\": 1,\n \"signupFee\": 1,\n \"customPeriod\": 2,\n \"isActive\": true,\n \"maxUses\": 1,\n \"validityPeriod\": 2,\n \"autoRenews\": true,\n \"renewalDaysInAdvance\": 30,\n \"requirePaymentUpfront\": true,\n \"sports\": [\n \"<string>\"\n ],\n \"features\": [\n \"<string>\"\n ],\n \"validFor\": {\n \"scopes\": [],\n \"classTypes\": [\n 123\n ],\n \"areaTypes\": [\n 123\n ],\n \"instructorTypes\": [\n 123\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"planId": 123,
"name": "<string>",
"description": "<string>",
"clubId": 123,
"seasonId": 123,
"planCategoryId": 123,
"revenueAccountId": 123,
"price": 123,
"signupFee": 123,
"billingFrequency": "<string>",
"isActive": true,
"maxUses": 123,
"sessionUnit": "<string>",
"validityPeriod": 123,
"autoRenews": true,
"renewalDaysInAdvance": 123,
"requirePaymentUpfront": true,
"customPeriod": 123,
"customPeriodUnit": "<string>",
"features": [
"<string>"
],
"visibility": "Private",
"validFor": {},
"sports": [
"<string>"
]
}{
"error": "<string>",
"code": "<string>",
"details": {}
}Authorizations
Organization-scoped bearer credential: a customer API key (1club_sk_live_...) or an MCP OAuth access token.
Path Parameters
Body
1205000Category the plan is grouped under on price lists, from GET /v1/platform/plan-categories. null takes it out of every category.
Ledger account a sale of this plan posts to, from GET /v1/platform/revenue-accounts. Leave it out and the sale falls to the organization's default account, resolved at the time of the sale - so omitting this is a choice, not a gap. null clears it back to that.
x >= 0x >= 0one_time, weekly, monthly, quarterly, annually, custom x >= 1days, weeks, months x >= 0booking, hour x >= 10 <= x <= 6050100Private, Member_only, Public Show child attributes
Show child attributes
Response
Plan updated
A membership plan. It carries its own price, joining fee, billing frequency and session allowance, so creating a membership only has to name the plan and the customer.
Club the plan is limited to; null when organization-wide.
Set when the plan sells a season, and the marker that it is not for sale through this API: a season pass costs the sum of the slots the buyer picks, so the plan's own price is 0 and a membership created against it would put a member on a large contract for nothing. GET /v1/platform/plans excludes these; get-by-id resolves one so a membership already sold against it can be explained. Check it before treating any plan as sellable.
Category the plan is grouped under on price lists; null when ungrouped.
Ledger account a sale posts to; null means the organization's default account is used at the time of the sale.
Charged each billing period.
Charged once when the membership starts, on top of the price.
False for a retired plan that is no longer sold.
Session allowance a membership gets; null when unlimited.
What a use is counted in - a booking or an hour.
Days the membership stays valid, when time-limited.
Whether a membership on this plan renews by default.
Private, Member_only, Public Booking resource scopes and optional type filters covered by the plan.
Was this page helpful?