Update Alternate Purchase Path
Patch an alternate purchase path. Purchasability is re-checked only when the target changes.
Patches one live alternate purchase path. Every field is optional. Omitted fields keep their stored values.
Purchasability is re-checked only when the resolved target actually changes
(targetType, targetId, or targetUrl). A label-only edit of an entry whose target
has since become unpublished or unpriced still succeeds — the learner-facing read
already suppresses that CTA. Sending the unchanged target again on a full-form save
does not count as a change.
label is sanitized on write the same way as
Create alternate purchase path.
https://example.thoughtindustries.com/v3/admin/content/:contentId/alternate-purchase-paths/:entryIdThis endpoint is served by the v3 API. Its full path is
https://{instance}.thoughtindustries.com/v3/admin/content/{contentId}/alternate-purchase-paths/{entryId}, not the/incoming/v2base URL used by the rest of this reference. Use the full URL shown in the examples below.
Example request
curl -X PATCH "https://{instance}.thoughtindustries.com/v3/admin/content/3a131ac3-1a74-420d-b4da-ae10b18b2c68/alternate-purchase-paths/443d8182-d461-4568-a777-918ca729fd85" \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"label": "Join the annual subscription",
"hidePrimaryCta": true
}'Parameters
Requires the settings.alternatePurchasePaths permission. A company API key satisfies this.
| Name | Type | Required | Location | Description |
|---|---|---|---|---|
contentId | uuid | Yes | path | Source course UUID. |
entryId | uuid | Yes | path | Alternate purchase path UUID. |
label | string | No | body | CTA label. Maximum 2000 characters after sanitize. Empty string is rejected. |
targetType | string | No | body | ti_item or external_url. Changing type clears the opposite-kind fields. |
targetId | uuid | No | body | Required in the merged result when targetType is ti_item. |
targetUrl | url | No | body | Required in the merged result when targetType is external_url. |
targetUrlTitle | string | No | body | Required in the merged result when targetType is external_url. |
displayOrder | integer | No | body | Non-negative integer. |
hidePrimaryCta | boolean | No | body |
Example response
Note the data wrapper — v3 endpoints nest their payload under data.
{
"data": {
"id": "443d8182-d461-4568-a777-918ca729fd85",
"courseId": "3a131ac3-1a74-420d-b4da-ae10b18b2c68",
"displayOrder": 0,
"label": "Join the annual subscription",
"targetType": "ti_item",
"targetId": "7a6b5c4d-3e2f-1a0b-9c8d-7e6f5a4b3c2d",
"targetUrl": null,
"targetUrlTitle": null,
"hidePrimaryCta": true,
"createdAt": "2026-09-15T14:22:01.000Z",
"updatedAt": "2026-09-15T15:01:44.000Z"
}
}Errors
A missing, soft-deleted, cross-company, or wrong-course entryId returns 404 with
code: "RESOURCE_NOT_FOUND" — see
Get alternate purchase path.
A merged result that fails the same static or purchasability rules as create returns
400 with code: "VALIDATION_ERROR", message: "Invalid alternate purchase path",
and metadata.errors. See
Create alternate purchase path.
Malformed DTO values return 400 with code: "BAD_REQUEST" and
category: "CLIENT_ERROR". message names the field. timestamp, statusCode, and
metadata.errors are present on the same body; see
Create alternate purchase path
for the shape. A missing or invalid API key returns 401. A manager session without
settings.alternatePurchasePaths returns 403.
Rate limit
60 requests per 60 seconds, counted per instance. This limit is specific to this endpoint
and is independent of the per-family rate limits that apply to /incoming/v2 endpoints.