API reference

Price Sync

Price Sync endpoints.

MethodPathSummary
POST/v1/account/connections/{connectionId}/price-syncSync now: read the CRM and update the listed locations (or all linked ones you can see). With a date ahead, schedule the CRM prices for that day
POST/v1/account/connections/{connectionId}/price-sync/previewPreview a date: what the CRM prices would be on that day at each location, against what is published
GET/v1/account/connections/{connectionId}/price-syncsRecent price syncs, newest first, for the locations you can see
GET/v1/account/connections/{connectionId}/pricing-mappingA connection's price sync mapping, and whether its CRM can supply prices
PUT/v1/account/connections/{connectionId}/pricing-mappingSave a price sync mapping after proving it against the CRM; with price sync on, the linked locations sync at once
GET/v1/account/connections/{connectionId}/pricing-mapping/suggestionsWhat the CRM holds (record types, values, templates) and map entries suggested from matching its names to your catalog. Nothing counts until you accept it
POST/v1/account/connections/{connectionId}/pricing-mapping/testRun a mapping against the CRM for every linked location and show what it would set, publishing nothing
GET/v1/account/connections/{connectionId}/pricing-mapping/versionsA connection's price sync mapping versions, newest first
GET/v1/account/price-syncThe account's price source, if any, and each location's latest sync with what the CRM says for every cell

Sync now: read the CRM and update the listed locations (or all linked ones you can see). With a date ahead, schedule the CRM prices for that day#

POST /v1/account/connections/{connectionId}/price-sync

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Request body

application/json, required.

FieldTypeRequiredDescription
effectiveFromstring (date-time)No—
groupIdsarray<string (grp_… ID)>NoUp to 500 items.
rateDatestring (date)No—

Response 200

FieldTypeRequiredDescription
resultsarray<object>Yes—
results[].changesintegerYes—
results[].errorCodestring | nullYes—
results[].groupIdstringYes—
results[].heldstring | nullYes—
results[].outcomeenumYesOne of: "unchanged", "drafted", "published", "submitted", "failed".
results[].versioninteger | nullYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/price-sync" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "effectiveFrom": "2026-01-15T15:30:00Z",
  "groupIds": [
    "grp_2ZPh7XbT0v9Ao4iJ3qK1mN8sRgE"
  ],
  "rateDate": "2026-01-15"
}'

Preview a date: what the CRM prices would be on that day at each location, against what is published#

POST /v1/account/connections/{connectionId}/price-sync/preview

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Request body

application/json, required.

FieldTypeRequiredDescription
groupIdsarray<string (grp_… ID)>NoUp to 500 items.
rateDatestring (date)Yes—

Response 200

FieldTypeRequiredDescription
locationsarray<PriceSyncPreview>Yes—
locations[].cellsarray<object>Yes—
locations[].cells[].centsinteger | nullYes—
locations[].cells[].optionIdsarray<string>Yes—
locations[].cells[].problemenum | nullYesOne of: "nothing_found", "not_single", "part_failed", "out_of_range".
locations[].cells[].recordsarray<string>Yes—
locations[].cells[].ruleIdstringYes—
locations[].cells[].serviceIdstringYes—
locations[].changesarray<object>Yes—
locations[].changes[].afterobject | object | nullYes—
locations[].changes[].after.centsintegerYes(variant 1) Between 1 and 99999999.
locations[].changes[].after.kindconstantYes(variant 1) Always "starting_at".
locations[].changes[].after.kindconstantYes(variant 2) Always "on_request".
locations[].changes[].beforeobject | object | nullYes—
locations[].changes[].before.centsintegerYes(variant 1) Between 1 and 99999999.
locations[].changes[].before.kindconstantYes(variant 1) Always "starting_at".
locations[].changes[].before.kindconstantYes(variant 2) Always "on_request".
locations[].changes[].optionIdsarray<string>Yes—
locations[].changes[].ruleIdstringYes—
locations[].changes[].serviceIdstringYes—
locations[].groupIdstringYes—
locations[].groupNamestringYes—
locations[].notOfferedarray<string>Yes—
locations[].problemsintegerYes—
locations[].unmappedarray<object>Yes—
locations[].unmapped[].keystringYes1–64 characters.
locations[].unmapped[].labelstringYesUp to 200 characters.
locations[].unmapped[].locationRefstring | nullYes1–128 characters.
locations[].unmapped[].refstringYes1–128 characters.
locations[].unmapped[].typestringYes1–64 characters.

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/price-sync/preview" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "rateDate": "2026-01-15"
}'

Recent price syncs, newest first, for the locations you can see#

GET /v1/account/connections/{connectionId}/price-syncs

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

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Query parameters

NameTypeRequiredDescription
groupIdstring (grp_… ID)NoID (grp_…)

Response 200

FieldTypeRequiredDescription
syncsarray<PriceSyncRecord>Yes—
syncs[].cellsarray<object>Yes—
syncs[].cells[].centsinteger | nullYes—
syncs[].cells[].optionIdsarray<string>Yes—
syncs[].cells[].problemenum | nullYesOne of: "nothing_found", "not_single", "part_failed", "out_of_range".
syncs[].cells[].recordsarray<string>Yes—
syncs[].cells[].ruleIdstringYes—
syncs[].cells[].serviceIdstringYes—
syncs[].changesarray<object>Yes—
syncs[].changes[].afterobject | object | nullYes—
syncs[].changes[].after.centsintegerYes(variant 1) Between 1 and 99999999.
syncs[].changes[].after.kindconstantYes(variant 1) Always "starting_at".
syncs[].changes[].after.kindconstantYes(variant 2) Always "on_request".
syncs[].changes[].beforeobject | object | nullYes—
syncs[].changes[].before.centsintegerYes(variant 1) Between 1 and 99999999.
syncs[].changes[].before.kindconstantYes(variant 1) Always "starting_at".
syncs[].changes[].before.kindconstantYes(variant 2) Always "on_request".
syncs[].changes[].optionIdsarray<string>Yes—
syncs[].changes[].ruleIdstringYes—
syncs[].changes[].serviceIdstringYes—
syncs[].effectiveFromstring (date-time) | nullYes—
syncs[].errorCodestring | nullYes—
syncs[].finishedAtstring (date-time) | nullYes—
syncs[].groupIdstringYes—
syncs[].heldReasonstring | nullYes—
syncs[].idstringYes—
syncs[].mappingVersionintegerYes—
syncs[].outcomeenum | nullYesOne of: "unchanged", "drafted", "published", "submitted", "failed".
syncs[].priceBookVersioninteger | nullYes—
syncs[].problemsintegerYes—
syncs[].rateDatestringYes—
syncs[].recordCountintegerYes—
syncs[].startedAtstring (date-time)Yes—
syncs[].triggerenumYesOne of: "schedule", "manual", "mapping_change", "scheduled_date".
syncs[].unmappedintegerYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X GET "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/price-syncs" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

A connection's price sync mapping, and whether its CRM can supply prices#

GET /v1/account/connections/{connectionId}/pricing-mapping

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

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Response 200

FieldTypeRequiredDescription
availablebooleanYes—
currentobject | nullYes—
current.authorIdstring | nullYes—
current.createdAtstring (date-time)Yes—
current.mappingobjectYes—
current.mapping.linksarray<object>YesUp to 1000 items. Default: [].
current.mapping.links[].groupIdstring (grp_… ID)YesID (grp_…)
current.mapping.links[].locationRefsarray<string>YesUp to 5 items.
current.mapping.locationMapsarray<object>YesUp to 1000 items. Default: [].
current.mapping.locationMaps[].entriesarray<object>YesUp to 1000 items.
current.mapping.locationMaps[].groupIdstring (grp_… ID)YesID (grp_…)
current.mapping.locationSettingsarray<object>YesUp to 1000 items. Default: [].
current.mapping.locationSettings[].applyenumNoOne of: "review", "auto".
current.mapping.locationSettings[].groupIdstring (grp_… ID)YesID (grp_…)
current.mapping.locationSettings[].limitsobjectNo—
current.mapping.locationSettings[].whenNothingenumNoOne of: "keep", "on_request".
current.mapping.mapsarray<object>YesUp to 5000 items. Default: [].
current.mapping.maps[].keystringYes1–64 characters.
current.mapping.maps[].locationRefstring | nullYes1–128 characters.
current.mapping.maps[].matchobject | object | object | objectYes—
current.mapping.maps[].targetobject | object | objectYes—
current.mapping.maps[].typestringYes1–64 characters.
current.mapping.overridesarray<object | object>YesUp to 5000 items. Default: [].
current.mapping.overrides[].actionenumYes(variant 1) One of: "off".
current.mapping.overrides[].groupIdstring (grp_… ID)Yes(variant 1) ID (grp_…)
current.mapping.overrides[].ruleIdstringYes(variant 1) 1–64 characters.
current.mapping.overrides[].actionenumYes(variant 2) One of: "change".
current.mapping.overrides[].groupIdstring (grp_… ID)Yes(variant 2) ID (grp_…)
current.mapping.overrides[].ruleobjectYes(variant 2)
current.mapping.overrides[].ruleIdstringYes(variant 2) 1–64 characters.
current.mapping.rulesarray<object>YesUp to 500 items. Default: [].
current.mapping.rules[].adjustobject | nullYes—
current.mapping.rules[].appliesToobjectYes—
current.mapping.rules[].chooseobjectYesDefault: \{"filters":[],"pinnedRef":null\}.
current.mapping.rules[].combineenumYesOne of: "lowest", "average", "single". Default: "lowest".
current.mapping.rules[].groupIdsarray<string (grp_… ID)>YesUp to 500 items. Default: [].
current.mapping.rules[].idstringYes1–64 characters.
current.mapping.rules[].plusarray<object | object>YesUp to 3 items. Default: [].
current.mapping.rules[].roundobject | nullYes—
current.mapping.rules[].sourcestringYes1–64 characters.
current.mapping.rules[].valuestringYes1–64 characters.
current.mapping.settingsobjectYesDefault: \{"apply":"review","enabled":false,"limits":\{"holdRemovals":true,"maxChangePercent":10,"maxChangedCells":null\},"rateDate":"today","rounding":\{"direction":"up","stepCents":5000\},"schedule":\{"hour":2,"kind":"nightly"\},"whenNothing":"keep"\}.
current.mapping.settings.applyenumYesOne of: "review", "auto". Default: "review".
current.mapping.settings.enabledbooleanYesDefault: false.
current.mapping.settings.limitsobjectYesDefault: \{"holdRemovals":true,"maxChangePercent":10,"maxChangedCells":null\}.
current.mapping.settings.rateDateenumYesOne of: "today", "first_of_next_month". Default: "today".
current.mapping.settings.roundingobjectYesDefault: \{"direction":"up","stepCents":5000\}.
current.mapping.settings.scheduleobject | object | objectYesDefault: \{"hour":2,"kind":"nightly"\}.
current.mapping.settings.whenNothingenumYesOne of: "keep", "on_request". Default: "keep".
current.notestring | nullYes—
current.versionintegerYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X GET "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/pricing-mapping" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Save a price sync mapping after proving it against the CRM; with price sync on, the linked locations sync at once#

PUT /v1/account/connections/{connectionId}/pricing-mapping

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Request body

application/json, required.

FieldTypeRequiredDescription
mappingobjectYes—
mapping.linksarray<object>NoUp to 1000 items. Default: [].
mapping.links[].groupIdstring (grp_… ID)YesID (grp_…)
mapping.links[].locationRefsarray<string>YesUp to 5 items.
mapping.locationMapsarray<object>NoUp to 1000 items. Default: [].
mapping.locationMaps[].entriesarray<object>YesUp to 1000 items.
mapping.locationMaps[].entries[].keystringYes1–64 characters.
mapping.locationMaps[].entries[].locationRefstring | nullNo1–128 characters.
mapping.locationMaps[].entries[].matchobject | object | object | objectYes—
mapping.locationMaps[].entries[].targetobject | object | objectYes—
mapping.locationMaps[].entries[].typestringYes1–64 characters.
mapping.locationMaps[].groupIdstring (grp_… ID)YesID (grp_…)
mapping.locationSettingsarray<object>NoUp to 1000 items. Default: [].
mapping.locationSettings[].applyenumNoOne of: "review", "auto".
mapping.locationSettings[].groupIdstring (grp_… ID)YesID (grp_…)
mapping.locationSettings[].limitsobjectNo—
mapping.locationSettings[].limits.holdRemovalsbooleanNoDefault: true.
mapping.locationSettings[].limits.maxChangePercentnumber | nullNoBetween 0 and 1000.
mapping.locationSettings[].limits.maxChangedCellsinteger | nullNoBetween 1 and 10000.
mapping.locationSettings[].whenNothingenumNoOne of: "keep", "on_request".
mapping.mapsarray<object>NoUp to 5000 items. Default: [].
mapping.maps[].keystringYes1–64 characters.
mapping.maps[].locationRefstring | nullNo1–128 characters.
mapping.maps[].matchobject | object | object | objectYes—
mapping.maps[].match.byenumYes(variant 1) One of: "id".
mapping.maps[].match.refstringYes(variant 1) 1–128 characters.
mapping.maps[].match.byenumYes(variant 2) One of: "name".
mapping.maps[].match.namestringYes(variant 2) 1–120 characters.
mapping.maps[].match.byenumYes(variant 3) One of: "contains".
mapping.maps[].match.textstringYes(variant 3) 1–120 characters.
mapping.maps[].match.byenumYes(variant 4) One of: "starts_with".
mapping.maps[].match.textstringYes(variant 4) 1–120 characters.
mapping.maps[].targetobject | object | objectYes—
mapping.maps[].target.kindenumYes(variant 1) One of: "service".
mapping.maps[].target.serviceIdstring (srv_… ID)Yes(variant 1) ID (srv_…)
mapping.maps[].target.kindenumYes(variant 2) One of: "option".
mapping.maps[].target.optionIdstring (sopt_… ID)Yes(variant 2) ID (sopt_…)
mapping.maps[].target.kindenumYes(variant 3) One of: "ignore".
mapping.maps[].typestringYes1–64 characters.
mapping.overridesarray<object | object>NoUp to 5000 items. Default: [].
mapping.overrides[].actionenumYes(variant 1) One of: "off".
mapping.overrides[].groupIdstring (grp_… ID)Yes(variant 1) ID (grp_…)
mapping.overrides[].ruleIdstringYes(variant 1) 1–64 characters.
mapping.overrides[].actionenumYes(variant 2) One of: "change".
mapping.overrides[].groupIdstring (grp_… ID)Yes(variant 2) ID (grp_…)
mapping.overrides[].ruleobjectYes(variant 2)
mapping.overrides[].rule.adjustobject | nullNo(variant 2)
mapping.overrides[].rule.appliesToobjectYes(variant 2)
mapping.overrides[].rule.chooseobjectNo(variant 2) Default: \{"filters":[],"pinnedRef":null\}.
mapping.overrides[].rule.combineenumNo(variant 2) One of: "lowest", "average", "single". Default: "lowest".
mapping.overrides[].rule.groupIdsarray<string (grp_… ID)>No(variant 2) Up to 500 items. Default: [].
mapping.overrides[].rule.plusarray<object | object>No(variant 2) Up to 3 items. Default: [].
mapping.overrides[].rule.roundobject | nullNo(variant 2)
mapping.overrides[].rule.sourcestringYes(variant 2) 1–64 characters.
mapping.overrides[].rule.valuestringYes(variant 2) 1–64 characters.
mapping.overrides[].ruleIdstringYes(variant 2) 1–64 characters.
mapping.rulesarray<object>NoUp to 500 items. Default: [].
mapping.rules[].adjustobject | nullNo—
mapping.rules[].adjust.centsintegerNoBetween -99999999 and 99999999.
mapping.rules[].adjust.percentnumberNoBetween -90 and 500.
mapping.rules[].appliesToobjectYes—
mapping.rules[].appliesTo.optionIdsarray<string (sopt_… ID)>NoUp to 2 items. Default: [].
mapping.rules[].appliesTo.serviceIdstring (srv_… ID)YesID (srv_…)
mapping.rules[].chooseobjectNoDefault: \{"filters":[],"pinnedRef":null\}.
mapping.rules[].choose.filtersarray<object>NoUp to 10 items. Default: [].
mapping.rules[].choose.pinnedRefstring | nullNo1–128 characters.
mapping.rules[].combineenumNoOne of: "lowest", "average", "single". Default: "lowest".
mapping.rules[].groupIdsarray<string (grp_… ID)>NoUp to 500 items. Default: [].
mapping.rules[].idstringYes1–64 characters.
mapping.rules[].plusarray<object | object>NoUp to 3 items. Default: [].
mapping.rules[].plus[].chooseobjectNo(variant 1) Default: \{"filters":[],"pinnedRef":null\}.
mapping.rules[].plus[].combineenumNo(variant 1) One of: "lowest", "average", "single". Default: "lowest".
mapping.rules[].plus[].kindenumYes(variant 1) One of: "records".
mapping.rules[].plus[].sourcestringYes(variant 1) 1–64 characters.
mapping.rules[].plus[].valuestringYes(variant 1) 1–64 characters.
mapping.rules[].plus[].centsintegerYes(variant 2) Between 0 and 99999999.
mapping.rules[].plus[].kindenumYes(variant 2) One of: "typed".
mapping.rules[].roundobject | nullNo—
mapping.rules[].round.directionenumYesOne of: "up", "down", "nearest".
mapping.rules[].round.stepCentsintegerYesBetween 1 and 1000000.
mapping.rules[].sourcestringYes1–64 characters.
mapping.rules[].valuestringYes1–64 characters.
mapping.settingsobjectNoDefault: \{"apply":"review","enabled":false,"limits":\{"holdRemovals":true,"maxChangePercent":10,"maxChangedCells":null\},"rateDate":"today","rounding":\{"direction":"up","stepCents":5000\},"schedule":\{"hour":2,"kind":"nightly"\},"whenNothing":"keep"\}.
mapping.settings.applyenumNoOne of: "review", "auto". Default: "review".
mapping.settings.enabledbooleanNoDefault: false.
mapping.settings.limitsobjectNoDefault: \{"holdRemovals":true,"maxChangePercent":10,"maxChangedCells":null\}.
mapping.settings.limits.holdRemovalsbooleanNoDefault: true.
mapping.settings.limits.maxChangePercentnumber | nullNoBetween 0 and 1000.
mapping.settings.limits.maxChangedCellsinteger | nullNoBetween 1 and 10000.
mapping.settings.rateDateenumNoOne of: "today", "first_of_next_month". Default: "today".
mapping.settings.roundingobjectNoDefault: \{"direction":"up","stepCents":5000\}.
mapping.settings.rounding.directionenumYesOne of: "up", "down", "nearest".
mapping.settings.rounding.stepCentsintegerYesBetween 1 and 1000000.
mapping.settings.scheduleobject | object | objectNoDefault: \{"hour":2,"kind":"nightly"\}.
mapping.settings.schedule.hourintegerYes(variant 1) Between 0 and 23.
mapping.settings.schedule.kindenumYes(variant 1) One of: "nightly".
mapping.settings.schedule.hourintegerYes(variant 2) Between 0 and 23.
mapping.settings.schedule.kindenumYes(variant 2) One of: "weekly".
mapping.settings.schedule.weekdayintegerYes(variant 2) Between 0 and 6.
mapping.settings.schedule.kindenumYes(variant 3) One of: "manual".
mapping.settings.whenNothingenumNoOne of: "keep", "on_request". Default: "keep".
notestringNoUp to 500 characters.

Response 200

FieldTypeRequiredDescription
syncarray<object>Yes—
sync[].changesintegerYes—
sync[].errorCodestring | nullYes—
sync[].groupIdstringYes—
sync[].heldstring | nullYes—
sync[].outcomeenumYesOne of: "unchanged", "drafted", "published", "submitted", "failed".
sync[].versioninteger | nullYes—
testPriceSyncTestYes—
test.brokenarray<object>Yes—
test.broken[].keystringYes1–64 characters.
test.broken[].locationRefstring | nullYes1–128 characters.
test.broken[].matchobject | object | object | objectYes—
test.broken[].match.byconstantYes(variant 1) Always "id".
test.broken[].match.refstringYes(variant 1) 1–128 characters.
test.broken[].match.byconstantYes(variant 2) Always "name".
test.broken[].match.namestringYes(variant 2) 1–120 characters.
test.broken[].match.byconstantYes(variant 3) Always "contains".
test.broken[].match.textstringYes(variant 3) 1–120 characters.
test.broken[].match.byconstantYes(variant 4) Always "starts_with".
test.broken[].match.textstringYes(variant 4) 1–120 characters.
test.broken[].targetobject | object | objectYes—
test.broken[].target.kindconstantYes(variant 1) Always "service".
test.broken[].target.serviceIdstring (srv_… ID)Yes(variant 1) ID (srv_…)
test.broken[].target.kindconstantYes(variant 2) Always "option".
test.broken[].target.optionIdstring (sopt_… ID)Yes(variant 2) ID (sopt_…)
test.broken[].target.kindconstantYes(variant 3) Always "ignore".
test.broken[].typestringYes1–64 characters.
test.issuesarray<object>Yes—
test.issues[].messagestringYes—
test.issues[].pathstringYes—
test.locationsarray<PriceSyncPreview>Yes—
test.locations[].cellsarray<object>Yes—
test.locations[].cells[].centsinteger | nullYes—
test.locations[].cells[].optionIdsarray<string>Yes—
test.locations[].cells[].problemenum | nullYesOne of: "nothing_found", "not_single", "part_failed", "out_of_range".
test.locations[].cells[].recordsarray<string>Yes—
test.locations[].cells[].ruleIdstringYes—
test.locations[].cells[].serviceIdstringYes—
test.locations[].changesarray<object>Yes—
test.locations[].changes[].afterobject | object | nullYes—
test.locations[].changes[].beforeobject | object | nullYes—
test.locations[].changes[].optionIdsarray<string>Yes—
test.locations[].changes[].ruleIdstringYes—
test.locations[].changes[].serviceIdstringYes—
test.locations[].groupIdstringYes—
test.locations[].groupNamestringYes—
test.locations[].notOfferedarray<string>Yes—
test.locations[].problemsintegerYes—
test.locations[].unmappedarray<object>Yes—
test.locations[].unmapped[].keystringYes1–64 characters.
test.locations[].unmapped[].labelstringYesUp to 200 characters.
test.locations[].unmapped[].locationRefstring | nullYes1–128 characters.
test.locations[].unmapped[].refstringYes1–128 characters.
test.locations[].unmapped[].typestringYes1–64 characters.
test.recordCountintegerYes—
versionintegerYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X PUT "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/pricing-mapping" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "mapping": {
    "links": [],
    "locationMaps": [],
    "locationSettings": [],
    "maps": [],
    "overrides": [],
    "rules": [],
    "settings": {
      "apply": "review",
      "enabled": false,
      "limits": {
        "holdRemovals": true,
        "maxChangePercent": 10,
        "maxChangedCells": null
      },
      "rateDate": "today",
      "rounding": {
        "direction": "up",
        "stepCents": 5000
      },
      "schedule": {
        "hour": 2,
        "kind": "nightly"
      },
      "whenNothing": "keep"
    }
  }
}'

What the CRM holds (record types, values, templates) and map entries suggested from matching its names to your catalog. Nothing counts until you accept it#

GET /v1/account/connections/{connectionId}/pricing-mapping/suggestions

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Response 200

FieldTypeRequiredDescription
suggestionsarray<object>Yes—
suggestions[].becausestringYes—
suggestions[].entryobjectYes—
suggestions[].entry.keystringYes1–64 characters.
suggestions[].entry.locationRefstring | nullYes1–128 characters.
suggestions[].entry.matchobject | object | object | objectYes—
suggestions[].entry.match.byenumYes(variant 1) One of: "id".
suggestions[].entry.match.refstringYes(variant 1) 1–128 characters.
suggestions[].entry.match.byenumYes(variant 2) One of: "name".
suggestions[].entry.match.namestringYes(variant 2) 1–120 characters.
suggestions[].entry.match.byenumYes(variant 3) One of: "contains".
suggestions[].entry.match.textstringYes(variant 3) 1–120 characters.
suggestions[].entry.match.byenumYes(variant 4) One of: "starts_with".
suggestions[].entry.match.textstringYes(variant 4) 1–120 characters.
suggestions[].entry.targetobject | object | objectYes—
suggestions[].entry.target.kindenumYes(variant 1) One of: "service".
suggestions[].entry.target.serviceIdstring (srv_… ID)Yes(variant 1) ID (srv_…)
suggestions[].entry.target.kindenumYes(variant 2) One of: "option".
suggestions[].entry.target.optionIdstring (sopt_… ID)Yes(variant 2) ID (sopt_…)
suggestions[].entry.target.kindenumYes(variant 3) One of: "ignore".
suggestions[].entry.typestringYes1–64 characters.
suggestions[].valueobjectYes—
suggestions[].value.keystringYes1–64 characters.
suggestions[].value.labelstringYesUp to 200 characters.
suggestions[].value.locationRefstring | nullYes1–128 characters.
suggestions[].value.refstringYes1–128 characters.
suggestions[].value.typestringYes1–64 characters.
templatesarray<object>Yes—
templates[].idstringYes1–64 characters.
templates[].keysarray<string>YesUp to 5 items.
templates[].labelstringYes1–120 characters.
templates[].typestringYes1–64 characters.
templates[].valuestringYes1–64 characters.
typesarray<object>Yes—
types[].filtersarray<object>YesUp to 20 items.
types[].filters[].keystringYes1–64 characters.
types[].filters[].kindenumYesOne of: "boolean", "number", "text", "list".
types[].filters[].labelstringYes1–80 characters.
types[].labelstringYes1–80 characters.
types[].moneyarray<object>YesUp to 20 items.
types[].money[].keystringYes1–64 characters.
types[].money[].labelstringYes1–80 characters.
types[].namedarray<object>YesUp to 20 items.
types[].named[].keystringYes1–64 characters.
types[].named[].labelstringYes1–80 characters.
types[].named[].perLocationbooleanYesDefault: false.
types[].rateByDatebooleanYesDefault: false.
types[].typestringYes1–64 characters.
valuesarray<object>Yes—
values[].keystringYes1–64 characters.
values[].labelstringYesUp to 200 characters.
values[].locationRefstring | nullYes1–128 characters.
values[].refstringYes1–128 characters.
values[].typestringYes1–64 characters.

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X GET "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/pricing-mapping/suggestions" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Run a mapping against the CRM for every linked location and show what it would set, publishing nothing#

POST /v1/account/connections/{connectionId}/pricing-mapping/test

Authentication: Bearer token: Authorization: Bearer <token> (Supabase access token).

Path parameters

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Request body

application/json, required.

FieldTypeRequiredDescription
mappingobjectNo—
mapping.linksarray<object>NoUp to 1000 items. Default: [].
mapping.links[].groupIdstring (grp_… ID)YesID (grp_…)
mapping.links[].locationRefsarray<string>YesUp to 5 items.
mapping.locationMapsarray<object>NoUp to 1000 items. Default: [].
mapping.locationMaps[].entriesarray<object>YesUp to 1000 items.
mapping.locationMaps[].entries[].keystringYes1–64 characters.
mapping.locationMaps[].entries[].locationRefstring | nullNo1–128 characters.
mapping.locationMaps[].entries[].matchobject | object | object | objectYes—
mapping.locationMaps[].entries[].targetobject | object | objectYes—
mapping.locationMaps[].entries[].typestringYes1–64 characters.
mapping.locationMaps[].groupIdstring (grp_… ID)YesID (grp_…)
mapping.locationSettingsarray<object>NoUp to 1000 items. Default: [].
mapping.locationSettings[].applyenumNoOne of: "review", "auto".
mapping.locationSettings[].groupIdstring (grp_… ID)YesID (grp_…)
mapping.locationSettings[].limitsobjectNo—
mapping.locationSettings[].limits.holdRemovalsbooleanNoDefault: true.
mapping.locationSettings[].limits.maxChangePercentnumber | nullNoBetween 0 and 1000.
mapping.locationSettings[].limits.maxChangedCellsinteger | nullNoBetween 1 and 10000.
mapping.locationSettings[].whenNothingenumNoOne of: "keep", "on_request".
mapping.mapsarray<object>NoUp to 5000 items. Default: [].
mapping.maps[].keystringYes1–64 characters.
mapping.maps[].locationRefstring | nullNo1–128 characters.
mapping.maps[].matchobject | object | object | objectYes—
mapping.maps[].match.byenumYes(variant 1) One of: "id".
mapping.maps[].match.refstringYes(variant 1) 1–128 characters.
mapping.maps[].match.byenumYes(variant 2) One of: "name".
mapping.maps[].match.namestringYes(variant 2) 1–120 characters.
mapping.maps[].match.byenumYes(variant 3) One of: "contains".
mapping.maps[].match.textstringYes(variant 3) 1–120 characters.
mapping.maps[].match.byenumYes(variant 4) One of: "starts_with".
mapping.maps[].match.textstringYes(variant 4) 1–120 characters.
mapping.maps[].targetobject | object | objectYes—
mapping.maps[].target.kindenumYes(variant 1) One of: "service".
mapping.maps[].target.serviceIdstring (srv_… ID)Yes(variant 1) ID (srv_…)
mapping.maps[].target.kindenumYes(variant 2) One of: "option".
mapping.maps[].target.optionIdstring (sopt_… ID)Yes(variant 2) ID (sopt_…)
mapping.maps[].target.kindenumYes(variant 3) One of: "ignore".
mapping.maps[].typestringYes1–64 characters.
mapping.overridesarray<object | object>NoUp to 5000 items. Default: [].
mapping.overrides[].actionenumYes(variant 1) One of: "off".
mapping.overrides[].groupIdstring (grp_… ID)Yes(variant 1) ID (grp_…)
mapping.overrides[].ruleIdstringYes(variant 1) 1–64 characters.
mapping.overrides[].actionenumYes(variant 2) One of: "change".
mapping.overrides[].groupIdstring (grp_… ID)Yes(variant 2) ID (grp_…)
mapping.overrides[].ruleobjectYes(variant 2)
mapping.overrides[].rule.adjustobject | nullNo(variant 2)
mapping.overrides[].rule.appliesToobjectYes(variant 2)
mapping.overrides[].rule.chooseobjectNo(variant 2) Default: \{"filters":[],"pinnedRef":null\}.
mapping.overrides[].rule.combineenumNo(variant 2) One of: "lowest", "average", "single". Default: "lowest".
mapping.overrides[].rule.groupIdsarray<string (grp_… ID)>No(variant 2) Up to 500 items. Default: [].
mapping.overrides[].rule.plusarray<object | object>No(variant 2) Up to 3 items. Default: [].
mapping.overrides[].rule.roundobject | nullNo(variant 2)
mapping.overrides[].rule.sourcestringYes(variant 2) 1–64 characters.
mapping.overrides[].rule.valuestringYes(variant 2) 1–64 characters.
mapping.overrides[].ruleIdstringYes(variant 2) 1–64 characters.
mapping.rulesarray<object>NoUp to 500 items. Default: [].
mapping.rules[].adjustobject | nullNo—
mapping.rules[].adjust.centsintegerNoBetween -99999999 and 99999999.
mapping.rules[].adjust.percentnumberNoBetween -90 and 500.
mapping.rules[].appliesToobjectYes—
mapping.rules[].appliesTo.optionIdsarray<string (sopt_… ID)>NoUp to 2 items. Default: [].
mapping.rules[].appliesTo.serviceIdstring (srv_… ID)YesID (srv_…)
mapping.rules[].chooseobjectNoDefault: \{"filters":[],"pinnedRef":null\}.
mapping.rules[].choose.filtersarray<object>NoUp to 10 items. Default: [].
mapping.rules[].choose.pinnedRefstring | nullNo1–128 characters.
mapping.rules[].combineenumNoOne of: "lowest", "average", "single". Default: "lowest".
mapping.rules[].groupIdsarray<string (grp_… ID)>NoUp to 500 items. Default: [].
mapping.rules[].idstringYes1–64 characters.
mapping.rules[].plusarray<object | object>NoUp to 3 items. Default: [].
mapping.rules[].plus[].chooseobjectNo(variant 1) Default: \{"filters":[],"pinnedRef":null\}.
mapping.rules[].plus[].combineenumNo(variant 1) One of: "lowest", "average", "single". Default: "lowest".
mapping.rules[].plus[].kindenumYes(variant 1) One of: "records".
mapping.rules[].plus[].sourcestringYes(variant 1) 1–64 characters.
mapping.rules[].plus[].valuestringYes(variant 1) 1–64 characters.
mapping.rules[].plus[].centsintegerYes(variant 2) Between 0 and 99999999.
mapping.rules[].plus[].kindenumYes(variant 2) One of: "typed".
mapping.rules[].roundobject | nullNo—
mapping.rules[].round.directionenumYesOne of: "up", "down", "nearest".
mapping.rules[].round.stepCentsintegerYesBetween 1 and 1000000.
mapping.rules[].sourcestringYes1–64 characters.
mapping.rules[].valuestringYes1–64 characters.
mapping.settingsobjectNoDefault: \{"apply":"review","enabled":false,"limits":\{"holdRemovals":true,"maxChangePercent":10,"maxChangedCells":null\},"rateDate":"today","rounding":\{"direction":"up","stepCents":5000\},"schedule":\{"hour":2,"kind":"nightly"\},"whenNothing":"keep"\}.
mapping.settings.applyenumNoOne of: "review", "auto". Default: "review".
mapping.settings.enabledbooleanNoDefault: false.
mapping.settings.limitsobjectNoDefault: \{"holdRemovals":true,"maxChangePercent":10,"maxChangedCells":null\}.
mapping.settings.limits.holdRemovalsbooleanNoDefault: true.
mapping.settings.limits.maxChangePercentnumber | nullNoBetween 0 and 1000.
mapping.settings.limits.maxChangedCellsinteger | nullNoBetween 1 and 10000.
mapping.settings.rateDateenumNoOne of: "today", "first_of_next_month". Default: "today".
mapping.settings.roundingobjectNoDefault: \{"direction":"up","stepCents":5000\}.
mapping.settings.rounding.directionenumYesOne of: "up", "down", "nearest".
mapping.settings.rounding.stepCentsintegerYesBetween 1 and 1000000.
mapping.settings.scheduleobject | object | objectNoDefault: \{"hour":2,"kind":"nightly"\}.
mapping.settings.schedule.hourintegerYes(variant 1) Between 0 and 23.
mapping.settings.schedule.kindenumYes(variant 1) One of: "nightly".
mapping.settings.schedule.hourintegerYes(variant 2) Between 0 and 23.
mapping.settings.schedule.kindenumYes(variant 2) One of: "weekly".
mapping.settings.schedule.weekdayintegerYes(variant 2) Between 0 and 6.
mapping.settings.schedule.kindenumYes(variant 3) One of: "manual".
mapping.settings.whenNothingenumNoOne of: "keep", "on_request". Default: "keep".

Response 200

FieldTypeRequiredDescription
brokenarray<object>Yes—
broken[].keystringYes1–64 characters.
broken[].locationRefstring | nullYes1–128 characters.
broken[].matchobject | object | object | objectYes—
broken[].match.byconstantYes(variant 1) Always "id".
broken[].match.refstringYes(variant 1) 1–128 characters.
broken[].match.byconstantYes(variant 2) Always "name".
broken[].match.namestringYes(variant 2) 1–120 characters.
broken[].match.byconstantYes(variant 3) Always "contains".
broken[].match.textstringYes(variant 3) 1–120 characters.
broken[].match.byconstantYes(variant 4) Always "starts_with".
broken[].match.textstringYes(variant 4) 1–120 characters.
broken[].targetobject | object | objectYes—
broken[].target.kindconstantYes(variant 1) Always "service".
broken[].target.serviceIdstring (srv_… ID)Yes(variant 1) ID (srv_…)
broken[].target.kindconstantYes(variant 2) Always "option".
broken[].target.optionIdstring (sopt_… ID)Yes(variant 2) ID (sopt_…)
broken[].target.kindconstantYes(variant 3) Always "ignore".
broken[].typestringYes1–64 characters.
issuesarray<object>Yes—
issues[].messagestringYes—
issues[].pathstringYes—
locationsarray<PriceSyncPreview>Yes—
locations[].cellsarray<object>Yes—
locations[].cells[].centsinteger | nullYes—
locations[].cells[].optionIdsarray<string>Yes—
locations[].cells[].problemenum | nullYesOne of: "nothing_found", "not_single", "part_failed", "out_of_range".
locations[].cells[].recordsarray<string>Yes—
locations[].cells[].ruleIdstringYes—
locations[].cells[].serviceIdstringYes—
locations[].changesarray<object>Yes—
locations[].changes[].afterobject | object | nullYes—
locations[].changes[].after.centsintegerYes(variant 1) Between 1 and 99999999.
locations[].changes[].after.kindconstantYes(variant 1) Always "starting_at".
locations[].changes[].after.kindconstantYes(variant 2) Always "on_request".
locations[].changes[].beforeobject | object | nullYes—
locations[].changes[].before.centsintegerYes(variant 1) Between 1 and 99999999.
locations[].changes[].before.kindconstantYes(variant 1) Always "starting_at".
locations[].changes[].before.kindconstantYes(variant 2) Always "on_request".
locations[].changes[].optionIdsarray<string>Yes—
locations[].changes[].ruleIdstringYes—
locations[].changes[].serviceIdstringYes—
locations[].groupIdstringYes—
locations[].groupNamestringYes—
locations[].notOfferedarray<string>Yes—
locations[].problemsintegerYes—
locations[].unmappedarray<object>Yes—
locations[].unmapped[].keystringYes1–64 characters.
locations[].unmapped[].labelstringYesUp to 200 characters.
locations[].unmapped[].locationRefstring | nullYes1–128 characters.
locations[].unmapped[].refstringYes1–128 characters.
locations[].unmapped[].typestringYes1–64 characters.
recordCountintegerYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X POST "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/pricing-mapping/test" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "mapping": {
    "links": [],
    "locationMaps": [],
    "locationSettings": [],
    "maps": [],
    "overrides": [],
    "rules": [],
    "settings": {
      "apply": "review",
      "enabled": false,
      "limits": {
        "holdRemovals": true,
        "maxChangePercent": 10,
        "maxChangedCells": null
      },
      "rateDate": "today",
      "rounding": {
        "direction": "up",
        "stepCents": 5000
      },
      "schedule": {
        "hour": 2,
        "kind": "nightly"
      },
      "whenNothing": "keep"
    }
  }
}'

A connection's price sync mapping versions, newest first#

GET /v1/account/connections/{connectionId}/pricing-mapping/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

NameTypeRequiredDescription
connectionIdstring (conn_… ID)YesID (conn_…)

Response 200

FieldTypeRequiredDescription
versionsarray<object>Yes—
versions[].authorIdstring | nullYes—
versions[].createdAtstring (date-time)Yes—
versions[].notestring | nullYes—
versions[].versionintegerYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X GET "$ANSWERSTACK_API_URL/v1/account/connections/{connectionId}/pricing-mapping/versions" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The account's price source, if any, and each location's latest sync with what the CRM says for every cell#

GET /v1/account/price-sync

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

FieldTypeRequiredDescription
connectionobject | nullYes—
connection.connectorstringYes—
connection.idstringYes—
connection.namestringYes—
latestarray<PriceSyncRecord>Yes—
latest[].cellsarray<object>Yes—
latest[].cells[].centsinteger | nullYes—
latest[].cells[].optionIdsarray<string>Yes—
latest[].cells[].problemenum | nullYesOne of: "nothing_found", "not_single", "part_failed", "out_of_range".
latest[].cells[].recordsarray<string>Yes—
latest[].cells[].ruleIdstringYes—
latest[].cells[].serviceIdstringYes—
latest[].changesarray<object>Yes—
latest[].changes[].afterobject | object | nullYes—
latest[].changes[].after.centsintegerYes(variant 1) Between 1 and 99999999.
latest[].changes[].after.kindconstantYes(variant 1) Always "starting_at".
latest[].changes[].after.kindconstantYes(variant 2) Always "on_request".
latest[].changes[].beforeobject | object | nullYes—
latest[].changes[].before.centsintegerYes(variant 1) Between 1 and 99999999.
latest[].changes[].before.kindconstantYes(variant 1) Always "starting_at".
latest[].changes[].before.kindconstantYes(variant 2) Always "on_request".
latest[].changes[].optionIdsarray<string>Yes—
latest[].changes[].ruleIdstringYes—
latest[].changes[].serviceIdstringYes—
latest[].effectiveFromstring (date-time) | nullYes—
latest[].errorCodestring | nullYes—
latest[].finishedAtstring (date-time) | nullYes—
latest[].groupIdstringYes—
latest[].heldReasonstring | nullYes—
latest[].idstringYes—
latest[].mappingVersionintegerYes—
latest[].outcomeenum | nullYesOne of: "unchanged", "drafted", "published", "submitted", "failed".
latest[].priceBookVersioninteger | nullYes—
latest[].problemsintegerYes—
latest[].rateDatestringYes—
latest[].recordCountintegerYes—
latest[].startedAtstring (date-time)Yes—
latest[].triggerenumYesOne of: "schedule", "manual", "mapping_change", "scheduled_date".
latest[].unmappedintegerYes—
rateByDatebooleanYes—

Errors: 400, 401, 403, 404, 409, 429, 500, with an ErrorBody body.

Example

bash
curl -X GET "$ANSWERSTACK_API_URL/v1/account/price-sync" \
  -H "Authorization: Bearer $ACCESS_TOKEN"