Raidstrats.gg Developers Embed API
Support policy. We do not offer help setting up or integrating this embed on your site. Only basic API or embed bugs are in scope. If you believe you have one, open a ticket on the Raidstrats.gg Discord.

Embed raid plans anywhere

Drop a Raidstrats.gg plan into any web page with an iframe. Pre-set the roster with URL parameters, then drive runtime updates, highlights, index badges, and spell badges via postMessage.

No auth required Iframe embeddable Live postMessage API

Quickstart #

Minimal iframe setup. Pre-fill the roster via URL parameters and listen for the ready event.

HTML
<iframe
  id="raidplanEmbed"
  src="https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID&animation=true&hidetrails=true"
  width="100%"
  height="600"
  frameborder="0">
</iframe>
JavaScript
const iframe = document.getElementById('raidplanEmbed');

// Listen for the embed to tell us which slots it has
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://raidstrats.gg') return;
  if (event.data.type === 'playerNamesLoaded') {
    console.log('Slots:', event.data.slots);
  }
  if (event.data.type === 'embedEditSaved') {
    document.getElementById('savedPlanId').value = event.data.planId;
    iframe.src = event.data.embedUrl;
  }
});

// Send a runtime update
iframe.contentWindow.postMessage({
  type: 'updatePlayers',
  players: {
    'index1': { name: 'Alice', class: 'Mage' }
  }
}, 'https://raidstrats.gg');

Index slots #

Every controllable token on the plan has a numeric embed index (set in the planner's properties panel). All messages target slots by indexKey (index1, index2, ...). This keeps targeting stable even when names change or duplicate names exist.

Rule of thumb: Always target by indexKey. Name-based targeting is supported for legacy flows but is ambiguous.

URL parameters #

Append to the iframe URL to configure initial state.

embedrequired, boolean
Must be true to enable embed mode.
idrequired, uuid
Your plan's UUID.
animationboolean
Show the animation play controls. Default false.
hidetrailsboolean
Hide animation path trails. Default false.
showScenesboolean
Show scene tabs. Default true.
sceneinteger
Open on a specific scene number (1-based). Example: scene=3. Out-of-range values are clamped.
namesstring list
Comma-separated names mapped by embed index (index1 → first name, …). Global multi-index: 7,18:Bob. Scene-specific (1-based scene number): 5/7:Bob or 7/18:Bob. Scene entries override global ones on that scene.
playersstring list
Positional: Alice|Mage,Bob|Warrior. Global multi-index: 7,18:Bob|Shaman (every scene). Scene-specific: 5/7:Bob|Shaman,7/18:Bob|Shaman when the same raider uses different embed indexes on different scenes — or when index 7 and 18 both appear on one scene as different people. Mix all forms in one URL.
maxCharactersinteger
Truncate all names to this length.
circleModeboolean
Render players as class rings instead of class/spec icons.
editModeboolean
Allow end users to move objects only (no add/delete/resize) and save. On save the embed posts embedEditSaved to the parent with the new plan link. Saving requires a logged-in Raidstrats account. Default false.
returnUrlstring (URL)
Used with editMode=true. When a guest tries to save, they are sent to /login on Raidstrats and returned here after login. If omitted, the embed uses document.referrer when it points to another site.

URL examples #

Start on scene 3
https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID
  &scene=3
Names only
https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID
  &names=Alice,Bob,Charlie,Dave,Eve
Name + class
https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID
  &players=Alice|Warrior,Bob|Mage,Charlie|Priest,Dave|Paladin
Same player, different indexes on different scenes
https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID
  &players=Catwo|Druid,...,5/7:Bob|Shaman,7/18:Bob|Shaman
// scene 5 index7 and scene 7 index18 both show Bob; other scenes unaffected
Index 7 and 18 on the same scene (different people)
https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID
  &players=Catwo|Druid,...,7/7:Alice|Mage,7/18:Bob|Shaman
// on scene 7 only: index7 = Alice, index18 = Bob
Class rings
https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID
  &players=Nairy|Priest,Bob|Mage&circleMode=true
Move-only edit mode
https://raidstrats.gg/planner?embed=true&id=YOUR_PLAN_ID
  &editMode=true&returnUrl=https://your-site.com/raid-page

Listen to events #

The embed posts messages back to the parent window. Always verify event.origin.

EVENT

playerNamesLoaded

Sent once the plan finishes loading. Contains planId, planName, names, and slots.

EVENT

animationStarted

Fires when embed animation playback starts.

EVENT

animationStopped

Fires when embed animation playback stops.

EVENT

assignSpellToIndexResult

Response to assignSpellToIndex. Single slot: ok, indexKey, spellId. Batch: batch: true and results[] per slot. Includes requestId when provided.

EVENT

embedSceneChanged

Fires after a scene switch. Includes sceneIndex and requestRuntimeReplay.

EVENT

embedEditSaved

Sent when a user saves in editMode=true. Includes planId, planName, plannerUrl, and embedUrl.

EVENT

embedEditSaveFailed

Sent when save fails in edit mode. Includes error.

EVENT

embedEditLoginRequired

Sent when a guest clicks Save. Includes loginUrl, returnUrl, and usePopup: true. A centered login popup opens; after login it closes and save can be retried automatically.

EVENT

embedEditLoginComplete

Sent to the parent page when popup login succeeds.

EVENT

embedAddonExportData

Response payload for addon export requests. Includes ok, planId, planName, and addonData (or error when failed).

Edit mode save — capture the plan ID #

When a logged-in user clicks Save in editMode=true, the iframe posts embedEditSaved to your page. Use event.data.planId to read the saved plan — store it in a form field, your CMS, or local state.

When does planId change?
  • Same ID — the logged-in user owns the plan and it was updated in place.
  • New ID — the user forked a copy (they were not the owner, or the source plan had no owner). Your page should persist the new planId if you want later loads to use the saved layout.
HTML — iframe + field for your CMS
<iframe
  id="raidplanEmbed"
  src="https://raidstrats.gg/planner?embed=true&id=ORIGINAL_PLAN_ID&editMode=true&returnUrl=https://your-site.com/raid-page"
  width="100%"
  height="600"
  frameborder="0">
</iframe>

<!-- Example: hidden input your CMS or backend reads -->
<input type="hidden" id="savedPlanId" name="raidstrats_plan_id" value="ORIGINAL_PLAN_ID">
JavaScript — listen and store the new plan ID
const iframe = document.getElementById('raidplanEmbed');
const planIdField = document.getElementById('savedPlanId');
const EMBED_ORIGIN = 'https://raidstrats.gg';

window.addEventListener('message', (event) => {
  if (event.origin !== EMBED_ORIGIN) return;
  if (!event.data || event.data.type !== 'embedEditSaved') return;

  const { planId, embedUrl, plannerUrl } = event.data;
  const previousId = planIdField.value;

  // Persist for your CMS, API, or page state
  planIdField.value = planId;

  // Optional: reload iframe so the embed uses the saved plan URL
  iframe.src = embedUrl;

  if (planId !== previousId) {
    console.log('User forked a new plan:', planId, plannerUrl);
    // e.g. PATCH your backend: { raidstrats_plan_id: planId }
  } else {
    console.log('Owner updated plan in place:', planId);
  }
});
planIdstring
UUID of the saved plan. Use this in your database or CMS field.
embedUrlstring
Full iframe src with the saved id= and your existing embed params (including editMode).
plannerUrlstring
Link to open the plan on raidstrats.gg.
sceneIndexnumber
Zero-based scene index that was active when the user saved.

Update names #

POSTupdatePlayerName

indexKeystring, recommended
Slot identifier, e.g. 'index1'.
newNamerequired, string
New display name. Truncated by maxCharacters.
oldNamestring, legacy
Exact current name (fallback when indexKey isn't available).
Request
iframe.contentWindow.postMessage({
  type: 'updatePlayerName',
  indexKey: 'index1',
  newName: 'Nairyana'
}, 'https://raidstrats.gg');

Update classes #

POSTupdatePlayerClass

indexKeystring, recommended
Target slot id.
newClassrequired, string or null
Class name (Warrior, Mage, Death Knight, ...). Use null to clear runtime override and restore that slot's baseline visual from load (class/spec/role).
newNamestring, optional
Rename the slot in the same call.
If circleMode=true is on the iframe URL, class updates render as rings. Otherwise they render as class/spec icons. Baseline resets (newClass: null) persist across scene switches for that indexKey and restore non-class role visuals too (for example DPS/Tank icons).
Request
iframe.contentWindow.postMessage({
  type: 'updatePlayerClass',
  indexKey: 'index1',
  newClass: 'Priest'
}, 'https://raidstrats.gg');
Reset to baseline class
iframe.contentWindow.postMessage({
  type: 'updatePlayerClass',
  indexKey: 'index1',
  newClass: null
}, 'https://raidstrats.gg');

Batch updates #

POSTupdatePlayers

Update name and/or class for many slots in a single message. Set class: null for a slot to reset its class back to baseline.

Request
iframe.contentWindow.postMessage({
  type: 'updatePlayers',
  players: {
    'index1': { name: 'Alice', class: 'Mage' },
    'index2': { name: 'Bob',   class: 'Warrior' },
    'index3': { name: 'Chad' }
  }
}, 'https://raidstrats.gg');
Cross-scene reliability: Keep an authoritative playersMap in the parent and re-send it when the embed emits embedSceneChanged. This ensures off-scene slots stay synchronized even if scene assets hydrate late.
Recommended listener
const ORIGIN = 'https://raidstrats.gg';
const playersMap = {
  'index1': { name: 'Alice', class: 'Mage' },
  'index2': { name: 'Bob' }
};

window.addEventListener('message', (event) => {
  if (event.origin !== ORIGIN) return;
  const data = event.data || {};

  if (data.type === 'embedSceneChanged' && data.requestRuntimeReplay) {
    iframe.contentWindow.postMessage({
      type: 'updatePlayers',
      players: playersMap
    }, ORIGIN);
  }
});

Highlight players #

POSThighlightPlayers

Dim all other players and apply a salmon glow to the targeted indices. Persists across scene switches until cleared with an empty array.

indicesnumber or number[]
1-based index or array of indices. [] clears all highlights.
Examples
// Single index
iframe.contentWindow.postMessage({ type: 'highlightPlayers', indices: 2 }, '*');

// Multiple
iframe.contentWindow.postMessage({ type: 'highlightPlayers', indices: [1, 3, 5] }, '*');

// Clear
iframe.contentWindow.postMessage({ type: 'highlightPlayers', indices: [] }, '*');

Index badges #

POSTtoggleIndexNumbers

Show or hide numeric index badges on player slots (for example 1, 2, 3). State persists across scene switches until changed again.

showboolean
Preferred flag. true shows badges, false hides badges.
visibleboolean, alias
Alias for show.
enabledboolean, alias
Alias for show.
Show index badges
iframe.contentWindow.postMessage({
  type: 'toggleIndexNumbers',
  show: true
}, 'https://raidstrats.gg');
Hide index badges
iframe.contentWindow.postMessage({
  type: 'toggleIndexNumbers',
  show: false
}, 'https://raidstrats.gg');

Spell badges #

POSTassignSpellToIndex

Attach Wowhead-backed spell icons to player slots. Badges have full Wowhead tooltips and persist across scene switches. Use a batch payload when applying the same spell to many slots — one message, one canvas update (avoids flicker).

indexKeystring
Single-slot target (e.g. index1). Alias: slotKey.
indexKeysstring[]
Batch: many slots with one shared spellId. Alias: slotKeys.
indicesnumber[] | string
Batch shorthand: [1,2,3]index1, index2, … or comma-separated "1,2,3".
assignmentsobject[]
Batch with per-slot options: [{ indexKey, spellId }, { indexKey, spellId, scale }, { indexKey, clear: true }].
spellIdinteger
WoW spell id. Shared by all entries in indexKeys / indices. Use 0 or null to clear. Aliases: spell_id, spellid.
clearboolean
Same as spellId: 0. For batch clear, use assignments: [{ indexKey, clear: true }, …].
scalenumber
Icon size ratio relative to the token. Default 0.5. Overridable per entry in assignments.
anchorobject
Offset from token center. Default { x: 0, y: -0.5 } (top center).
requestIdstring
Echoed in assignSpellToIndexResult for correlation.
Assign one slot
iframe.contentWindow.postMessage({
  type: 'assignSpellToIndex',
  indexKey: 'index1',
  spellId: 73920,
  scale: 0.5
}, 'https://raidstrats.gg');
Same spell on many slots (recommended)
iframe.contentWindow.postMessage({
  type: 'assignSpellToIndex',
  requestId: 'raid-w1-heroic',
  indexKeys: ['index1', 'index2', 'index3', 'index4', 'index5', 'index6'],
  spellId: 451832,
  scale: 0.5
}, 'https://raidstrats.gg');

// Or numeric indices:
iframe.contentWindow.postMessage({
  type: 'assignSpellToIndex',
  indices: [1, 2, 3, 4, 5, 6],
  spellId: 451832
}, 'https://raidstrats.gg');
Different spell per slot
iframe.contentWindow.postMessage({
  type: 'assignSpellToIndex',
  requestId: 'assignments-demo',
  assignments: [
    { indexKey: 'index1', spellId: 451832 },
    { indexKey: 'index2', spellId: 451832 },
    { indexKey: 'index3', spellId: 123456 }
  ]
}, 'https://raidstrats.gg');
Clear one or many slots
// One slot
iframe.contentWindow.postMessage({
  type: 'assignSpellToIndex',
  indexKey: 'index1',
  spellId: 0
}, 'https://raidstrats.gg');

// Many slots
iframe.contentWindow.postMessage({
  type: 'assignSpellToIndex',
  assignments: [
    { indexKey: 'index1', clear: true },
    { indexKey: 'index2', clear: true }
  ]
}, 'https://raidstrats.gg');
Batch result (embed → parent)
{
  type: 'assignSpellToIndexResult',
  requestId: 'raid-w1-heroic',
  ok: true,
  batch: true,
  results: [
    { indexKey: 'index1', ok: true, spellId: 451832 },
    { indexKey: 'index2', ok: true, spellId: 451832 }
  ]
}

Animation #

Control embed animation playback. Requires animation=true on the iframe URL.

POST

startAnimation

Begin playback of the current scene's animation.

POST

stopAnimation

Stop playback and reset to frame 0.

Addon export (embed) #

Request addon payload directly from the embed via postMessage. The response includes both plan metadata and the generated addon export string.

requestAddonExportparent → embed
Request export payload. Optional requestId is echoed in the response.
embedAddonExportDataembed → parent
Response event. Includes ok, planId, planName, addonData, requestId, and sceneIndex. On failure, ok=false and error is set.
JavaScript - request + receive addon export
const iframe = document.getElementById('raidplanEmbed');
const ORIGIN = 'https://raidstrats.gg';

window.addEventListener('message', (event) => {
  if (event.origin !== ORIGIN) return;
  const data = event.data || {};
  if (data.type !== 'embedAddonExportData') return;

  if (!data.ok) {
    console.error('Addon export failed:', data.error);
    return;
  }

  console.log('Plan meta:', data.planId, data.planName);
  console.log('Addon payload:', data.addonData);
});

iframe.contentWindow.postMessage({
  type: 'requestAddonExport',
  requestId: 'cms-export-1'
}, ORIGIN);

Addon export (REST API) #

Fetch a plan's in-game addon import string with a simple authenticated GET. Requires a Bearer API key. Contact Raidstrats on Discord to request one. Guild plans are blocked.

GET /api/plans/:id/addon-exportREST
Returns the cached !raidstrats-addon-… string for one non-guild plan.
POST /api/plans/addon-exportREST
Batch version. Body: { "planIds": ["uuid1", "uuid2"] } (max 50). Returns a results[] array with per-plan success/error.
Authorizationheader
Bearer <api_key> (required).
The export string is generated when a plan is saved on raidstrats.gg. If a plan has never been saved since this feature shipped, the API returns 404 with code: "addon_export_missing" until someone re-saves it.

Success response

JSON
{
  "ok": true,
  "planId": "3d7b347e-6aa4-46c4-b397-df4127b2b6d2",
  "planName": "Mythic soak positions",
  "addonExport": "!raidstrats-addon-…"
}

Example

cURL
curl -s \
  -H "Authorization: Bearer rsgg_your_api_key_here" \
  "https://raidstrats.gg/api/plans/PLAN_ID/addon-export"
JavaScript - fetch (single)
const res = await fetch(
  `https://raidstrats.gg/api/plans/${planId}/addon-export`,
  {
    headers: {
      Authorization: `Bearer ${apiKey}`
    }
  }
);

const data = await res.json();
if (!res.ok) {
  throw new Error(data.error || 'Addon export failed');
}

console.log(data.planName, data.addonExport);
JavaScript - fetch (batch)
const res = await fetch('https://raidstrats.gg/api/plans/addon-export', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ planIds: ['uuid-1', 'uuid-2'] })
});

const data = await res.json();
// data.results = [{ ok, planId, planName, addonExport } | { ok:false, code, error }, ...]
for (const row of data.results || []) {
  if (row.ok) console.log(row.planName, row.addonExport);
  else console.warn(row.planId, row.code, row.error);
}

Error codes

401
Missing, invalid, or revoked API key.
403
Single GET only: plan is a guild plan. Batch returns code: "guild_plan" per item instead.
404
Single GET only: plan not found, or export missing (addon_export_missing). Batch returns those as per-item failures.
400
Batch body missing / empty planIds.

Message types #

Complete reference of every supported message type.

Parent to embed

updatePlayerName
Rename one slot.
updatePlayerNames
Bulk rename. names: { index1: 'Alice', ... }
updatePlayerClass
Update one class visual (or reset with newClass: null).
updatePlayerClasses
Bulk class update (null resets per slot).
updatePlayers
Bulk name + class in one call (class: null resets).
highlightPlayers
Focus by index. [] clears.
toggleIndexNumbers
Show / hide index badges on player slots.
assignSpellToIndex
Add / remove spell badges. Single slot (indexKey) or batch (indexKeys, indices, assignments).
requestAddonExport
Request addon payload and plan metadata from the embed.
startAnimation
Begin playback.
stopAnimation
Stop playback.

Embed to parent

playerNamesLoaded
Sent after initial load. Includes planId, planName, names, and slots.
animationStarted
Animation playback started.
animationStopped
Animation playback stopped.
assignSpellToIndexResult
Result of badge apply/clear. Batch responses include batch: true and results[].
embedSceneChanged
Scene switched. Includes sceneIndex and requestRuntimeReplay: true.
embedEditSaved
User saved in edit mode. Includes planId, planName, embedUrl, plannerUrl, sceneIndex. See Edit mode save.
embedAddonExportData
Addon export response. Includes ok, planId, planName, addonData, and optional requestId/sceneIndex. On failure includes error.
embedEditSaveFailed
Save failed in edit mode. Includes error.

Security #

Always validate event.origin === 'https://raidstrats.gg' in your message listener before trusting payloads.
  • Prefer indexKey targeting over fragile name matching.
  • Only post messages after the iframe has loaded.
  • encodeURIComponent user-provided values when composing URL parameters.
  • Handle embed load failures gracefully. Do not block on playerNamesLoaded.