Wheel Embed and API
Embed the wheel iframe, receive spin results through postMessage, and use service.wheel client credentials to create, update, and spin wheels.
Local portal docs
The wheel service can be used as an iframe or as a backend API. Use iframe embeds for interactive wheels and the service API for creating wheels, importing entries, adding giveaway participants, and running persisted spins from your own backend.
Embed URLs
TCM pages mount the wheel microapp below /wheelapp:
https://www.thecrimsonmarket.com/wheelapp/wheelofgiveaways?listName=summer-draw
https://www.thecrimsonmarket.com/wheelapp/customwheel?listName=creator-picks
https://www.thecrimsonmarket.com/wheelapp/crimsonwheel?wheel_type=member
https://www.thecrimsonmarket.com/wheelapp/pcgiveaway?chromeless=true&wheel_type=tierExternal domains can iframe the deployed wheel URL directly. Pass your exact parent origin:
<iframe
src="https://www.thecrimsonmarket.com/wheelapp/customwheel?listName=demo&parentOrigin=https%3A%2F%2Fpartner.example"
title="Wheel"
></iframe>Result events
Listen for TCM_WHEEL_SPIN_COMPLETE and validate event.origin before trusting the payload.
window.addEventListener("message", (event) => {
if (event.origin !== "https://www.thecrimsonmarket.com") return;
if (event.data?.type !== "TCM_WHEEL_SPIN_COMPLETE") return;
const { result, context } = event.data;
console.log(result.winner, context.listName, context.drawSlug);
});The iframe also posts IFRAME_HEIGHT for responsive host resizing and UPDATE_URL_BAR_ONLY when a share/open action should update the parent route.
Important URL params
listName,wheel,wheelName- the wheel slug to load or create.mode- host-specific mode such asgiveaway,custom, orpcgiveaway-prize-tier.parentOrigin- exact iframe parent origin for cross-domainpostMessage.host_parent_path,parentPath- route used when building share links.brand_title,branding_title,title- displayed wheel title.brand_logo,brandingLogoSrc,logo- logo URL or data image.brand_logo_placement,brandingLogoPlacement-behindorcenter.brand_colors,branding_colors,colorPalette- comma-separated hex palette.draw_slug,drawSlug,draw,slug- draw-room slug preserved in result context.wheel_type,wheelType- draw wheel category such astierormember.chromeless,show_title,show_description,show_join_cta,show_spin,show_volume- embed display controls.transparent_background=true,transparent=true, orbackground=transparent- makes the iframe document background transparent so only the wheel and controls render.random_initial_rotation,visual_treatment,spin_duration,single_spin- wheel rendering and spin controls.data_source=parent- tells PC/member iframes to wait for host-supplied data overpostMessage.
Parent-supplied data
For hosted draw pages, send the same data snapshot the parent will use to save the result:
iframe.contentWindow.postMessage({
type: "TCM_WHEEL_MEMBER_SEGMENTS_SYNC",
participants: [
{ name: "Alice", userId: "user-1", weight: 100, karma: 5 }
]
}, "https://www.thecrimsonmarket.com");
iframe.contentWindow.postMessage({
type: "TCM_WHEEL_PC_CONFIG_SYNC",
config: { tiers: [{ name: "CRIMSON", weight: 10, color: "#DC2626" }] }
}, "https://www.thecrimsonmarket.com");API credentials
Create a machine-to-machine service client and request audience service.wheel. Grant only the scopes your integration needs:
wheel:read- read wheel state and results.wheel:write- create wheels, update entries/settings/branding, and add participants.wheel:spin- run persisted wheel spins.
Mint a token:
curl -u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials \
-d resource=service.wheel \
-d scope="wheel:read wheel:write wheel:spin" \
https://www.thecrimsonmarket.com/mana/oauth/tokenAPI endpoints
All endpoints require Authorization: Bearer <access_token> where the token has aud=service.wheel.
| Endpoint | Scope | Use | | --- | --- | --- | | POST /wheelapp/api/v1/wheels | wheel:write | Create or update a wheel with listName, entries, and settings. | | GET /wheelapp/api/v1/wheels/{listName} | wheel:read | Read participants, custom entries, settings, and last draw result. | | PUT /wheelapp/api/v1/wheels/{listName} | wheel:write | Replace custom entries or update settings/branding. | | POST /wheelapp/api/v1/wheels/{listName} | wheel:write | Add a giveaway participant with duplicate, fingerprint, VPN, and jail rules. | | PUT /wheelapp/api/v1/wheels/{listName}/entries | wheel:write | Replace all custom entries. | | POST /wheelapp/api/v1/wheels/{listName}/entries | wheel:write | Append custom entries. | | POST /wheelapp/api/v1/wheels/{listName}/spin | wheel:spin | Spin a custom or participant wheel and persist the result. |
Example import and spin
curl -X PUT https://www.thecrimsonmarket.com/wheelapp/api/v1/wheels/demo/entries \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"entries": [
{ "name": "Alice", "weight": 1, "color": "#E11D48" },
{ "name": "Bob", "weight": 2, "color": "#2563EB" }
],
"settings": {
"spinDurationSeconds": 30,
"colorPalette": ["#B60100", "#111111", "#E7E7E7"]
}
}'
curl -X POST https://www.thecrimsonmarket.com/wheelapp/api/v1/wheels/demo/spin \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "type": "custom" }'