Updating Marketplace Controls
This API surface is for integration partners building on top of the Rokt network. Rokt ecommerce partners integrating placements on their own checkout should use the Rokt Ecommerce developer docs instead.
This recipe covers ongoing edits to marketplace controls on an already-onboarded merchant.
Verticals merge; domains replace. Send only the verticals whose policy you are changing; the rest keep their stored policy. To unblock a vertical, send it with policy: "Allow" — omitting it does nothing. domains is different: send the full list every time, because anything you omit is removed. See Update Semantics.
- GET the current state
Do this unless you know the merchant has no domain rules. Verticals merge, so you do not need the current vertical list, but
domainsreplaces and omitting it clears whatever is stored.curl https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
-H "Authorization: Bearer $TOKEN" \
-H "X-Platform-Parent-Account-Id: $PARENT"{
"status": 200,
"error": null,
"message": "ok",
"request_id": "0e3a1b9c-...",
"data": {
"account_id": "<your-account-id>",
"marketplace_controls_list": {
"marketplace_controls_list_id": "8c6f2a1e-...",
"domains": [ { "domain": "competitor.example.com", "policy": "Block" } ],
"content_hash": "v7-1a9e3f4c"
},
"translated_verticals": [
{ "vertical_id": 1610, "policy": "Block", "position_1_policy": "Block" },
{ "vertical_id": 1611, "policy": "Allow", "position_1_policy": "Allow" }
]
}
}translated_verticalscarries the effective policy for every sub-vertical mapped in your taxonomy;vertical_idis your sub-vertical ID, not a Rokt ID. - Build the request body
Include only the verticals you are changing. Include the full domain list if you are touching domains at all.
- javascript
- python
const envelope = await getMcl(accountId); // the GET above
const current = envelope.data; // unwrap the envelope
const next = {
name: "Acme Network Controls",
// Only the vertical being changed. Everything else keeps its stored policy.
blockedVerticals: [
{ partnerVerticalId: 1500, partnerSubVerticalId: 1612, policy: "Block", position1Policy: "Block" },
],
// Domains replace, so send the full list from the GET.
domains: current.marketplace_controls_list.domains,
};envelope = get_mcl(account_id) # the GET above
current = envelope["data"] # unwrap the envelope
next_body = {
"name": "Acme Network Controls",
# Only the vertical being changed. Everything else keeps its stored policy.
"blockedVerticals": [
{
"partnerVerticalId": 1500,
"partnerSubVerticalId": 1612,
"policy": "Block",
"position1Policy": "Block",
}
],
# Domains replace, so send the full list from the GET.
"domains": current["marketplace_controls_list"]["domains"],
}To unblock instead, send the same entry with
policy: "Allow". - PUT the change
curl -X PUT https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
-H "Authorization: Bearer $TOKEN" \
-H "X-Platform-Parent-Account-Id: $PARENT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d @next.json - Optionally dry-run first
Append
?dry_run=trueto validate the payload (full validation and taxonomy translation) without committing. No state is persisted.curl -X PUT 'https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists?dry_run=true' \
-H "Authorization: Bearer $TOKEN" \
-H "X-Platform-Parent-Account-Id: $PARENT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d @next.jsonWhen you re-call without
dry_runfor the real write, use a fresh Idempotency-Key. The dry-run key is now cached. See Dry-Run Mode. - Verify
GET again and confirm the change landed, your previous blocks are still there, and
domainsis what you expect.curl https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
-H "Authorization: Bearer $TOKEN" \
-H "X-Platform-Parent-Account-Id: $PARENT"
Common gotchasDirect link to Common gotchas
I sent a vertical with policy Allow and nothing happened
Check the pair. A vertical is identified by {partnerVerticalId, partnerSubVerticalId} together, and the merge is keyed on the sub-vertical. If the sub-vertical ID doesn't match the one that is currently blocked, you have added an Allow for a different vertical rather than lifting the block you meant.
GET .../marketplacecontrolslists returns translated_verticals with the sub-vertical IDs currently in effect, as vertical_id. Use those as your partnerSubVerticalId. That call does not return the parent partnerVerticalId, so take it from your own taxonomy or from GET /v1/partnership/vertical-mappings.
I only changed verticals and my domain blocks disappeared
Domains replace. Omitting domains from the body is the same as sending [], which clears the list. Always carry the current domains array through from your GET, even on a vertical-only change.
I want to lift several blocks at once
There is no bulk clear. blockedVerticals: [] is a no-op, not a reset. Send one Allow entry per vertical.
It takes two GETs to assemble that list, because each PUT entry needs partnerVerticalId and partnerSubVerticalId while the controls GET only gives you the sub-vertical:
GET .../marketplacecontrolslistsand collect everytranslated_verticalsentry whosepolicyisBlock. Eachvertical_idis apartnerSubVerticalId.GET /v1/partnership/vertical-mappings?parent_account_id=<your-parent>and join onpartner_sub_vertical_idto recover eachpartner_vertical_id.- PUT one entry per vertical with both IDs,
policy: "Allow"andposition1Policy: "Allow".
If you already hold your own parent-to-sub taxonomy, skip step 2 and use it directly.
PUT returns 503 ServiceUnavailable
{
"status": 503,
"error": "ServiceUnavailable",
"message": "Internal error. Contact support with your request_id.",
"request_id": "0e3a1b9c-..."
}
One cause is specific to controls: the server could not read the merchant's stored policy, so it rejected the write rather than overwrite it from an incomplete picture. Nothing was changed. The response body is deliberately generic on any 5xx, so it will not tell you which cause applied.
Retry with the same Idempotency-Key; a 503 is classified transient and will re-execute, up to three retries per key. Beyond that the cached failure is replayed for the rest of the 24-hour window, so a further attempt needs a fresh key. If it persists, contact smb-partnerships@rokt.com with the request_id.
Server returns 400: 'No vertical mapping found for the following partner vertical(s)'
One or more of your partnerVerticalId / partnerSubVerticalId pairs isn't in Rokt's vertical mapping table. The PUT is rejected atomically: no partial writes.
The message names every unmapped pair, so you can fix them in one pass:
No vertical mapping found for the following partner vertical(s):
(partner_vertical_id=1500, partner_sub_vertical_id=1610). Call GET
/v1/partnership/vertical-mappings to see which verticals are currently
mapped, and contact smb-partnerships@rokt.com to request additions. The
MCL write was rejected atomically; no partial update was applied.
Resolution: call GET /v1/partnership/vertical-mappings?parent_account_id=<your-parent> to see the current set (see Check what's mapped), then email smb-partnerships@rokt.com with the unmapped IDs and we'll add the rows. Meanwhile, omit the unmapped verticals from your PUT.