API reference
Pricing
Pricing endpoints.
| Method | Path | Summary |
|---|---|---|
GET | /v1/account/groups/{groupId}/price-book | A location's current prices, its unpublished changes, and what blocks publishing |
POST | /v1/account/groups/{groupId}/price-book/approve | Approve a location's price changes: they are published, on their date if one was asked |
POST | /v1/account/groups/{groupId}/price-book/cancel-scheduled | Cancel a scheduled price change before its date: it becomes the draft again |
PUT | /v1/account/groups/{groupId}/price-book/draft | Save a location's unpublished price changes |
DELETE | /v1/account/groups/{groupId}/price-book/draft | Discard a location's unpublished price changes |
POST | /v1/account/groups/{groupId}/price-book/publish | Publish a location's price changes, now or on a date. Sent for approval instead when your changes need it |
POST | /v1/account/groups/{groupId}/price-book/return | Send price changes waiting for approval back to draft, with a note saying why |
GET | /v1/account/groups/{groupId}/price-book/versions | A location's published price books, newest first |
POST | /v1/account/groups/{groupId}/price-book/versions/{version}/rollback | Publish a copy of an earlier price book as the newest version (sent for approval when your changes need it) |
POST | /v1/account/groups/{groupId}/price-book/withdraw | Take back price changes you sent for approval, to change them |
GET | /v1/account/price-matrix | Every location you can see against every service: current prices and drafts, or the prices in effect at a past moment |
POST | /v1/account/price-matrix/approve | Approve the price changes waiting at several locations |
POST | /v1/account/price-matrix/discard | Discard the unpublished price changes of several locations |
PUT | /v1/account/price-matrix/drafts | Save unpublished price changes for several locations at once |
POST | /v1/account/price-matrix/publish | Publish the price changes of several locations with one note, now or on a date (sent for approval when your changes need it) |
GET | /v1/account/pricing/catalog | The services, option sets and options you sell, and the pricing settings |
POST | /v1/account/pricing/option-sets | Add an option set: a list of choices that changes a price |
PATCH | /v1/account/pricing/option-sets/{optionSetId} | Rename, reorder or archive an option set |
POST | /v1/account/pricing/option-sets/{optionSetId}/options | Add an option to a set: the account's, or a location's own |
PATCH | /v1/account/pricing/options/{optionId} | Rename, reorder or archive an option |
POST | /v1/account/pricing/services | Add a service to the account's catalog, or a location's own |
PATCH | /v1/account/pricing/services/{serviceId} | Change or archive a service. Every location that offers it is recomputed |
GET | /v1/account/pricing/specials | Your specials: drafts, those waiting for approval, and approved ones |
POST | /v1/account/pricing/specials | Add a special. It is approved at once, or sent for approval when your changes need it, or kept as a draft |
PATCH | /v1/account/pricing/specials/{specialId} | Change a special. Changing an approved one sends it back for approval when your changes need it |
DELETE | /v1/account/pricing/specials/{specialId} | Delete a draft special (approved ones are ended, never deleted) |
POST | /v1/account/pricing/specials/{specialId}/approve | Approve a special waiting for approval |
POST | /v1/account/pricing/specials/{specialId}/end | End an approved special now: the agent stops mentioning it |
POST | /v1/account/pricing/specials/{specialId}/return | Send a special waiting for approval back to draft, with a note saying why |
POST | /v1/account/pricing/specials/{specialId}/submit | Send a draft special for approval (approved at once when your changes do not need it) |
POST | /v1/account/pricing/specials/{specialId}/withdraw | Take back a special you sent for approval |
A location's current prices, its unpublished changes, and what blocks publishing#
GET /v1/account/groups/{groupId}/price-book
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
current | any | null | Yes | — |
draft | any | null | Yes | — |
groupId | string (grp_… ID) | Yes | ID (grp_…) |
groupName | string | Yes | — |
issues | array<object> | Yes | — |
issues[].message | string | Yes | — |
issues[].path | string | Yes | — |
scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book" \
-H "Authorization: Bearer $ACCESS_TOKEN"Approve a location's price changes: they are published, on their date if one was asked#
POST /v1/account/groups/{groupId}/price-book/approve
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
outcome | enum | Yes | One of: "published", "scheduled", "pending_approval". |
priceBook | PriceBook | Yes | — |
priceBook.current | any | null | Yes | — |
priceBook.draft | any | null | Yes | — |
priceBook.groupId | string (grp_… ID) | Yes | ID (grp_…) |
priceBook.groupName | string | Yes | — |
priceBook.issues | array<object> | Yes | — |
priceBook.issues[].message | string | Yes | — |
priceBook.issues[].path | string | Yes | — |
priceBook.scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/approve" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "string"
}'Cancel a scheduled price change before its date: it becomes the draft again#
POST /v1/account/groups/{groupId}/price-book/cancel-scheduled
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
current | any | null | Yes | — |
draft | any | null | Yes | — |
groupId | string (grp_… ID) | Yes | ID (grp_…) |
groupName | string | Yes | — |
issues | array<object> | Yes | — |
issues[].message | string | Yes | — |
issues[].path | string | Yes | — |
scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/cancel-scheduled" \
-H "Authorization: Bearer $ACCESS_TOKEN"Save a location's unpublished price changes#
PUT /v1/account/groups/{groupId}/price-book/draft
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
content | object | Yes | — |
content.entries | array<object> | No | Default: []. |
content.entries[].cells | array<object> | No | Default: []. |
content.entries[].cells[].confirmedAt | string (date-time) | No | — |
content.entries[].cells[].crm | object | No | — |
content.entries[].cells[].hidden | boolean | No | Default: false. |
content.entries[].cells[].internalNote | string | No | Up to 500 characters. |
content.entries[].cells[].offered | boolean | No | Default: true. |
content.entries[].cells[].options | array<string (sopt_… ID)> | No | Up to 2 items. Default: []. |
content.entries[].cells[].price | object | object | Yes | — |
content.entries[].cells[].wording | string | No | Up to 200 characters. |
content.entries[].offered | boolean | No | Default: true. |
content.entries[].pricedBy | array<string (oset_… ID)> | No | Up to 2 items. Default: []. |
content.entries[].serviceId | string (srv_… ID) | Yes | ID (srv_…) |
expectedHash | string | null | No | Up to 100 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
current | any | null | Yes | — |
draft | any | null | Yes | — |
groupId | string (grp_… ID) | Yes | ID (grp_…) |
groupName | string | Yes | — |
issues | array<object> | Yes | — |
issues[].message | string | Yes | — |
issues[].path | string | Yes | — |
scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X PUT "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/draft" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": {
"entries": []
}
}'Discard a location's unpublished price changes#
DELETE /v1/account/groups/{groupId}/price-book/draft
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
current | any | null | Yes | — |
draft | any | null | Yes | — |
groupId | string (grp_… ID) | Yes | ID (grp_…) |
groupName | string | Yes | — |
issues | array<object> | Yes | — |
issues[].message | string | Yes | — |
issues[].path | string | Yes | — |
scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X DELETE "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/draft" \
-H "Authorization: Bearer $ACCESS_TOKEN"Publish a location's price changes, now or on a date. Sent for approval instead when your changes need it#
POST /v1/account/groups/{groupId}/price-book/publish
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
effectiveFrom | string (date-time) | No | — |
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
outcome | enum | Yes | One of: "published", "scheduled", "pending_approval". |
priceBook | PriceBook | Yes | — |
priceBook.current | any | null | Yes | — |
priceBook.draft | any | null | Yes | — |
priceBook.groupId | string (grp_… ID) | Yes | ID (grp_…) |
priceBook.groupName | string | Yes | — |
priceBook.issues | array<object> | Yes | — |
priceBook.issues[].message | string | Yes | — |
priceBook.issues[].path | string | Yes | — |
priceBook.scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/publish" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"effectiveFrom": "2026-01-15T15:30:00Z",
"note": "string"
}'Send price changes waiting for approval back to draft, with a note saying why#
POST /v1/account/groups/{groupId}/price-book/return
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | Yes | 1–500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
current | any | null | Yes | — |
draft | any | null | Yes | — |
groupId | string (grp_… ID) | Yes | ID (grp_…) |
groupName | string | Yes | — |
issues | array<object> | Yes | — |
issues[].message | string | Yes | — |
issues[].path | string | Yes | — |
scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/return" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "string"
}'A location's published price books, newest first#
GET /v1/account/groups/{groupId}/price-book/versions
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
versions | array<PriceBookVersion> | Yes | — |
versions[].authorId | string | null | Yes | — |
versions[].changeNote | string | null | Yes | — |
versions[].content | object | Yes | — |
versions[].content.entries | array<object> | Yes | Default: []. |
versions[].content.entries[].cells | array<object> | Yes | Default: []. |
versions[].content.entries[].offered | boolean | Yes | Default: true. |
versions[].content.entries[].pricedBy | array<string (oset_… ID)> | Yes | Up to 2 items. Default: []. |
versions[].content.entries[].serviceId | string (srv_… ID) | Yes | ID (srv_…) |
versions[].contentHash | string | Yes | — |
versions[].decidedBy | string | null | Yes | — |
versions[].decisionNote | string | null | Yes | — |
versions[].effectiveFrom | string (date-time) | null | Yes | — |
versions[].publishedAt | string (date-time) | null | Yes | — |
versions[].publishedBy | string | null | Yes | — |
versions[].status | enum | Yes | One of: "draft", "pending_approval", "published". |
versions[].submittedAt | string (date-time) | null | Yes | — |
versions[].submittedBy | string | null | Yes | — |
versions[].updatedAt | string (date-time) | Yes | — |
versions[].version | integer | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/versions" \
-H "Authorization: Bearer $ACCESS_TOKEN"Publish a copy of an earlier price book as the newest version (sent for approval when your changes need it)#
POST /v1/account/groups/{groupId}/price-book/versions/{version}/rollback
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
version | integer | Yes | Minimum 1. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
outcome | enum | Yes | One of: "published", "scheduled", "pending_approval". |
priceBook | PriceBook | Yes | — |
priceBook.current | any | null | Yes | — |
priceBook.draft | any | null | Yes | — |
priceBook.groupId | string (grp_… ID) | Yes | ID (grp_…) |
priceBook.groupName | string | Yes | — |
priceBook.issues | array<object> | Yes | — |
priceBook.issues[].message | string | Yes | — |
priceBook.issues[].path | string | Yes | — |
priceBook.scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/versions/{version}/rollback" \
-H "Authorization: Bearer $ACCESS_TOKEN"Take back price changes you sent for approval, to change them#
POST /v1/account/groups/{groupId}/price-book/withdraw
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | Yes | ID (grp_…) |
Request body
application/json, required.
Type: object
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
current | any | null | Yes | — |
draft | any | null | Yes | — |
groupId | string (grp_… ID) | Yes | ID (grp_…) |
groupName | string | Yes | — |
issues | array<object> | Yes | — |
issues[].message | string | Yes | — |
issues[].path | string | Yes | — |
scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/groups/{groupId}/price-book/withdraw" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Every location you can see against every service: current prices and drafts, or the prices in effect at a past moment#
GET /v1/account/price-matrix
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
at | string (date-time) | No | — |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
catalog | PriceCatalog | Yes | — |
catalog.optionSets | array<object> | Yes | — |
catalog.optionSets[].archived | boolean | Yes | Default: false. |
catalog.optionSets[].id | string (oset_… ID) | Yes | ID (oset_…) |
catalog.optionSets[].name | string | Yes | 1–80 characters. |
catalog.optionSets[].sort | integer | Yes | Between 0 and 100000. Default: 0. |
catalog.options | array<object> | Yes | — |
catalog.options[].archived | boolean | Yes | Default: false. |
catalog.options[].groupId | string (grp_… ID) | null | Yes | — |
catalog.options[].id | string (sopt_… ID) | Yes | ID (sopt_…) |
catalog.options[].name | string | Yes | 1–80 characters. |
catalog.options[].optionSetId | string (oset_… ID) | Yes | ID (oset_…) |
catalog.options[].sort | integer | Yes | Between 0 and 100000. Default: 0. |
catalog.options[].spokenName | string | No | 1–80 characters. |
catalog.options[].synonyms | array<string> | Yes | Up to 20 items. Default: []. |
catalog.services | array<object> | Yes | — |
catalog.services[].archived | boolean | Yes | Default: false. |
catalog.services[].description | string | Yes | Up to 600 characters. Default: "". |
catalog.services[].groupId | string (grp_… ID) | null | Yes | — |
catalog.services[].id | string (srv_… ID) | Yes | ID (srv_…) |
catalog.services[].kind | enum | Yes | One of: "service", "add_on", "fee". Default: "service". |
catalog.services[].name | string | Yes | 1–80 characters. |
catalog.services[].optionSetIds | array<string (oset_… ID)> | Yes | Up to 2 items. Default: []. |
catalog.services[].perPerson | enum | Yes | One of: "single", "second_person". Default: "single". |
catalog.services[].sort | integer | Yes | Between 0 and 100000. Default: 0. |
catalog.services[].spokenName | string | No | 1–80 characters. |
catalog.services[].synonyms | array<string> | Yes | Up to 20 items. Default: []. |
catalog.services[].unit | enum | Yes | One of: "month", "day", "night", "week", "visit", "hour", "one_time". Default: "month". |
catalog.settings | object | Yes | — |
catalog.settings.allowLocationServices | boolean | Yes | Default: true. |
catalog.settings.priceApproval | enum | Yes | One of: "off", "group_managers", "everyone". Default: "off". |
catalog.settings.priceApprovalIncludesCrm | boolean | Yes | Default: false. |
catalog.settings.priceReviewDays | integer | Yes | Between 0 and 3650. Default: 90. |
priceBooks | array<PriceBook> | Yes | — |
priceBooks[].current | any | null | Yes | — |
priceBooks[].draft | any | null | Yes | — |
priceBooks[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
priceBooks[].groupName | string | Yes | — |
priceBooks[].issues | array<object> | Yes | — |
priceBooks[].issues[].message | string | Yes | — |
priceBooks[].issues[].path | string | Yes | — |
priceBooks[].scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/price-matrix" \
-H "Authorization: Bearer $ACCESS_TOKEN"Approve the price changes waiting at several locations#
POST /v1/account/price-matrix/approve
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
groupIds | array<string (grp_… ID)> | Yes | Up to 500 items. |
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
outcome | enum | Yes | One of: "published", "scheduled", "pending_approval". |
priceBooks | array<PriceBook> | Yes | — |
priceBooks[].current | any | null | Yes | — |
priceBooks[].draft | any | null | Yes | — |
priceBooks[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
priceBooks[].groupName | string | Yes | — |
priceBooks[].issues | array<object> | Yes | — |
priceBooks[].issues[].message | string | Yes | — |
priceBooks[].issues[].path | string | Yes | — |
priceBooks[].scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/price-matrix/approve" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"groupIds": [
"grp_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE"
]
}'Discard the unpublished price changes of several locations#
POST /v1/account/price-matrix/discard
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
groupIds | array<string (grp_… ID)> | Yes | Up to 500 items. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
discarded | integer | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/price-matrix/discard" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"groupIds": [
"grp_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE"
]
}'Save unpublished price changes for several locations at once#
PUT /v1/account/price-matrix/drafts
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
drafts | array<object> | Yes | Up to 500 items. |
drafts[].content | object | Yes | — |
drafts[].content.entries | array<object> | No | Default: []. |
drafts[].content.entries[].cells | array<object> | No | Default: []. |
drafts[].content.entries[].offered | boolean | No | Default: true. |
drafts[].content.entries[].pricedBy | array<string (oset_… ID)> | No | Up to 2 items. Default: []. |
drafts[].content.entries[].serviceId | string (srv_… ID) | Yes | ID (srv_…) |
drafts[].expectedHash | string | null | No | Up to 100 characters. |
drafts[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
priceBooks | array<PriceBook> | Yes | — |
priceBooks[].current | any | null | Yes | — |
priceBooks[].draft | any | null | Yes | — |
priceBooks[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
priceBooks[].groupName | string | Yes | — |
priceBooks[].issues | array<object> | Yes | — |
priceBooks[].issues[].message | string | Yes | — |
priceBooks[].issues[].path | string | Yes | — |
priceBooks[].scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X PUT "$ANSWERSTACK_API_URL/v1/account/price-matrix/drafts" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"drafts": [
{
"groupId": "grp_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE",
"content": {
"entries": []
}
}
]
}'Publish the price changes of several locations with one note, now or on a date (sent for approval when your changes need it)#
POST /v1/account/price-matrix/publish
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
effectiveFrom | string (date-time) | No | — |
groupIds | array<string (grp_… ID)> | Yes | Up to 500 items. |
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
outcome | enum | Yes | One of: "published", "scheduled", "pending_approval". |
priceBooks | array<PriceBook> | Yes | — |
priceBooks[].current | any | null | Yes | — |
priceBooks[].draft | any | null | Yes | — |
priceBooks[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
priceBooks[].groupName | string | Yes | — |
priceBooks[].issues | array<object> | Yes | — |
priceBooks[].issues[].message | string | Yes | — |
priceBooks[].issues[].path | string | Yes | — |
priceBooks[].scheduled | any | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/price-matrix/publish" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"groupIds": [
"grp_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE"
]
}'The services, option sets and options you sell, and the pricing settings#
GET /v1/account/pricing/catalog
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
optionSets | array<object> | Yes | — |
optionSets[].archived | boolean | Yes | Default: false. |
optionSets[].id | string (oset_… ID) | Yes | ID (oset_…) |
optionSets[].name | string | Yes | 1–80 characters. |
optionSets[].sort | integer | Yes | Between 0 and 100000. Default: 0. |
options | array<object> | Yes | — |
options[].archived | boolean | Yes | Default: false. |
options[].groupId | string (grp_… ID) | null | Yes | — |
options[].id | string (sopt_… ID) | Yes | ID (sopt_…) |
options[].name | string | Yes | 1–80 characters. |
options[].optionSetId | string (oset_… ID) | Yes | ID (oset_…) |
options[].sort | integer | Yes | Between 0 and 100000. Default: 0. |
options[].spokenName | string | No | 1–80 characters. |
options[].synonyms | array<string> | Yes | Up to 20 items. Default: []. |
services | array<object> | Yes | — |
services[].archived | boolean | Yes | Default: false. |
services[].description | string | Yes | Up to 600 characters. Default: "". |
services[].groupId | string (grp_… ID) | null | Yes | — |
services[].id | string (srv_… ID) | Yes | ID (srv_…) |
services[].kind | enum | Yes | One of: "service", "add_on", "fee". Default: "service". |
services[].name | string | Yes | 1–80 characters. |
services[].optionSetIds | array<string (oset_… ID)> | Yes | Up to 2 items. Default: []. |
services[].perPerson | enum | Yes | One of: "single", "second_person". Default: "single". |
services[].sort | integer | Yes | Between 0 and 100000. Default: 0. |
services[].spokenName | string | No | 1–80 characters. |
services[].synonyms | array<string> | Yes | Up to 20 items. Default: []. |
services[].unit | enum | Yes | One of: "month", "day", "night", "week", "visit", "hour", "one_time". Default: "month". |
settings | object | Yes | — |
settings.allowLocationServices | boolean | Yes | Default: true. |
settings.priceApproval | enum | Yes | One of: "off", "group_managers", "everyone". Default: "off". |
settings.priceApprovalIncludesCrm | boolean | Yes | Default: false. |
settings.priceReviewDays | integer | Yes | Between 0 and 3650. Default: 90. |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/pricing/catalog" \
-H "Authorization: Bearer $ACCESS_TOKEN"Add an option set: a list of choices that changes a price#
POST /v1/account/pricing/option-sets
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | 1–80 characters. |
sort | integer | No | Between 0 and 100000. Default: 0. |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
archived | boolean | Yes | Default: false. |
id | string (oset_… ID) | Yes | ID (oset_…) |
name | string | Yes | 1–80 characters. |
sort | integer | Yes | Between 0 and 100000. Default: 0. |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/option-sets" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "string"
}'Rename, reorder or archive an option set#
PATCH /v1/account/pricing/option-sets/{optionSetId}
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
optionSetId | string (oset_… ID) | Yes | ID (oset_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
archived | boolean | No | — |
name | string | No | 1–80 characters. |
sort | integer | No | Between 0 and 100000. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
optionSet | object | Yes | — |
optionSet.archived | boolean | Yes | Default: false. |
optionSet.id | string (oset_… ID) | Yes | ID (oset_…) |
optionSet.name | string | Yes | 1–80 characters. |
optionSet.sort | integer | Yes | Between 0 and 100000. Default: 0. |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X PATCH "$ANSWERSTACK_API_URL/v1/account/pricing/option-sets/{optionSetId}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"archived": true,
"name": "string",
"sort": 0
}'Add an option to a set: the account's, or a location's own#
POST /v1/account/pricing/option-sets/{optionSetId}/options
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
optionSetId | string (oset_… ID) | Yes | ID (oset_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
groupId | string (grp_… ID) | null | No | — |
name | string | Yes | 1–80 characters. |
sort | integer | No | Between 0 and 100000. Default: 0. |
spokenName | string | No | 1–80 characters. |
synonyms | array<string> | No | Up to 20 items. Default: []. |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
archived | boolean | Yes | Default: false. |
groupId | string (grp_… ID) | null | Yes | — |
id | string (sopt_… ID) | Yes | ID (sopt_…) |
name | string | Yes | 1–80 characters. |
optionSetId | string (oset_… ID) | Yes | ID (oset_…) |
sort | integer | Yes | Between 0 and 100000. Default: 0. |
spokenName | string | No | 1–80 characters. |
synonyms | array<string> | Yes | Up to 20 items. Default: []. |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/option-sets/{optionSetId}/options" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "string"
}'Rename, reorder or archive an option#
PATCH /v1/account/pricing/options/{optionId}
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
optionId | string (sopt_… ID) | Yes | ID (sopt_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
archived | boolean | No | — |
name | string | No | 1–80 characters. |
sort | integer | No | Between 0 and 100000. |
spokenName | string | null | No | 1–80 characters. |
synonyms | array<string> | No | Up to 20 items. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
option | object | Yes | — |
option.archived | boolean | Yes | Default: false. |
option.groupId | string (grp_… ID) | null | Yes | — |
option.id | string (sopt_… ID) | Yes | ID (sopt_…) |
option.name | string | Yes | 1–80 characters. |
option.optionSetId | string (oset_… ID) | Yes | ID (oset_…) |
option.sort | integer | Yes | Between 0 and 100000. Default: 0. |
option.spokenName | string | No | 1–80 characters. |
option.synonyms | array<string> | Yes | Up to 20 items. Default: []. |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X PATCH "$ANSWERSTACK_API_URL/v1/account/pricing/options/{optionId}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"archived": true,
"name": "string",
"sort": 0,
"spokenName": "string",
"synonyms": [
"string"
]
}'Add a service to the account's catalog, or a location's own#
POST /v1/account/pricing/services
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
description | string | No | Up to 600 characters. Default: "". |
groupId | string (grp_… ID) | null | No | — |
kind | enum | No | One of: "service", "add_on", "fee". Default: "service". |
name | string | Yes | 1–80 characters. |
optionSetIds | array<string (oset_… ID)> | No | Up to 2 items. Default: []. |
perPerson | enum | No | One of: "single", "second_person". Default: "single". |
sort | integer | No | Between 0 and 100000. Default: 0. |
spokenName | string | No | 1–80 characters. |
synonyms | array<string> | No | Up to 20 items. Default: []. |
unit | enum | No | One of: "month", "day", "night", "week", "visit", "hour", "one_time". Default: "month". |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
archived | boolean | Yes | Default: false. |
description | string | Yes | Up to 600 characters. Default: "". |
groupId | string (grp_… ID) | null | Yes | — |
id | string (srv_… ID) | Yes | ID (srv_…) |
kind | enum | Yes | One of: "service", "add_on", "fee". Default: "service". |
name | string | Yes | 1–80 characters. |
optionSetIds | array<string (oset_… ID)> | Yes | Up to 2 items. Default: []. |
perPerson | enum | Yes | One of: "single", "second_person". Default: "single". |
sort | integer | Yes | Between 0 and 100000. Default: 0. |
spokenName | string | No | 1–80 characters. |
synonyms | array<string> | Yes | Up to 20 items. Default: []. |
unit | enum | Yes | One of: "month", "day", "night", "week", "visit", "hour", "one_time". Default: "month". |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/services" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "string"
}'Change or archive a service. Every location that offers it is recomputed#
PATCH /v1/account/pricing/services/{serviceId}
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
serviceId | string (srv_… ID) | Yes | ID (srv_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
archived | boolean | No | — |
description | string | No | Up to 600 characters. |
kind | enum | No | One of: "service", "add_on", "fee". |
name | string | No | 1–80 characters. |
optionSetIds | array<string (oset_… ID)> | No | Up to 2 items. |
perPerson | enum | No | One of: "single", "second_person". |
sort | integer | No | Between 0 and 100000. |
spokenName | string | null | No | 1–80 characters. |
synonyms | array<string> | No | Up to 20 items. |
unit | enum | No | One of: "month", "day", "night", "week", "visit", "hour", "one_time". |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
service | object | Yes | — |
service.archived | boolean | Yes | Default: false. |
service.description | string | Yes | Up to 600 characters. Default: "". |
service.groupId | string (grp_… ID) | null | Yes | — |
service.id | string (srv_… ID) | Yes | ID (srv_…) |
service.kind | enum | Yes | One of: "service", "add_on", "fee". Default: "service". |
service.name | string | Yes | 1–80 characters. |
service.optionSetIds | array<string (oset_… ID)> | Yes | Up to 2 items. Default: []. |
service.perPerson | enum | Yes | One of: "single", "second_person". Default: "single". |
service.sort | integer | Yes | Between 0 and 100000. Default: 0. |
service.spokenName | string | No | 1–80 characters. |
service.synonyms | array<string> | Yes | Up to 20 items. Default: []. |
service.unit | enum | Yes | One of: "month", "day", "night", "week", "visit", "hour", "one_time". Default: "month". |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X PATCH "$ANSWERSTACK_API_URL/v1/account/pricing/services/{serviceId}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"archived": true,
"description": "string",
"kind": "service",
"name": "string",
"optionSetIds": [
"oset_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE"
],
"perPerson": "single",
"sort": 0,
"spokenName": "string",
"synonyms": [
"string"
],
"unit": "month"
}'Your specials: drafts, those waiting for approval, and approved ones#
GET /v1/account/pricing/specials
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token). Bearer token: Authorization: Bearer <token> (An API token (ans_pat_ or ans_svc_). Only routes that list a scope here accept one, and only with that scope.).
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
specials | array<SpecialListItem> | Yes | — |
specials[].createdBy | string | null | Yes | — |
specials[].decidedBy | string | null | Yes | — |
specials[].decisionNote | string | null | Yes | — |
specials[].endsOn | string | null | Yes | — |
specials[].groupIds | array<string> | Yes | — |
specials[].id | string (spcl_… ID) | Yes | ID (spcl_…) |
specials[].reach | array<object> | Yes | — |
specials[].reach[].groupId | string | Yes | — |
specials[].reach[].groupName | string | Yes | — |
specials[].reach[].reason | enum | null | Yes | One of: "no_published_prices". |
specials[].reach[].said | boolean | Yes | — |
specials[].serviceIds | array<string> | Yes | — |
specials[].spokenWording | string | Yes | — |
specials[].startsOn | string | Yes | — |
specials[].status | enum | Yes | One of: "draft", "pending_approval", "approved". |
specials[].submittedBy | string | null | Yes | — |
specials[].title | string | Yes | — |
specials[].updatedAt | string (date-time) | Yes | — |
specials[].writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X GET "$ANSWERSTACK_API_URL/v1/account/pricing/specials" \
-H "Authorization: Bearer $ACCESS_TOKEN"Add a special. It is approved at once, or sent for approval when your changes need it, or kept as a draft#
POST /v1/account/pricing/specials
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
draft | boolean | No | — |
endsOn | string (date) | null | No | — |
groupIds | array<string (grp_… ID)> | No | Up to 500 items. Default: []. |
serviceIds | array<string (srv_… ID)> | No | Up to 50 items. Default: []. |
spokenWording | string | Yes | 1–300 characters. |
startsOn | string (date) | Yes | — |
title | string | Yes | 1–80 characters. |
writtenWording | string | No | 1–300 characters. |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
special | Special | Yes | — |
special.createdBy | string | null | Yes | — |
special.decidedBy | string | null | Yes | — |
special.decisionNote | string | null | Yes | — |
special.endsOn | string | null | Yes | — |
special.groupIds | array<string> | Yes | — |
special.id | string (spcl_… ID) | Yes | ID (spcl_…) |
special.serviceIds | array<string> | Yes | — |
special.spokenWording | string | Yes | — |
special.startsOn | string | Yes | — |
special.status | enum | Yes | One of: "draft", "pending_approval", "approved". |
special.submittedBy | string | null | Yes | — |
special.title | string | Yes | — |
special.updatedAt | string (date-time) | Yes | — |
special.writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/specials" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "string",
"spokenWording": "string",
"startsOn": "2026-01-15"
}'Change a special. Changing an approved one sends it back for approval when your changes need it#
PATCH /v1/account/pricing/specials/{specialId}
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
specialId | string (spcl_… ID) | Yes | ID (spcl_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
endsOn | string (date) | null | No | — |
groupIds | array<string (grp_… ID)> | No | Up to 500 items. |
serviceIds | array<string (srv_… ID)> | No | Up to 50 items. |
spokenWording | string | No | 1–300 characters. |
startsOn | string (date) | No | — |
title | string | No | 1–80 characters. |
writtenWording | string | null | No | 1–300 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
special | Special | Yes | — |
special.createdBy | string | null | Yes | — |
special.decidedBy | string | null | Yes | — |
special.decisionNote | string | null | Yes | — |
special.endsOn | string | null | Yes | — |
special.groupIds | array<string> | Yes | — |
special.id | string (spcl_… ID) | Yes | ID (spcl_…) |
special.serviceIds | array<string> | Yes | — |
special.spokenWording | string | Yes | — |
special.startsOn | string | Yes | — |
special.status | enum | Yes | One of: "draft", "pending_approval", "approved". |
special.submittedBy | string | null | Yes | — |
special.title | string | Yes | — |
special.updatedAt | string (date-time) | Yes | — |
special.writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X PATCH "$ANSWERSTACK_API_URL/v1/account/pricing/specials/{specialId}" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"endsOn": "2026-01-15",
"groupIds": [
"grp_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE"
],
"serviceIds": [
"srv_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE"
],
"spokenWording": "string",
"startsOn": "2026-01-15",
"title": "string",
"writtenWording": "string"
}'Delete a draft special (approved ones are ended, never deleted)#
DELETE /v1/account/pricing/specials/{specialId}
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
specialId | string (spcl_… ID) | Yes | ID (spcl_…) |
Response 204
No content.
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X DELETE "$ANSWERSTACK_API_URL/v1/account/pricing/specials/{specialId}" \
-H "Authorization: Bearer $ACCESS_TOKEN"Approve a special waiting for approval#
POST /v1/account/pricing/specials/{specialId}/approve
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
specialId | string (spcl_… ID) | Yes | ID (spcl_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
special | Special | Yes | — |
special.createdBy | string | null | Yes | — |
special.decidedBy | string | null | Yes | — |
special.decisionNote | string | null | Yes | — |
special.endsOn | string | null | Yes | — |
special.groupIds | array<string> | Yes | — |
special.id | string (spcl_… ID) | Yes | ID (spcl_…) |
special.serviceIds | array<string> | Yes | — |
special.spokenWording | string | Yes | — |
special.startsOn | string | Yes | — |
special.status | enum | Yes | One of: "draft", "pending_approval", "approved". |
special.submittedBy | string | null | Yes | — |
special.title | string | Yes | — |
special.updatedAt | string (date-time) | Yes | — |
special.writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/specials/{specialId}/approve" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "string"
}'End an approved special now: the agent stops mentioning it#
POST /v1/account/pricing/specials/{specialId}/end
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
specialId | string (spcl_… ID) | Yes | ID (spcl_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
special | Special | Yes | — |
special.createdBy | string | null | Yes | — |
special.decidedBy | string | null | Yes | — |
special.decisionNote | string | null | Yes | — |
special.endsOn | string | null | Yes | — |
special.groupIds | array<string> | Yes | — |
special.id | string (spcl_… ID) | Yes | ID (spcl_…) |
special.serviceIds | array<string> | Yes | — |
special.spokenWording | string | Yes | — |
special.startsOn | string | Yes | — |
special.status | enum | Yes | One of: "draft", "pending_approval", "approved". |
special.submittedBy | string | null | Yes | — |
special.title | string | Yes | — |
special.updatedAt | string (date-time) | Yes | — |
special.writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/specials/{specialId}/end" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "string"
}'Send a special waiting for approval back to draft, with a note saying why#
POST /v1/account/pricing/specials/{specialId}/return
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
specialId | string (spcl_… ID) | Yes | ID (spcl_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | Yes | 1–500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
special | Special | Yes | — |
special.createdBy | string | null | Yes | — |
special.decidedBy | string | null | Yes | — |
special.decisionNote | string | null | Yes | — |
special.endsOn | string | null | Yes | — |
special.groupIds | array<string> | Yes | — |
special.id | string (spcl_… ID) | Yes | ID (spcl_…) |
special.serviceIds | array<string> | Yes | — |
special.spokenWording | string | Yes | — |
special.startsOn | string | Yes | — |
special.status | enum | Yes | One of: "draft", "pending_approval", "approved". |
special.submittedBy | string | null | Yes | — |
special.title | string | Yes | — |
special.updatedAt | string (date-time) | Yes | — |
special.writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/specials/{specialId}/return" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "string"
}'Send a draft special for approval (approved at once when your changes do not need it)#
POST /v1/account/pricing/specials/{specialId}/submit
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
specialId | string (spcl_… ID) | Yes | ID (spcl_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
special | Special | Yes | — |
special.createdBy | string | null | Yes | — |
special.decidedBy | string | null | Yes | — |
special.decisionNote | string | null | Yes | — |
special.endsOn | string | null | Yes | — |
special.groupIds | array<string> | Yes | — |
special.id | string (spcl_… ID) | Yes | ID (spcl_…) |
special.serviceIds | array<string> | Yes | — |
special.spokenWording | string | Yes | — |
special.startsOn | string | Yes | — |
special.status | enum | Yes | One of: "draft", "pending_approval", "approved". |
special.submittedBy | string | null | Yes | — |
special.title | string | Yes | — |
special.updatedAt | string (date-time) | Yes | — |
special.writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/specials/{specialId}/submit" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "string"
}'Take back a special you sent for approval#
POST /v1/account/pricing/specials/{specialId}/withdraw
Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
specialId | string (spcl_… ID) | Yes | ID (spcl_…) |
Request body
application/json, required.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | No | Up to 500 characters. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
effective | array<object> | Yes | — |
effective[].groupId | string (grp_… ID) | Yes | ID (grp_…) |
effective[].issues | array<string> | Yes | — |
effective[].outcome | enum | Yes | One of: "updated", "needs_review", "blocked_no_backup", "blocked_opening", "no_profile". |
effective[].playbookId | string (pb_… ID) | Yes | ID (pb_…) |
special | Special | Yes | — |
special.createdBy | string | null | Yes | — |
special.decidedBy | string | null | Yes | — |
special.decisionNote | string | null | Yes | — |
special.endsOn | string | null | Yes | — |
special.groupIds | array<string> | Yes | — |
special.id | string (spcl_… ID) | Yes | ID (spcl_…) |
special.serviceIds | array<string> | Yes | — |
special.spokenWording | string | Yes | — |
special.startsOn | string | Yes | — |
special.status | enum | Yes | One of: "draft", "pending_approval", "approved". |
special.submittedBy | string | null | Yes | — |
special.title | string | Yes | — |
special.updatedAt | string (date-time) | Yes | — |
special.writtenWording | string | null | Yes | — |
Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.
Example
curl -X POST "$ANSWERSTACK_API_URL/v1/account/pricing/specials/{specialId}/withdraw" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"note": "string"
}'