Skip to main content

Update Semantics

Audience

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.

Controls updates are not uniform. blockedVerticals merges onto the merchant's stored vertical policy, while domains and status replace in full. Getting that split wrong is the most common integration bug we see. Read this page before you touch putMarketplaceControls or putPartnershipStatus.

warning

Verticals merge; domains replace. A vertical you omit keeps the policy it already has. A domain you omit is removed. To unblock a vertical, send it explicitly with policy: "Allow" — omitting it does nothing.

What merges and what replacesDirect link to What merges and what replaces

FieldBehaviourOmitting an entry means
blockedVerticalsMergeLeave that vertical's stored policy alone
domainsReplaceRemove that domain from the list
status (Status route)Replacen/a, the field is a single value

blockedVerticals is an override list, not a desired-state list. The server starts from the merchant's stored policy for every sub-vertical and applies your entries on top. Anything you don't mention is untouched.

domains is a desired-state list. The server reconciles the stored domain list to exactly what you sent.

Blocking and unblocking verticalsDirect link to Blocking and unblocking verticals

A merchant currently has verticals 1500 and 1502 blocked. The partner wants to add a block on 1504.

{
"name": "Acme Network Controls",
"blockedVerticals": [
{
"partnerVerticalId": 1504,
"partnerSubVerticalId": 1612,
"policy": "Block",
"position1Policy": "Block"
}
]
}

1500 and 1502 keep their blocks because you didn't mention them, so you do not need to fetch and re-send the vertical list.

danger

But you still have to carry domains. Omitting the field clears every stored domain rule, so a vertical-only body like the one above wipes a merchant's competitor blocks. Either include the current domains array from a GET, or only skip the GET when you know the merchant has none.

To unblock 1500, say so explicitly:

{
"name": "Acme Network Controls",
"blockedVerticals": [
{
"partnerVerticalId": 1500,
"partnerSubVerticalId": 1610,
"policy": "Allow",
"position1Policy": "Allow"
}
]
}
note

Both policy fields are required on every entry. policy covers all offer positions; position1Policy covers the first, most valuable slot. Send the pair explicitly on every entry; omitting either returns a 422.

Nothing is inferred on your behalf. Your merchant-facing dashboard already renders both switches with a concrete value for each, so both values are already in hand at the point you build the request, and sending them removes any question about what a partial entry meant. It also lets you express a partial restriction, such as policy: "Allow" with position1Policy: "Block" to keep a category out of the top slot only.

note

There is no "clear every block" operation. Sending blockedVerticals: [] is a no-op for verticals, not a reset. To lift several blocks at once, send one Allow entry per vertical you want opened up.

Building that list takes two calls, because a PUT entry needs both partnerVerticalId and partnerSubVerticalId and the controls GET only returns the sub-vertical. GET the current state to find which sub-verticals are Block, then look each one up in GET /v1/partnership/vertical-mappings to recover its parent partner_vertical_id.

Domains still replaceDirect link to Domains still replace

This is where the read-modify-write discipline still applies.

A merchant has competitor.example.com blocked. The partner wants to add competitor-two.example.com.

{
"name": "Acme Network Controls",
"domains": [
{ "domain": "competitor-two.example.com", "policy": "Block" }
]
}

wrong.json removes the block on competitor.example.com. The server replaces the domain list with what you sent. There is no error and no warning.

Omitting domains entirely from the request body has the same effect as sending []: the stored list is replaced with an empty one. If you are only changing verticals, send the merchant's current domains array back unchanged.

Status replaces tooDirect link to Status replaces too

PUT status=paused pauses every non-archived page variant on the account. There is no "pause only variant X"; per-variant control is not in the Partnerships API surface today.

contentHashDirect link to contenthash

Every GET response includes marketplace_controls_list.content_hash. You can pass it back as the contentHash field of your PUT.

warning

contentHash is advisory today, not enforced. A stale hash is logged server-side and the write still proceeds. Do not rely on it to detect concurrent edits, and do not expect a 409. If two writers can touch the same merchant, serialise them on your side.

We intend to enforce it. This page will be updated when that lands.

Walkthrough: add a domain blockDirect link to Walkthrough: add a domain block

  1. GET the current MCL state
    curl https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
    -H "Authorization: Bearer $ROKT_TOKEN"

    Response data (abbreviated):

    {
    "marketplace_controls_list": {
    "domains": [
    { "domain": "competitor.example.com", "policy": "Block" }
    ],
    "content_hash": "h_abc123"
    },
    "translated_verticals": [
    { "vertical_id": 1610, "policy": "Block", "position_1_policy": "Block" }
    ]
    }

    vertical_id here is your sub-vertical ID, not a Rokt ID. It corresponds to partnerSubVerticalId on a PUT. The parent partnerVerticalId is not returned by this call; get it from GET /v1/partnership/vertical-mappings.

  2. Append the new domain locally

    Add { "domain": "competitor-two.example.com", "policy": "Block" } to the domains array from the GET. Keep the existing entries.

  3. PUT with the full domain list
    curl -X PUT https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
    -H "Authorization: Bearer $ROKT_TOKEN" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{
    "name": "Acme Network Controls",
    "domains": [
    {"domain": "competitor.example.com", "policy": "Block"},
    {"domain": "competitor-two.example.com", "policy": "Block"}
    ]
    }'

    Both domains are now blocked. The vertical block on 1610 is preserved automatically, because verticals merge and you didn't mention it.

Was this article helpful?