Web SDK Comparison Guide

Miro Web SDK Comparison Guide: v1 -> v2

If your app currently uses the Miro Web SDK v1, it’s time to plan your migration to v2. The Miro Developer Platform 2.0 has reworked and improved the Web SDK, focusing on performance and reliability, as well as the developer experience. This document outlines the changes in certain data objects and how those objects relate to others. For a complete map of each v1 endpoint to its v2 counterpart, be sure to check out the reference guide.

Widgets / Items

In the Miro Web SDK v1, the widget endpoint was polymorphic – meaning that one endpoint was used to represent all potential widget types. The structure of the call would differ depending on what type of widget you were creating or updating. In the v2 SDK, we have replaced this with an independent constructor for each widget (now called "item") type.

The new constructors should feel familiar to you, as they were designed to mostly follow the structure of the type-specific payloads of the previous board.widgets.create() call. There are two examples below, and for a full map of v1 endpoint calls to their v2 equivalents, please see the reference guide.

v1 Create Widget callv2 Equivalent
Create an Image
  type: 'image',
  url: imgUrl,
  x: xCoordinate,
  y: yCoordinate,
Create an Image
  x: xCoordinate, 
  y: yCoordinate, 
  url: imgUrl 

Create a Shape
  type: 'shape',
  text: messageText,
  x: xCoordinate,
  y: yCoordinate,
  style: {
    textColor: '#fff',
    backgroundColor: colorHexValue,
    borderColor: 'transparent',
Create a Shape
  x: xCoordinate,
  y: yCoordinate,
  content: messageText,
  style: {
    fillColor: colorHexValue,

The sync() function

In the v2 Web SDK, we have introduced a new method for each object type –sync(). This method will refresh the content of an object without needing to refresh the entire Miro board. For example, if you are programmatically updating the description of a specific card, you would call card.sync() at the end of the update call so that the refreshed data is immediately available for a user. To learn more about the sync() function and see several examples of its usage, check out this guide.


The Miro UI has evolved significantly since the creation of the v1 Web SDK. When building the v2 SDK, we decided to rethink the way we expose extension points. The goal is to create consistency for the user experience so that all web applications feel like a natural extension of the Miro product, and all apps have an intuitive pattern.

Unfortunately, this means that some options that were available to developers in v1 are no longer available in v2, such as the bottom panel and the left sidebar. As of today, we provide developers with two options: the app panel (also known as the left panel) and the pop-up modal.

  • The app panel ("Panel") should be used for the majority of your application's interactions, and can be extended to provide multiple views for the user, depending on the context of your app.
  • The pop-up modal ("Modal") steals the focus of the browser window, and should be used for more visually-intensive user interactions (such as scrolling through their third-party data, or configuring settings and customizations, etc.).

If you have a use case that relies on certain extension points, we'd like to hear about it. There are several feature requests already noted on our roadmap, and we encourage you to add your votes and subscribe to future updates. You’re also welcome to raise any questions or concerns in our developer Discord or on our community forum.

Additional changes

Several changes were made to improve the developer experience or to introduce consistency between the Web SDK and REST API. These changes include:

  • With v2, authentication is now handled automatically when a user clicks on an app icon, meaning developers no longer need to explicitly invoke an authorization flow.
  • App names and app icons will now be managed in App Settings. There is no longer a programmatic way to update either the App Name or the App Icon.
  • Some endpoints in the v1 SDK were designed to support Enterprise accounts, such as account.get(). These have been removed from the v2 Web SDK, and any Enterprise-based changes should be managed through the REST API.
  • Experimental features or methods can be previewed in the experimental miro.board.experimental namespace.

An example - Converting Sticky Notes to Shapes

As an example of the changes that may be required when migrating your own app from v1 to v2, we have included the following example, which shows a side-by-side comparison of the Sticky Note to Shape conversion sample app. The full JavaScript source from both the v1 sample app and the v2 sample app is displayed below, along with a description of each affected piece of the v1 sample code.

v1 Code Sample

v1 Change

v2 Code Sample

1 miro.onReady(() => {
2   miro.initialize({
3     extensionPoints: {
4       bottomBar: {
5         title: 'Sticker to shapes',
6         svgIcon:
7           '<circle cx="12" cy="12" r="9"
                fill="none" fill-rule="evenodd"
                stroke="currentColor" stroke-width="2"/>',
8         positionPriority: 1,
9         onClick: async () => {
  • bottomBar is no longer available
  • title can no longer be set or changed programmatically
  • svgIcon can no longer be set or changed programmatically
1 const { board } = window.miro;
3 async function init() {
4   board.ui.on("icon:click", async () => {

10           // Get selected widgets
11           let selectedWidgets = 
                  await miro.board.selection.get()
  • The endpoint name has changed

5 // Get selected items
6     let selectedItems = 
        await miro.board.getSelection();
13            // Filter stickers from selected widgets
14           let stickers = selectedWidgets.filter(
                   (widget) => widget.type === 'STICKER')

  • widget is now item
  • STICKER is now sticky_note

8     // Filter sticky notes from selected items
9     let stickyNotes = selectedItems.filter(
10       (item) => item.type === "sticky_note"
11     );
16           // Delete selected stickers
17           await miro.board.widgets.deleteById(
                   stickers.map((sticker) => sticker.id))

  • Widgets are no longer deleted by ID. Rather, the item object is removed from the board object.
13     // Delete selected stickers
14     for (const stickyNote of stickyNotes) {
15       await board.remove(stickyNote);
16     }
19           // Create shapes from selected stickers
20           await miro.board.widgets.create(
21             stickers.map((sticker) => ({
22               type: 'shape',
23               text: sticker.text,
24               x: sticker.x,
25               y: sticker.y,
26               width: sticker.bounds.width,
27               height: sticker.bounds.height,
28             })),
29           )
  • Shapes now have an independent creation endpoint, as do all other widget types.
  • text is now content

18     // Create shapes from selected sticky notes
19     for (const stickyNote of stickyNotes) {
20       await miro.board.createShape({
21         content: stickyNote.content,
22         x: stickyNote.x,
23         y: stickyNote.y,
24         width: stickyNote.width,
25         height: stickyNote.height,
26       });
27     }

31           // Show success message
32           miro.showNotification(
                   'Stickers has been converted')
33         },
34       },
35     },
36   })
37 })
  • Notifications in v2 are now handled via the showInfo() method.
// Create a notification message to display on the board UI.
const infoMessage = {
  code: 42,
  action: 'The ultimate answer to life, the universe, and everything is:',
  followUp: '42.',

// Compose the message.
const infoNotification = `${infoMessage.action} ${infoMessage.followUp}`;

// Display the notification on the board UI.
await miro.board.notifications.showInfo(infoNotification);