メインコンテンツまでスキップ

Onboarding a New Merchant

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.

This recipe walks the canonical path: from a brand-new merchant in your platform to a live, revenue-generating Rokt account. Every step is callable from your backend with an API token bearer token, the X-Platform-Parent-Account-Id header, and an Idempotency-Key.

備考

Pre-reqs: you've read Overview, Authentication, and Quickstart. You have a valid API token and your platform_parent_account_id. Every example assumes $PARENT holds that value.

  1. Register the merchant

    POST /v1/accounts/register/partnership with the merchant's brand, partner-taxonomy IDs, country, store URL, and your stable external_account_id. Capture the returned account_id from data.account_id — every subsequent call keys off it.

    Pass the optional pages array to declare which surfaces this merchant will render placements on. Each entry maps a partner-facing surface (confirmation, tracking, returns) to a layout style (Overlay or Embedded). See Pages and Layouts for the full surface vocabulary.

    curl -X POST https://accounts.rokt.com/v1/accounts/register/partnership \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Platform-Parent-Account-Id: $PARENT" \
    -H "Content-Type: application/json" \
    -d '{
    "brand": "Acme Apparel",
    "vertical_id": 1500,
    "sub_vertical_id": 1610,
    "country_code": "US",
    "platform_parent_account_id": "<your-platform-parent-account-id>",
    "store_identifier": "https://acme-apparel.example.com",
    "external_account_id": "partner-merchant-abc123",
    "pages": [
    { "surface": "confirmation", "layout_type": "Overlay" },
    { "surface": "tracking", "layout_type": "Embedded" }
    ]
    }'

    Response:

    {
    "status": 200,
    "error": null,
    "message": "ok",
    "request_id": "0e3a1b9c-...",
    "data": {
    "account_id": "<your-account-id>",
    "pages": [
    { "surface": "confirmation", "page_id": "bfb5b9be-...", "layout_id": "9d11d8aa-...", "page_identifier": "confirmation_page" },
    { "surface": "tracking", "page_id": "2b9d8a5e-...", "layout_id": "f8700369-...", "page_identifier": "tracking_page" }
    ]
    }
    }
    注記

    Registration is idempotent on external_account_id. Re-POSTing with the same external_account_id returns the same account_id — no duplicate account is created. Use this to make your onboarding retry-safe.

    警告

    store_identifier must be a valid URL between 3–400 chars and include the scheme. Send https://acme.myshopify.com, not acme.myshopify.com; the bare hostname returns a 400.

  2. Inspect default controls

    Your partnership preset seeds default marketplace controls when the account is created. Read them before customizing so you know your baseline.

    curl https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Platform-Parent-Account-Id: $PARENT"

    The MCL response payload (data.translatedVerticals) includes a list showing your partner taxonomy IDs alongside the Rokt internal IDs they map to — useful for surfacing readable category names in your UI.

  3. Customize marketplace controls (optional)

    PUT the full desired blocklist. This is SET semantics: send the complete list every time — anything you omit becomes unblocked. See SET Semantics and the Vertical Taxonomy concept page.

    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 '{
    "name": "Acme Network Controls",
    "blockedVerticals": [
    { "partnerVerticalId": 1500, "partnerSubVerticalId": 1610, "policy": "Block", "position1Policy": "Block" },
    { "partnerVerticalId": 1500, "partnerSubVerticalId": 1611, "policy": "Block", "position1Policy": "Block" }
    ],
    "domains": [
    { "domain": "competitor.example.com", "policy": "Block" }
    ],
    "contentHash": null
    }'
    ヒント

    contentHash: null is fine on first write. For subsequent updates, pass the hash from the previous GET to opt in to optimistic-concurrency checks. The end-to-end stale-hash rejection is preview-grade — verified by acceptance but not yet observed live on the partner surface. See Updating Controls.

  4. Start payout setup

    POST /v1/partnership/accounts/{account_id}/payout-setup to initiate Stripe Connect onboarding. Pick one of two shapes:

    • experience: "embedded" — render Stripe's onboarding UI inside your app. Do not include contact; server returns 400 if you do.
    • experience: "hosted_invite" — Rokt emails the merchant a link. contact.email is required.
    # Embedded — no contact block
    curl -X POST https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/payout-setup \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Platform-Parent-Account-Id: $PARENT" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(uuidgen)" \
    -d '{
    "provider": "stripe_connect",
    "experience": "embedded"
    }'

    # Hosted-invite — contact required
    curl -X POST https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/payout-setup \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Platform-Parent-Account-Id: $PARENT" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(uuidgen)" \
    -d '{
    "provider": "stripe_connect",
    "experience": "hosted_invite",
    "contact": { "email": "merchant@example.com", "name": "Acme Apparel" }
    }'

    The response carries one of two sub-shapes inside data:

    • For embedded: data.embedded.publishable_key + data.embedded.client_secret — wire these into Stripe.js to render the flow.
    • For hosted_invite: data.hosted_invite.invite_id + data.hosted_invite.email — the merchant gets the email automatically.
    警告

    Never put bank account, card, routing, SSN, IBAN, tax, PayPal, or external-account fields anywhere in the request — these field names are forbidden at any nesting level and return 400. Stripe collects those directly from the merchant.

  5. Wait for payout completion

    Poll GET /v1/partnership/accounts/{account_id}/payout-setup/status until data.payouts_enabled === true and data.details_submitted === true. Recommended cadence: every 30 seconds, give up after 7 days. Stripe onboarding is partner-driven and can take time — don't tight-loop.

    curl https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/payout-setup/status \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Platform-Parent-Account-Id: $PARENT"
    {
    "status": 200,
    "error": null,
    "message": "ok",
    "request_id": "...",
    "data": {
    "provider": "stripe_connect",
    "setup_id": "stp_...",
    "managed_account_id": "<your-account-id>",
    "manager_account_id": "<your-platform-parent-account-id>",
    "connected_account_id": "acct_...",
    "details_submitted": false,
    "payouts_enabled": false,
    "charges_enabled": false,
    "requirements_currently_due_count": 3,
    "requirements_eventually_due_count": 0,
    "requirements_past_due_count": 0,
    "disabled_reason": null,
    "updated_at": "2026-05-20T19:14:00Z"
    }
    }

    If disabled_reason is non-null or requirements_past_due_count > 0, surface that back to the merchant so they can finish.

    If your 7-day polling window expires without payouts_enabled === true, don't leave the merchant stuck. Recover with this sequence:

    1. Re-invoke POST /v1/partnership/accounts/{account_id}/payout-setup to generate a fresh onboarding session. The same merchant can have multiple sessions outstanding — only the latest one matters for completion, so older embedded client secrets or hosted_invite links can be safely abandoned. Use a new Idempotency-Key for the new session.
    2. Surface the underlying disabled_reason (from the most recent polling response's data.disabled_reason) back to the merchant verbatim so they know exactly what to fix on the Stripe side before they restart — e.g. missing tax ID, failed identity verification, unverified bank account. The Stripe-defined reason strings are stable enough to drive an in-product help message.
    3. If disabled_reason indicates a Stripe-side issue you can't surface or remediate (e.g. requires_rokt_review, under_review, or a value not documented in Stripe's Connect onboarding docs), file a support ticket. Include the X-Operation-Id from the original payout-setup response and the merchant's account_id — that's enough for Rokt operators to pull the Stripe connected-account record and unstick it.
  6. Activate the partnership

    Once payouts are complete and you're happy with controls, flip status to active. The cascade enables every non-archived page variant on the account.

    curl -X PUT https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/status \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Platform-Parent-Account-Id: $PARENT" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(uuidgen)" \
    -d '{ "status": "active" }'
  7. Verify the cascade

    Round-trip the status read to confirm every variant flipped.

    curl https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/status \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Platform-Parent-Account-Id: $PARENT"

    data.status should be "active" and every entry in data.variants[] should show "active". If you see "mixed", the cascade missed some variants — file a support ticket with your Idempotency-Key and the request_id from the response envelope.

  8. Wire the Web SDK on the merchant's pages

    The orchestrator has provisioned the account, pages, and layouts. The remaining step happens on the merchant's site: load the Rokt Web SDK once per page and call selectPlacements on each surface, passing the matching page_identifier from the registration response.

    <script type="module">
    await window.RoktLauncherScriptPromise;
    const launcher = await window.Rokt.createLauncher({
    accountId: "<account_id from registration>",
    sandbox: true
    });

    // Confirmation page:
    await launcher.selectPlacements({
    identifier: "confirmation_page", // ← from registration response's pages[].page_identifier
    attributes: { email, firstname, lastname, confirmationref, amount, currency, country }
    });
    </script>

    Embedded surfaces (Embedded layout type) need an anchor element on the page. By default the SDK looks for <div id="rokt-container"></div>. See SDK Integration for the full setup including the loader snippet, attribute coverage, and SPA notes.

Customizing the merchant's experienceCustomizing the merchant's experience への直接リンク

Registration ships every merchant with the partnership preset's default theme and surface set. Once the integration is live, two endpoints let you evolve that baseline without re-registering: the 5-token layout PATCH for visual theming, and the add-page POST for adding new surfaces (e.g. tracking after the merchant initially launched with confirmation only). Both are partner-callable, idempotent, and scoped to the same managed account — no Rokt-side intervention needed.

The merchant is live. Next:

この記事は役に立ちましたか?