board is a property of window.miro that enables:

Properties

ui

BoardUI

ui is the namespace that groups methods that apps can use to interact with users through the board UI.
Through miro.board.ui, apps can access methods to display specific UI elements, and to populate them with the desired content.
Typically, Miro apps can prompt for user interaction on the board UI through panels and modals.

miro.board.ui also enables apps to subscribe to and unsubscribe from Miro Web SDK events.


notifications

Notifications

notifications is the namespace that groups methods to handle and control notifications displayed on the board UI.
Through miro.board.notifications, apps can access methods to display specific notification types, and to populate them with the desired messages.

  • showInfo: a convenience method to trigger a notification to display an informative message on the board UI.
    Informs users about the successful outcome of an action or event.
  • showError: a convenience method to trigger a notification to display an error message on the board UI.
    Warns users about an unexpected error that caused the action or event to partially or completely fail.
  • show: a method that triggers a notification to display either an informative, or an error message on the board UI.

viewport

Viewport

viewport is the namespace that groups methods that apps can use to interact with the viewport:

  • get the current viewport.
  • set a new viewport.
  • zoomTo an item on the board, and focus the viewport on the specified object.

storage

Storage

The storage namespace provides methods and components for storing, retrieving, and working with app data.
Through miro.board.storage, apps can access methods to manage collections - saving, reading, and removing data.

  • collection(): Gets a collection object for a specific collection name.
    Collections allow you to store key/value data, similar to tables in a database.
    To get a collection, call collection() with the collection name: const collection = miro.board.storage.collection('my-collection').
  • Collection.set(): Saves a value to the collection for a given key.
    This lets you store data mapped to a key: await collection.set('key', 'you-value').
  • Collection.get(): Retrieves the value for a given key in the collection.
    This lets you fetch stored data: await collection.get('key').
  • Collection.remove(): Deletes the value for a given key in the collection.
    This lets you remove stored data: await collection.remove('key').

events

RealtimeEvents

events is the namespace that enables apps to subscribe to and unsubscribe from real-time events. This is currently an experimental feature available only in the experimental namespace. miro.board.experimental.events provides methods for apps to:

  • Subscribe to real-time broadcasted events for this app. When subscribing, the app specifies a callback function to be invoked when an event is broadcast.
  • Unsubscribe from real-time broadcasted events. This stops the app from receiving further events.
  • Broadcast custom events to other clients and users that are using the same app. The app can broadcast events with a event name and data payload. Other subscribed clients will receive these event notifications through their callback functions.

timer

Timer

The timer namespace provides control over the built-in Miro timer feature. This is available under miro.board.timer.

  • start: starts the timer for a specified amount of milliseconds.
  • get: gets the current state of the timer.
  • stop: stops the timer.
  • pause: pauses the timer.
  • resume: resumes the timer.
  • prolong: prolongs the timer by a specified amount of milliseconds.
  • isStarted: checks if the timer has started or not.
  • on: subscribes to different timer events.
  • off: unsubscribes from previously subscribed timer events.

Note:

Timer is only available on paid plans, Starter and above.
It can be checked via await miro.board.canUse('timer').


collaboration

Collaboration

Experimental feature Experimental

The collaboration namespace provides methods and components to handle collaborative features on Miro boards, including: sessions, attention management, and remote viewport control.
Sessions are the foundational component necessary for leveraging collaborative features. It is necessary to start a collaborative session (sessionStart) in order to manage features like attention management and remote viewport control.

miro.board.collaboration provides methods and components that allow apps to create collaborative experiences across multiple users on the same board. This includes controlling the viewport, attention management capabilities such as zooming into user content, and more.

  • startSession: starts a collaborative session.
  • getSessions: retrieves existing sessions for the current app.
  • zoomTo: zooms the specified user to one or more items on the board.
  • on: subscribes to different collaborative events.
  • off: unsubscribes from previously subscribed collaborative events.
  • attention: provides access to methods related to managing attention.
    • follow: initiates the process of following a specified online user(s), referred to as the followed user.
    • unfollow: is used to stop a user(s) from following another user.
    • isFollowing: checks whether the current user is already following another user on the board.
    • getFollowedUser: if a user is following another user, the method returns the followed user details.

experimental

Experimental

Experimental feature Experimental

experimental is the namespace that groups and exposes experimental features.
Through miro.board.experimental, apps can access functionality, properties, and methods that are in active development, and therefore subject to change without notice.

⚠️ Warning:

  • The features exposed through miro.board.experimental are suitable for testing purposes.
    Don't deploy these features to a production environment.

Methods

bringInFrontOf

(items: OneOrMany<BaseItem>, target: BaseItem) => Promise<void>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

In a stack of items, this method sends an item or array of items in front of another item (target).
When the items are moved to the front, the items can partially or completely hide underlying items in the same stack.

ℹ️ Note:

  • As this method implements relative positioning, you can use this method to place items in front or behind other items.
    If you want to send an item all the way to the front,
    you can use the method bringToFront(), which places the item at the top of the stack.
  • Frame items don't support the bringInFrontOf() method.
    As a frame item acts as a parent that can contain other items, a frame item is always at the back, relative to any other items on the board.
    The only object behind a frame is the board itself.

Example:

// Create three sticky notes
const first = await miro.board.createStickyNote({
  content: 'first',
});

const second = await miro.board.createStickyNote({
  content: 'second',
});

const third = await miro.board.createStickyNote({
  content: 'third',
});

// Bring the first sticky note in front of second.
await miro.board.bringInFrontOf(first, second);

// OR bring the list of several items in front of third.
await miro.board.bringInFrontOf([first, second], third);

bringToFront

(items: OneOrMany<BaseItem>) => Promise<void>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

In a stack of items, it brings an item or an array of items to the front so that they are at the top of the stack.
When they are at the front, items are fully visible; they can partially or completely hide underlying items in the same stack.

ℹ️ Note:

  • Frame items don't support the bringToFront() method.
    As a frame item acts as a parent that can contain other items, a frame item is always at the back, relative to any other items on the board.
    The only object behind a frame is the board itself.

Example:

// Create three sticky notes
const first = await miro.board.createStickyNote({
  content: 'first',
});

const second = await miro.board.createStickyNote({
  content: 'second',
});

const third = await miro.board.createStickyNote({
  content: 'third',
});

// Bring the first sticky note to the front of the board.
await miro.board.bringToFront(first);

// Or: bring the second and third sticky notes to the front of the board.
await miro.board.bringToFront([second, third]);

canUse

(feature: BoardFeature) => Promise<boolean>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 1

The method canUse() checks whether the current user in Miro board is entitled to use some of the restricted Miro features.

You need to pass the feature name as argument to check, the currently supported features are:

  • timer
  • voting

Returns:

  • Promise<boolean> - whether the current user running the app is entitled to use the enquired Miro feature.

Example:

const canUseVoting = await miro.board.canUse('voting');
const canUseTimer = await miro.board.canUse('timer');

if (canUseVoting) {
  console.log('User has access to voting');
}

if (canUseTimer) {
  console.log('User has access to timer');
}

createAppCard

(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  description?: string
  fields?: DeepPartial<undefined | Array<CardField>>
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  owned?: readonly DeepPartial<boolean>
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  status?: DeepPartial<AppCardStatus>
  style?: DeepPartial<CardStyle>
  tagIds?: Array<string>
  title?: string
  title="type">type?: readonly 'app_card'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<AppCard>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates an app card on a board.

There are no required properties that you need to pass upon creation.
If you create a card without passing any properties, the card is empty.
You can update the default values at a later time.

ℹ️ Note:

  • To open the detail view of an app card from its compact view, the app must listen to the app_card:open event.
    A typical use case for app_card:open is to open a modal displaying content fetched from a specified URL.
    For more information, see app_card:open.

Example:

const appCard = await miro.board.createAppCard({
  title: 'This is the title of the app card',
  description:
    'The custom preview fields are highlighted in different colors; the app card icon is displayed on the bottom-right.',
  style: {
    cardTheme: '#2d9bf0',
  },
  fields: [
    {
      value: 'Owner',
      iconUrl: 'https://cdn-icons-png.flaticon.com/512/921/921124.png',
      iconShape: 'round',
      fillColor: '#FBE983',
      textColor: '#F83A22',
      tooltip: 'Caption text displayed in a tooltip when clicking or hovering over the preview field',
    },
    {
      value: 'Timeline',
      iconUrl: 'https://cdn-icons-png.flaticon.com/512/3094/3094861.png',
      iconShape: 'square',
      fillColor: '#F8D878',
      textColor: '#503000',
      tooltip: 'Caption text displayed in a tooltip when clicking or hovering over the preview field',
    },
    {
      value: 'Tasks',
      iconUrl: 'https://cdn-icons-png.flaticon.com/512/3176/3176366.png',
      iconShape: 'square',
      fillColor: '#bef2f2',
      textColor: '#0713FF',
      tooltip: 'Caption text displayed in a tooltip when clicking or hovering over the preview field',
    },
    {
      value: 'Bug fix',
      iconUrl: 'https://cdn-icons-png.flaticon.com/512/3867/3867669.png',
      iconShape: 'square',
      fillColor: '#E5E5E5',
      textColor: '#000000',
      tooltip: 'Caption text displayed in a tooltip when clicking or hovering over the preview field',
    },
  ],
  x: 2000,
  y: 2000,
  width: 320,
  rotation: 0.0,
  status: 'connected', // Default status of new app cards: 'disconnected'
});

// Listen to the 'app_card:open' event
miro.board.ui.on('app_card:open', (event) => {
  console.log('Subscribed to app card open event', event);
  const {appCard} = event;

  // Fetch a specific app card by specifying its ID
  const url = `https://my.app.example.com/modal.html?appCardId=${appCard.id}`;

  // Open the modal to display the content of the fetched app card
  miro.board.ui.openModal({
    url,
  });
});

// Output the created item to the developer console
console.log(appCard);

App card item, compact view:


Figure 1. Compact view of an app card. The custom preview fields are highlighted in different colors. The default app card icon is on the bottom right. The status icon is displayed when hovering the mouse over the top-right corner of the app card.

AppCardProps
{
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  description: undefined | string
  fields?: DeepPartial<undefined | Array<CardField>>
  groupId?: readonly DeepPartial<undefined | string>
  height: readonly undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  owned: readonly undefined | DeepPartial<boolean>
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  rotation: undefined | number
  status: undefined | DeepPartial<AppCardStatus>
  style: undefined | DeepPartial<CardStyle>
  tagIds: undefined | Array<string>
  title: undefined | string
  title="type">type: readonly undefined | 'app_card'
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createCard

(props?: {
  assignee?: DeepPartial<undefined | CardAssignee>
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  description?: string
  dueDate?: DeepPartial<undefined | string>
  fields?: DeepPartial<undefined | Array<CardField>>
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  startDate?: DeepPartial<undefined | string>
  style?: DeepPartial<CardStyle>
  tagIds?: Array<string>
  taskStatus?: DeepPartial<CardTaskStatus>
  title?: string
  title="type">type?: readonly 'card'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Card>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a card on a board.

There are no required properties that you need to pass upon creation.
If you create a card without passing any properties, the card is empty.
You can update the default values at a later time.

Example:

const card = await miro.board.createCard({
  title: 'Easy peasy lemon squeezy',
  description:
    '<p>Go back in time and DO NOT clone a whole pack of T-Rexes.<br>They make for rather rowdy pets.<br>🦖👎</p>',
  dueDate: '2006-08-18',
  assignee: {
    userId: '3074457362577955221',
  },
  taskStatus: 'to-do',
  style: {
    cardTheme: '#2d9bf0', // Default color: light blue
  },
  fields: [
    {
      value: 'Bug fix',
      iconUrl: 'https://cdn-icons-png.flaticon.com/512/3867/3867669.png',
      iconShape: 'round',
      fillColor: '#E5E5E5',
      textColor: '#000000',
      tooltip: 'Caption text displayed in a tooltip when clicking or hovering over the preview field',
    },
  ],
  x: 0, // Default value: horizontal center of the board
  y: 0, // Default value: vertical center of the board
  width: 320,
  rotation: 0.0,
});

// Output the created item to the developer console
console.log(card);

Card item, compact view:

Compact view of a card. You can view basic information.
Figure 1. Compact view of a card. You can view basic information.

CardProps
{
  assignee?: DeepPartial<undefined | CardAssignee>
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  description: undefined | string
  dueDate?: DeepPartial<undefined | string>
  fields?: DeepPartial<undefined | Array<CardField>>
  groupId?: readonly DeepPartial<undefined | string>
  height: readonly undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  rotation: undefined | number
  startDate?: DeepPartial<undefined | string>
  style: undefined | DeepPartial<CardStyle>
  tagIds: undefined | Array<string>
  taskStatus: undefined | DeepPartial<CardTaskStatus>
  title: undefined | string
  title="type">type: readonly undefined | 'card'
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createConnector

(props: {
  captions?: DeepPartial<undefined | Array<ConnectorCaption>>
  createdAt?: readonly string
  createdBy?: readonly string
  end?: DeepPartial<undefined | Endpoint>
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  shape?: DeepPartial<ConnectorShape>
  start?: DeepPartial<undefined | Endpoint>
  style?: DeepPartial<ConnectorStyle>
  title="type">type?: readonly 'connector'
  width?: readonly number
}) => Promise<Connector>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a connector item on a board.

When creating connector lines programmatically, either with the Web SDK or the REST API, it's not possible to create loose (both ends disconnected) or dangling (one end disconnected) connectors.

To create a connector, you must specify at least:

  • start and end points of the connector.
  • The item IDs of the board items that the connector links.
  • The location of the two terminal points that attach the connector to its start and end items.

You can set the location of the terminal points in one of the following ways:

  • Either specify the position.x and position.y coordinates of each point.
  • Or specify the snapTo property for each point.
  • You cannot specify both position coordinates and snapTo properties for the start and end points.

Example:

// Create a shape to use as a start point for the connector.
const start = await miro.board.createShape({
  content: 'start',
  x: 4500,
});

// Create a shape to use as an end point for the connector.
const end = await miro.board.createShape({
  content: 'end',
  x: 4800,
});

// Create a connector.
const connector = await miro.board.createConnector({
  shape: 'elbowed',
  style: {
    startStrokeCap: 'diamond',
    endStrokeCap: 'stealth',
    strokeStyle: 'dashed',
    strokeColor: '#ff00ff', // Magenta
    strokeWidth: 2,
  },
  // Set the start point of the connector.
  start: {
    // Define the start board item for the connector by specifying the 'start' item ID.
    item: start.id,
    // Set a point on the border of the 'start' shape to mark the start point of the connector.
    position: {
      // Horizontal: right
      x: 1.0,
      // Vertical: middle
      y: 0.5,
    },
  },
  // Set the end point of the connector.
  end: {
    // Define the end board item for the connector by specifying the 'end' item ID.
    item: end.id,
    // Set a snapTo of 'end' shape to mark the end point of the connector.
    snapTo: 'right',
  },
  captions: [
    {
      content: 'This connector links a start and an end shape.',
      position: 0.5,
      textAlignVertical: 'bottom',
    },
  ],
});

console.log(connector);

Connector example:


Figure 1. The connector joins the start and end shapes. It starts from the point defined in start.position, and it ends at the point defined in end.snapTo.

ConnectorProps
{
  captions?: DeepPartial<undefined | Array<ConnectorCaption>>
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  end?: DeepPartial<undefined | Endpoint>
  groupId?: readonly DeepPartial<undefined | string>
  height: readonly undefined | number
  title="id">id: readonly undefined | string
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  shape: undefined | DeepPartial<ConnectorShape>
  start?: DeepPartial<undefined | Endpoint>
  style: undefined | DeepPartial<ConnectorStyle>
  title="type">type: readonly undefined | 'connector'
  width: readonly undefined | number
}

createEmbed

(props: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly DeepPartial<undefined | number>
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  mode?: DeepPartial<EmbedMode>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  previewUrl?: string
  relativeTo?: DeepPartial<RelativeTo>
  title="type">type?: readonly 'embed'
  url?: readonly string
  width?: readonly DeepPartial<undefined | number>
  title="x">x?: number
  title="y">y?: number
}) => Promise<Embed>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 3

Creates an embed item on a board.

To embed content from a supported provider in a board, specify:

  • The URL pointing to the resource that you want to embed in a board.
  • (Optional):
    • x and y board coordinates where you want the content to be embedded.
    • width and height of the embed area.
    • A URL pointing to an image to use as a preview for the embed item.

ℹ️ Note:

  • If you don't explicitly set any dimensions, width and height are set based on the corresponding retrieved values for the resource.
  • If width and height values aren't available, the embed item is displayed on the board as a 500x500 dp gray square.

Example:

const embed = await miro.board.createEmbed({
  url: 'https://youtu.be/HlVSNEiFCBk',
  previewUrl:
    'https://miro.com/blog/wp-content/uploads/2020/10/organize-their-Miro-boards-for-trainings-and-workshops-FB.png',
  mode: 'modal',
  width: 1280,
  height: 720,
  x: 1600,
  y: 1600,
});

console.log(embed);

Embed item example:


Figure 1. Example of an embed item with a playable YouTube video and an assigned preview image.

EmbedProps
{
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly DeepPartial<undefined | number>
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  mode: undefined | DeepPartial<EmbedMode>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  previewUrl: undefined | string
  relativeTo: undefined | DeepPartial<RelativeTo>
  title="type">type: readonly undefined | 'embed'
  url: readonly undefined | string
  width?: readonly DeepPartial<undefined | number>
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createFrame

(props?: {
  childrenIds?: Array<string>
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  showContent?: DeepPartial<boolean>
  style?: DeepPartial<{ fillColor: string }>
  title?: string
  title="type">type?: readonly 'frame'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Frame>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a frame on a board.

There are no required properties to pass upon creation.
You can update the default values at a later time.

Example:

const frame = await miro.board.createFrame({
  title: 'This frame ratio is 16:9',
  style: {
    fillColor: '#ffffff', // Default value: 'transparent' (no fill color)
  },
  x: 0, // Default value: horizontal center of the board
  y: 0, // Default value: vertical center of the board
  width: 800,
  height: 450,
});

console.log(frame);

Frame item:

A frame parent item containing a sticky note as a child item.
Figure 1. A frame parent item containing a sticky note as a child item.

FrameProps
{
  childrenIds: undefined | Array<string>
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  groupId?: readonly DeepPartial<undefined | string>
  height: undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  showContent: undefined | DeepPartial<boolean>
  style: undefined | DeepPartial<{ fillColor: string }>
  title: undefined | string
  title="type">type: readonly undefined | 'frame'
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createImage

(props: ImageProps) => Promise<Image>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 3

Inserts an image on a board.

The only required property to pass upon creation is a valid url pointing to the image.

Example:

const image = await miro.board.createImage({
  title: 'This is an image',
  url: 'https://miro.com/blog/wp-content/uploads/2023/10/Frame-12772209-1536x806.png',
  x: 0, // Default value: horizontal center of the board
  y: 0, // Default value: vertical center of the board
  width: 800, // Set either 'width', or 'height'
  rotation: 0.0,
});

console.log(image);

Image item:


Figure 1. Image item.

ImageProps
{
  alt: DeepPartial<undefined | string>
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  groupId?: readonly DeepPartial<undefined | string>
  height: undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  rotation: undefined | number
  title: undefined | string
  title="type">type: undefined | 'image'
  url: string
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createPreview

(props: PreviewProps) => Promise<Preview>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a preview on a board.

The only required property to pass upon creation is a valid url.

Example:

const preview = await miro.board.createPreview({
  url: 'https://miro.com/',
  x: 0, // Default value: horizontal center of the board
  y: 0, // Default value: vertical center of the board
  width: 400,
  rotation: 0.0,
});

console.log(preview);

Preview item:

Preview item.
Figure 1. Preview item.

PreviewProps
{
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  groupId?: readonly DeepPartial<undefined | string>
  height: undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  title="type">type: undefined | 'preview'
  url: string
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createShape

(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content?: string
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  shape?: DeepPartial<ShapeType | 'rectangle' | 'circle' | 'triangle' | 'wedge_round_rectangle_callout' | '...'>
  style?: DeepPartial<ShapeStyle>
  title="type">type?: readonly 'shape'
  width?: readonly number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Shape>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a geometric shape on a board.

The only required property to pass upon creation is a valid shape.

Example:

const shape = await miro.board.createShape({
  content: '<p>This is a star shape.</p>',
  shape: 'star',
  style: {
    color: '#ff0000', // Default text color: '#1a1a1a' (black)
    fillColor: '#ffff00', // Default shape fill color: transparent (no fill)
    fontFamily: 'arial', // Default font type for the text
    fontSize: 14, // Default font size for the text, in dp
    textAlign: 'center', // Default horizontal alignment for the text
    textAlignVertical: 'middle', // Default vertical alignment for the text
    borderStyle: 'normal', // Default border line style
    borderOpacity: 1.0, // Default border color opacity: no opacity
    borderColor: '#ff7400', // Default border color: '#ffffff` (white)
    borderWidth: 2, // Default border width
    fillOpacity: 1.0, // Default fill color opacity: no opacity
  },
  x: 0, // Default value: center of the board
  y: 0, // Default value: center of the board
  width: 200,
  height: 200,
});

console.log(shape);

Shape item (star shape):

Shape item example: a star shape.
Figure 1. Shape item example: a star shape.

ShapeProps
{
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content: undefined | string
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  groupId?: readonly DeepPartial<undefined | string>
  height: undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  rotation: undefined | number
  shape:
    | undefined
    | DeepPartial<ShapeType | 'rectangle' | 'circle' | 'triangle' | 'wedge_round_rectangle_callout' | '...'>
  style: undefined | DeepPartial<ShapeStyle>
  title="type">type: undefined | 'shape'
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createStickyNote

(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content?: string
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  shape?: DeepPartial<StickyNoteShape>
  style?: DeepPartial<StickyNoteStyle>
  tagIds?: Array<string>
  title="type">type?: readonly 'sticky_note'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<StickyNote>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a sticky note on a board.
Sticky notes look like physical paper sticky notes.

There are no required properties that you need to pass upon creation.
If you create a sticky note without passing any properties, the sticky note content is empty.
You can update the default values at a later time.

Example:

const stickyNote = await miro.board.createStickyNote({
  content: '<p>This is a sticky note. It looks just like the actual paper one.</p>',
  style: {
    fillColor: 'light_yellow', // Default value: light yellow
    textAlign: 'center', // Default alignment: center
    textAlignVertical: 'middle', // Default alignment: middle
  },
  x: 0, // Default value: horizontal center of the board
  y: 0, // Default value: vertical center of the board
  shape: 'square',
  width: 200, // Set either 'width', or 'height'
});

console.log(stickyNote);

Sticky note item:


Figure 1. Sticky note item.

StickyNoteProps
{
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content: undefined | string
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  groupId?: readonly DeepPartial<undefined | string>
  height: undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  shape: undefined | DeepPartial<StickyNoteShape>
  style: undefined | DeepPartial<StickyNoteStyle>
  tagIds: undefined | Array<string>
  title="type">type: undefined | 'sticky_note'
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

createTag

(props?: {
  color?: DeepPartial<'red' | 'magenta' | 'violet' | 'light_green' | 'green' | '...'>
  title="id">id?: readonly string
  title?: string
  title="type">type?: readonly 'tag'
}) => Promise<Tag>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a tag on a board.
After creating a tag, you can attach it to the following items:

ℹ️ Note:

  • title is required.
  • If no color is specified, it defaults to red.
  • Card and sticky note items can have up to 8 tags.
  • Boards can have up to 100 tags in total.

Example:

// Create a tag
const todo = await miro.board.createTag({
  title: 'todo or not todo, that is the question',
  color: 'yellow',
});

// Create a sticky note and attach the tag to it
const stickyNote = await miro.board.createStickyNote({
  content: "sticky note with tag: 'todo'",
  tagIds: [todo.id],
});

console.log(stickyNote.tagIds); // => ['3074457345627244742']

Tag attached to a sticky note:

A tag attached to a sticky note.
Figure 1. A tag attached to a sticky note.

TagProps
{
  color: undefined | DeepPartial<'red' | 'magenta' | 'violet' | 'light_green' | 'green' | '...'>
  title="id">id: undefined | string
  title: undefined | string
  title="type">type: undefined | 'tag'
}

createText

(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content?: string
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  style?: DeepPartial<TextStyle>
  title="type">type?: readonly 'text'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Text>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Creates a text item on a board.

There are no required properties to pass upon creation.
If you create a text item without passing any properties, content is an empty string.
You can update the values at a later time.

Example:

const text = await miro.board.createText({
  content: '<p>This is a piece of text to remind me that I always finish what I ...</p>',
  style: {
    color: '#1a1a1a', // Default value: '#1a1a1a' (black)
    fillColor: 'transparent', // Default value: transparent (no fill)
    fillOpacity: 1, // Default value: 1 (solid color)
    fontFamily: 'arial', // Default font type for the text
    fontSize: 14, // Default font size for the text
    textAlign: 'left', // Default horizontal alignment for the text
  },
  x: 0, // Default value: horizontal center of the board
  y: 0, // Default value: vertical center of the board
  width: 300,
  rotation: 0.0,
});

console.log(text);

Text item:

Text item.
Figure 1. Text item.

TextProps
{
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content: undefined | string
  createdAt: readonly undefined | string
  createdBy: readonly undefined | string
  groupId?: readonly DeepPartial<undefined | string>
  height: readonly undefined | number
  title="id">id: readonly undefined | string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt: readonly undefined | string
  modifiedBy: readonly undefined | string
  origin: undefined | 'center'
  parentId: readonly undefined | DeepPartial<'null' | string>
  relativeTo: undefined | DeepPartial<RelativeTo>
  rotation: undefined | number
  style: undefined | DeepPartial<TextStyle>
  title="type">type: readonly undefined | 'text'
  width: undefined | number
  title="x">x: undefined | number
  title="y">y: undefined | number
}

deselect

(filter?: F) => Promise<QueryReturn<Connector | AppCard | Card | Embed | Image | '...', F>>
🚦 Rate limit: Level 1
🔒 Requires scope: boards:write

Deselects one or more items from the board and returns the list of deselected items.
If you don't pass any arguments, the method deselects all items and returns them.

Optionally, you can deselect items by id, type, and tags:

  • Deselect by id: pass an item id to deselect the corresponding item. If the ID doesn't exist on the board, the method throws an error.
    Pass an array of IDs to deselect items with one of the specified IDs.
  • Deselect by type: pass an item type to deselect items matching the requested type.
    Pass an array of types to deselect items matching one of the specified types. If you pass type group, all the elements within the groups will be deselected.
  • Deselect by tags: pass one or more tags to deselect items with the specified tags.
    If the tags don't exist on the board, the method returns an empty array.
    Pass an array of tags to deselect items matching one of the specified tags.

ℹ️ Note:

  • The method cannot return child items inside unsupported parent items, such as User Story Mapping (USM) and Kanban.
  • If you filter by passing an array of item IDs, item types, or tags, the logical operator between the array members is OR.
  • The method doesn't have an upper limit as to the maximum amount of items that it can return.
    To avoid performance degradation on the board UI, we recommend to not exceed 10000 items per board.

Example:

// Create a tag
const todo = await miro.board.createTag({
  title: 'todo',
  color: 'yellow',
});

// Create another tag
const urgent = await miro.board.createTag({
  title: 'urgent',
  color: 'magenta',
});

// Create a card and attach the tags to it
const card = await miro.board.createCard({
  title: 'card with tags: "todo", "urgent"',
  tagIds: [todo.id, urgent.id],
});

// Create a sticky note and attach the tags to it
const stickyNote = await miro.board.createStickyNote({
  content: 'sticky note with tags: "todo", "urgent"',
  tagIds: [todo.id, urgent.id],
});

// Select all
await miro.board.select();

// Deselect the sticky note by passing its ID
await miro.board.deselect({
  id: stickyNote.id,
});

// Deselect all items with 'card' OR 'sticky_note' type
await miro.board.deselect({
  type: ['card', 'sticky_note'],
});

// Deselect all 'card' OR 'sticky_note' items with 'todo' OR 'urgent' tags
await miro.board.deselect({
  type: ['sticky_note', 'card'],
  tags: ['todo', 'urgent'],
});

// Deselect all grouped items in the board
await miro.board.deselect({
  type: 'group',
});

findEmptySpace

(dimensions: Rect & { offset?: number }) => Promise<Rect>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 1

Use the findEmptySpace method to identify an area on the board that doesn't overlap with existing board items.

Parameters

  • x and y: define the starting central point to begin the search for an empty space.
  • width and height: specify the desired size of the empty space.
  • offset (optional): sets a distance between the empty space and nearby board items. If not provided, the method finds the closest available space. Default value: 100

Returns An object containing x and y coordinates for the center point of the identified empty space, along with the specified width and height.

Example:

const position = await miro.board.findEmptySpace({
  x: 0,
  y: 0,
  width: 200,
  height: 200,
});
const sticky = await miro.board.createStickyNote({
  content: "No overlap",
  x: position.x,
  y: position.y,
  width: position.width,
});

await miro.board.viewport.zoomTo(sticky)

get

(filter?: F) => Promise<QueryReturn<Connector | AppCard | Card | Embed | Image | '...', F>>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 3

Fetches one or more items, tags or groups from the board.
If you don't pass any arguments, the method returns an array with all the items, groups and tags on the board.

Optionally, you can filter items by id, type, and tags:

  • Filter by id: pass an item or a tag id to fetch the corresponding item or tag.
    If the ID doesn't exist on the board, the method throws an error.
    Pass an array of IDs to fetch an array with all the items or tags matching one of the specified IDs.
  • Filter by type: pass an item type to fetch an array with the items matching the requested type.
    Pass an array of types to fetch an array with the items matching one of the specified types.
  • Filter by tags: pass one or more tags to fetch all the items with the specified tags.
    If the tags don't exist on the board, the method returns an empty array.
    Pass an array of tags to fetch an array with the items matching one of the specified tags.

ℹ️ Note:

  • The method cannot return child items inside unsupported parent items, such as User Story Mapping (USM) and Kanban.
  • If you filter by passing an array of item IDs, item types, or tags, the logical operator between the array members is OR.
  • The method doesn't have an upper limit as to the maximum amount of items that it can return.
    To avoid performance degradation on the board UI, we recommend to not exceed 10000 items per board.

Example:

// Create a tag
const todo = await miro.board.createTag({
  title: 'todo',
  color: 'yellow',
});

// Create another tag
const urgent = await miro.board.createTag({
  title: 'urgent',
  color: 'magenta',
});

// Create a card and attach the tags to it
const card = await miro.board.createCard({
  title: 'card with tags: "todo", "urgent"',
  tagIds: [todo.id, urgent.id],
});

// Create a sticky note and attach the tags to it
const stickyNote = await miro.board.createStickyNote({
  content: 'sticky note with tags: "todo", "urgent"',
  tagIds: [todo.id, urgent.id],
});

// Get the sticky note by passing its ID
await miro.board.get({
  id: stickyNote.id,
});

// Get all items with type: 'card' OR 'sticky_note'
await miro.board.get({
  type: ['card', 'sticky_note'],
});

// Get all 'card' OR 'sticky_note' items with tags: 'todo' OR 'urgent'
await miro.board.get({
  type: ['sticky_note', 'card'],
  tags: ['todo', 'urgent'],
});
GetFilter
{ title="id">id: Array<string> | string } | { tags?: Array<string> | string; title="type">type?: Array<string> | string }

getAppData

(key?: K_1) => Promise<conditional>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 1

Fetches app metadata, stored per board, for the specified metadata key.
The response contains the metadata value assigned to the requested key.

To fetch all the metadata for an app, invoke the method without passing any arguments.
The response contains all the metadata associated with the app as key/value pairs.

An app can access only the metadata that it sets.
It cannot access metadata set by other apps.

ℹ️ Note:

⚠️ Warning:

  • Total AppData storage limit: 30 KB per app.

Example:

// Set app metadata to a board.
await miro.board.setAppData('activeTags', ['v1', 'v2', 'v3']);

// Get the specific 'activeTags' app metadata from the board.
const activeTags = await miro.board.getAppData('activeTags');

console.log(activeTags); // => ['v1', 'v2', 'v3']

getById

(title="id">id: string) => Promise<Unsupported | Connector | AppCard | Card | Embed | '...'>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 1

Fetches an item, if it exists on the board, based on the item ID that you pass with the method.
If the requested item ID doesn't exist—for example, because the item has been deleted from the board—the method throws an error:

Can not retrieve item with id 3458764518726781234

Example:

// Create a sticky note
const stickyNote = await miro.board.createStickyNote({
  content: 'This is a sticky note',
});

// Get the sticky note by passing its ID
await miro.board.getById(stickyNote.id);

getIdToken

() => Promise<string>
🚦 Rate limit: Level 1

Retrieves a JSON Web Token (JWT), an encoded form of JSON data, signed with the app client secret.
The JWT that the Web SDK method returns isn't the same type of token as the app access token for the REST API.
Pass the JWT that getIdToken returns as a bearer token to establish communication between the frontend and the backend of a Miro app built on top of the Miro Web SDK.
The token authenticates the app frontend with the app backend. The frontend runs on the board; the backend runs on the server that hosts the app to make it available.


Figure 1. The Web SDK token authenticates app instances running in the frontend with the app backend running on a server.

Example of the decoded JWT structure:

# JWT header
{
  "typ": "JWT", # Token type : JWT
  "alg": "HS256" # Encoding algorithm: HS256
}

# JWT payload
{
  "sub": "3458764521234567890", # Subject: the Client ID of the app that the JWT is issued for
  "iss": "miro", # Issuer: the JWT issuer is Miro
  "team": "3074457350123456789", # ID of the Miro team that the JWT is assigned to
  "exp": 1650619757, # Expiry date of the JWT in Unix epoch time: 1 hour after 'iat'
  "user": "3074457359876543210", # ID of the Miro user that the JWT is assigned to
  "iat": 1650616157 # Issue date of the JWT in Unix epoch time
}

# JWT signature
Signature: RqwL4X4iopF2GH0erQ3cTY_9QWasd5zxUIOPzKLfghj

To authenticate requests from the frontend to the backend of your Miro app:

  • Pass a valid JWT with each request.
  • In the request, include the JWT in the Authorization HTTP header as a Bearer token.

Example:

// Get the JWT signed with your app client secret.
const token = await miro.board.getIdToken();

// Pass the JWT with each request from your app to your backend services.
const response = await fetch('/your-app-server-endpoint', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`,
  };

  body: JSON.stringify(data); // Request body with data payload
});

See also:


getInfo

() => Promise<BoardInfo>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 1

Fetches basic metadata about the current board:

  • id: unique board ID.
  • createdAt: the date and time when the board was created.
  • updatedAt: the date and time when the board was last modified.
  • locale: the current user's locale.

The method takes no arguments.

Example:

const boardInfo = await miro.board.getInfo();

console.log(boardInfo); // => {id: "o9J_g9mOJpo=",createdAt: "2021-06-22T12:33:36.765Z",updatedAt: "2021-08-04T12:57:19.083Z", locale: "en"}

getLayerIndex

(item: BaseItem) => Promise<number>
🔒 Requires scope: boards:read

The getLayerIndex() method returns the position of an item in the item stack.

Items in a stack are layered on top of each other based on their layer index value. An item with a higher layer index appears above items with lower layer index values.

Each item on the board has a layer index position in the stack. The higher the layer index value, the "closer" to the user the item appears.

For example, with three items on the board - first, second, and third - their initial layer index values might be:
first[0], second[1], third[2].

The item with layerIndex === 2 (third) will be fully visible at the top of the stack. The item with layerIndex === 1 (second) may be partially hidden by the item above it. And the item with layerIndex === 0 (first) may be fully hidden by the items above it.

Returns:

  • Promise<number> - calling getLayerIndex() allows you get the position of a specific item in this stack.

ℹ️ Note:

  • Stack is zero indexed.
  • Frame items don't support the getLayerIndex() method.
    Since they act as parents that can contain other items, they are always at the back, relative to any other items on the board.
    The only object behind a frame is the board itself.

Example:

// Create three sticky notes,
// sticky notes will be created on top of each other in creation order, layer index will be equal to creation index
const first = await miro.board.createStickyNote({
  content: 'first',
});

const second = await miro.board.createStickyNote({
  content: 'second',
});

const third = await miro.board.createStickyNote({
  content: 'third',
});

await miro.board.getLayerIndex(third); // returns 2

getMetadata

(item: BaseItem, key?: K) => Promise<conditional>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 1

Fetches board item metadata, stored per app, for the specified metadata key.
The response contains the metadata value assigned to the requested key.

To fetch all the metadata for a board item, invoke the method without passing any arguments.
The response contains all the metadata associated with the board item as key/value pairs.

An app can access only the metadata that it sets.
It cannot access metadata set by other apps.

getMetadata and setMetadata are available for the following board items:

  • Card
  • Connector
  • Embed
  • Image
  • Preview
  • Shape
  • Sticky note
  • Text

The methods aren't available for the following board items:

ℹ️ Note:

⚠️ Warning:

  • Total ItemMetadata storage limit: 6 KB per item.

Example:

// Get the board item you want to retrieve metadata from.
const [geoCard] = await miro.board.get({type: 'card'});

// Set item metadata for an imaginary geocaching game, and store it to the retrieved card item.
await geoCard.setMetadata('leaderboard', ['Ziltoid', 'Howard', 'Paul']);

// Get the specific 'leaderboard' metadata from the card item.
const leaderboard = await geoCard.getMetadata('leaderboard');

// Get all the metadata from the card item by passing no arguments.
await geoCard.getMetadata();

getOnlineUsers

() => Promise<Array<OnlineUserInfo>>
🔒 Requires scope: boards:read
🚦 Rate limit: Level 1

Fetches basic information about the board users that are currently online:

  • id: unique user ID.
  • name: the name of the user.

The method takes no arguments.

Example:

const onlineUsers = await miro.board.getOnlineUsers();

console.log(onlineUsers); // => [{"id": "3458714513325546974", "name": "John Smith"}]
OnlineUserInfo
{ title="id">id: string; name: string }

getSelection

() => Promise<Array<Unsupported | Connector | AppCard | Card | Embed | '...'>>
🚦 Rate limit: Level 3
🔒 Requires scope: boards:read

Fetches the selected items from the board, and it returns them in an array.
If no items are selected on the board, the method returns an empty array.

If the grouped items are selected, the group entity for those items will also be returned.
When individual items within a group are selected with a double-click, the group entity will not be returned as part of this method.

Example:

// Get an array with the selected item(s) and their properties
const selection = await miro.board.getSelection();

console.log(selection);

getUserInfo

() => Promise<UserInfo>
🔒 Requires scope: identity:read
🚦 Rate limit: Level 1

Fetches basic metadata about the currently active user:

  • id: unique user ID.
  • name: the name of the user.
  • email: the email of the user.

The method takes no arguments.

Example:

const userInfo = await miro.board.getUserInfo();

console.log(userInfo); // => {"id": "3658432978520043388", "name": "John Smith", "email": "[email protected]"}
UserInfo
{ title="id">id: string; name: string }

goToLink

(item: BaseItem) => Promise<boolean>
🔒 Requires scope: boards:read

goToLink navigates to the provided link associated with the item on a board.

For links that point to another item on the same board, the viewport will automatically move to that item when true is returned.

For links that point to an item on a separate board or an external url, a new tab tab will be opened.

Returns:

Promise<boolean>

  • true: Link is successfully associated with the item, navigation is triggered, and the linkedTo property contains a valid value.
  • false: Link is not successfully associated to the item due to an invalid or missing linkedTo property, and no navigation is triggered.

Example:

const [geoCard] = await miro.board.get({type: 'card'});

// Link item to some url
geoCard.linkedTo = 'https://google.com';

// Update widget props and apply changes
await geoCard.sync();

// Navigate to https://google.com (value of `linkedTo` property)
await geoCard.goToLink();

group

(props: CreateGroupProps) => Promise<Group>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Groups the given items in the board, including unsupported items.

ℹ️ Note:

  • Previously grouped items cannot be grouped again, this will cause an error. You can use the groupId property in the item to check whether it's already assigned to a group.
  • Groups can only be created with at least two items.
  • Locked elements cannot be grouped.
  • Mindmaps and tags are not supported in groups.
  • Groups do not support metadata as other board items.
  • If a group is added to a frame, all the grouped items will also be attached to that frame. The group must fit within the frame dimensions to be added.

Example of adding grouped items to a frame:

const shape = await miro.board.createShape()
const card = await miro.board.createCard()
const text = await miro.board.createText()

const boardItems = [shape, card, text]

const group = await miro.board.group({ items: boardItems })
const frame = await miro.board.createFrame();

// shape, card and text will also be added to the frame
// you can check their parentId property after this operation
await frame.add(group)

remove

(item: BaseItem) => Promise<void>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Removes a board item or a tag from the board.
When removing board items or tags, any associated metadata is removed as well.

ℹ️ Note:

  • To use the remove() method, apps need the boards:write permission.
  • board.remove() removes board items, groups, and tags from the board.
    It doesn't remove parent-child relationships between items.
    To remove a parent-child relationship between items, use remove() at the parent item level.
    For example: frame.remove().
  • When removing groups, the group itself and all the items are removed from the board.

remove is common to all board items.


select

(filter?: F) => Promise<QueryReturn<Connector | AppCard | Card | Embed | Image | '...', F>>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Selects one or more items from the board and returns the list of selected items.
If you don't pass any arguments, the method selects all items and returns them.

Optionally, you can select items by id, type, and tags:

  • Select by id: pass an item id to select the corresponding item. If the ID doesn't exist on the board, the method throws an error.
    Pass an array of IDs to select items with one of the specified IDs.
  • Select by type: pass an item type to select items matching the requested type.
    Pass an array of types to select items matching one of the specified types. If you pass type group, all the elements within the groups will be deselected.
  • Select by tags: pass one or more tags to select items with the specified tags.
    If the tags don't exist on the board, the method returns an empty array.
    Pass an array of tags to select items matching one of the specified tags.

ℹ️ Note:

  • The method cannot return child items inside unsupported parent items, such as User Story Mapping (USM) and Kanban.
  • If you filter by passing an array of item IDs, item types, or tags, the logical operator between the array members is OR.
  • The method doesn't have an upper limit as to the maximum amount of items that it can return.
    To avoid performance degradation on the board UI, we recommend to not exceed 10000 items per board.

Example:

// Create a tag
const todo = await miro.board.createTag({
  title: 'todo',
  color: 'yellow',
});

// Create another tag
const urgent = await miro.board.createTag({
  title: 'urgent',
  color: 'magenta',
});

// Create a card and attach the tags to it
const card = await miro.board.createCard({
  title: 'card with tags: "todo", "urgent"',
  tagIds: [todo.id, urgent.id],
});

// Create a sticky note and attach the tags to it
const stickyNote = await miro.board.createStickyNote({
  content: 'sticky note with tags: "todo", "urgent"',
  tagIds: [todo.id, urgent.id],
});

// Select the sticky note by passing its ID
await miro.board.select({
  id: stickyNote.id,
});

// Select all items with 'card' OR 'sticky_note' type
await miro.board.select({
  type: ['card', 'sticky_note'],
});

// Select all 'card' OR 'sticky_note' items with 'todo' OR 'urgent' tags
await miro.board.select({
  type: ['sticky_note', 'card'],
  tags: ['todo', 'urgent'],
});

// Select all grouped items in the board
await miro.board.select({
  type: 'group',
});

sendBehindOf

(items: OneOrMany<BaseItem>, target: BaseItem) => Promise<void>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

In a stack of items, this method sends an item or array of items behind another item (target).
When the items are moved to the back, the items can be partially or completely hidden by the overlying items in the top of the same stack.

ℹ️ Note:

  • As this method implements relative positioning, you can use this method to place items in front or behind other items.
    If you want to send an item all the way to the back,
    you can use the method sendToBack(), which places the item at the bottom of the stack.
  • Frame items don't support the sendBehindOf() method.
    As a frame item acts as a parent that can contain other items, a frame item is always at the back, relative to any other items on the board.
    The only object behind a frame is the board itself.

Example:

// Create three sticky notes
const first = await miro.board.createStickyNote({
  content: 'first',
});

const second = await miro.board.createStickyNote({
  content: 'second',
});

const third = await miro.board.createStickyNote({
  content: 'third',
});

// Send the third sticky note behind the second one
await miro.board.sendBehindOf(third, second);

// OR send the list of items behind the first one
await miro.board.sendBehindOf([third, second], first);

sendToBack

(items: OneOrMany<BaseItem>) => Promise<void>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

In a stack of items, it sends an item or an array of items to the back so that they are at the bottom of the stack.
When they are at the back, items are partially or completely hidden by overlying items in the same stack.

ℹ️ Note:

  • Frame items don't support the sendToBack() method.
    As a frame item acts as a parent that can contain other items, a frame item is always at the back, relative to any other items on the board.
    The only object behind a frame is the board itself.

Example:

// Create three sticky notes
const first = await miro.board.createStickyNote({
  content: 'first',
});

const second = await miro.board.createStickyNote({
  content: 'second',
});

const third = await miro.board.createStickyNote({
  content: 'third',
});

// Send the first sticky note to the back of the board
await miro.board.sendToBack(first);

// Or: send the second and third sticky notes to the back of the board
await miro.board.sendToBack([second, third]);

setAppData

(key: string, value: title="Json">Json) => Promise<D_1>
🔒 Requires scope: boards:write
🚦 Rate limit: Level 1

Adds app metadata to make it available on the board that the app runs on.
An app can access only the metadata that it sets.
It cannot access metadata set by other apps.

For each board, app metadata is stored per app, and it's available to all the users who can:

  • Access and view the board that the app is running on, AND
  • Run the app on the board.

AppData is a key/value pair object. It can contain values with the following data types:

  • string
  • number
  • boolean
  • Object
  • Array
  • null
  • undefined

To overwrite an existing key inside AppData:

  • Pass the same key multiple times with different values. Only the last/most recent value is stored with the key.

To remove a key from AppData:

  • Set the value of the existing key to either null, or undefined.
    This clears the key. If you call getAppData(key) to retrieve a key that has been set to null or undefined, the method returns undefined.

ℹ️ Note:

  • To access app metadata, apps require the boards:read permission.
  • To store app metadata to the board, apps require the boards:write permission.
  • App metadata doesn't expire.
  • You can assign an empty array ([]) to a key. It's returned as an empty array.
  • You can assign an empty string ('') to a key. It's returned as an empty string.

⚠️ Warning:

  • Total AppData storage limit: 30 KB per app.

Example:

// Set app metadata for an imaginary character, and store it for the app at board level.
await miro.board.setAppData('characterCard', {
  name: 'null',
  age: 1,
  good: false,
  alias: ['xenomorph', 'bug', 'crab', 'facehugger', 'alien'],
  abilities: [
    {
      name: 'Acid blood',
      description: 'Can melt through metal.',
    },
    {
      name: 'Regeneration',
      description: 'Can regenerate from a single cell.',
    },
    {
      name: 'Strength',
      description: 'Can lift 20 times its own weight.',
    },
  ],
});

// Get the app metadata about the imaginary character from the board
const characterCard = await miro.board.getAppData('characterCard');

// Get all the app metadata from the board.
const allMetaData = await await miro.board.getAppData();

// Clear the metadata about the imaginary character in one of the following ways:
// 1. Assign 'characterCard' an empty object.
await miro.board.setAppData('characterCard', {});
// 2. Set 'characterCard' to 'undefined'.
await miro.board.setAppData('characterCard', undefined);
// 3. Set 'characterCard' to 'null'.
await miro.board.setAppData('characterCard', null);

setMetadata

(item: BaseItem, key: string, value: title="Json">Json) => Promise<D>
🔒 Requires scope: boards:write

Adds board item metadata to make it available on the board that the app runs on.
An app can access only the board item metadata that it sets.
It cannot access metadata set by other apps.

Board item metadata is stored in the item it refers to. Therefore:

  • When duplicating an item, the metadata is copied to the new item.
  • When deleting an item, the corresponding metadata is removed with the deleted item.

Board item metadata is synced across, and available to, all the users who can:

  • Access and view the board that the app is running on, AND
  • Run the app on the board.

ItemMetadata is a key/value-pair object. It can contain values with the following data types:

  • string
  • number
  • boolean
  • Object
  • Array
  • null
  • undefined

getMetadata and setMetadata are available for the following board items:

  • Card
  • Connector
  • Embed
  • Image
  • Preview
  • Shape
  • Sticky note
  • Text

The methods aren't available for the following board items:

To overwrite an existing key inside ItemMetadata:

  • Pass the same key multiple times with different values. Only the last/most recent value is stored with the key.

To remove a key from ItemMetadata:

  • Set the value of the existing key to either null, or undefined.
    This clears the key. If you call getMetadata(key) to retrieve a key that has been set to null or undefined, the method returns undefined.

ℹ️ Note:

⚠️ Warning:

  • Total ItemMetadata storage limit: 6 KB per item.

Example:

// Get the board item you want to set metadata to.
const [geoCard] = await miro.board.get({type: 'card'});

// Set item metadata for an imaginary geocaching game, and store it to the retrieved card item.
await geoCard.setMetadata('geoData', {
  name: 'null',
  coordinates: {
    latitude: '33.950278',
    longitude: '-105.314167',
  },
  lastFound: '1947-07-08',
  content: true,
  difficulty: 5,
  keywords: ['x-files', 'truth-is-out-there', 'area-51', 'roswell', 'aliens'],
  geoCache: [
    {
      name: 'UFO',
      description: 'Severely damaged unidentified flying object. ',
    },
    {
      name: 'Alien',
      description: 'Remains of an alien life form.',
    },
    {
      name: 'Artifacts',
      description: 'Tools, equipment, and other items found at the crash site.',
    },
    {
      name: 'Edibles',
      description: 'The alien was likely as high as a kite when they crashed. Typical.',
    },
  ],
});

// Get the specific 'geoData' metadata from the card item.
// The response contains the metadata value assigned to the key.
const geoCardGeoData = await geoCard.getMetadata('geoData');

// Get all the metadata from the card item.
// The response contains all the metadata assigned to the board item as key/value pairs.
const geoCardAllMetaData = await geoCard.getMetadata();

// Clear the metadata about the imaginary geocaching game in one of the following ways:
// 1. Assign 'geoData' an empty object.
await miro.board.setMetadata('geoData', {});
// 2. Set 'geoData' to 'undefined'.
await miro.board.setMetadata('geoData', undefined);
// 3. Set 'geoData' to 'null'.
await miro.board.setMetadata('geoData', null);

sync

(item: BaseItem) => Promise<void>
🔒 Requires scope: boards:write

sync propagates to the board any changes to item and tag properties.
After updating the properties of an item or a tag, sync it with the board to:

  • Propagate to the board the changes applied to the item or to the tag.
  • Make the changes visible on the board.

All board items and tags require sync to make any changes to their properties visible on the board.

For more information and examples, see Update and sync item properties.

Example:
(The code example updates a text item using sync.
The same mechanism applies to and works in the same way for all supported board items.)

// Create an item.
// In this case, a text item.
const text = await miro.board.createText({
  content: '<p>This is a piece of text to remind me that I always finish what I ...</p>',
  style: {
    fillColor: 'transparent',
    textAlign: 'left',
  },
  x: 0,
  y: 0,
  width: 450,
  rotation: 0.0,
});

// Update the board item by modifying the values of its properties.
// In the text item case, the updated properties modify content, background color, and rotation of the item.
text.content = 'A fourteneer is "A line that rumbles on like this for being a bit too long."';
text.style.fillColor = '#a9fe65';
text.rotation = 180.0;

// Call 'sync' to make the changed board item properties visible on the board.
await text.sync();

// Output the updated board item to the developer console.
console.log(text);

Example:
(The code example updates a tag using sync.
The same mechanism applies to and works in the same way for all supported board items.)

// Create a tag.
const todo = await miro.board.createTag({
  title: 'todo',
  color: 'yellow',
});

// Create a sticky note and attach the tag to it.
const stickyNote = await miro.board.createStickyNote({
  content: 'sticky note with tag: "todo"',
  tagIds: [todo.id],
});
console.log(stickyNote.tagIds); // => ['3074457345627244742']

// Update the tag properties: title and color.
todo.title = "won't fix";
todo.color = 'green';

// Call 'sync' to make the changed tag properties visible on the board.
await todo.sync();

// Output the updated tag to the developer console.
console.log(todo);

All properties

PropertyType
bringInFrontOf
(items: OneOrMany<BaseItem>, target: BaseItem) => Promise<void>
bringToFront
(items: OneOrMany<BaseItem>) => Promise<void>
canUse
(feature: BoardFeature) => Promise<boolean>
collaboration
Collaboration
createAppCard
(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  description?: string
  fields?: DeepPartial<undefined | Array<CardField>>
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  owned?: readonly DeepPartial<boolean>
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  status?: DeepPartial<AppCardStatus>
  style?: DeepPartial<CardStyle>
  tagIds?: Array<string>
  title?: string
  title="type">type?: readonly 'app_card'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<AppCard>
createCard
(props?: {
  assignee?: DeepPartial<undefined | CardAssignee>
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  description?: string
  dueDate?: DeepPartial<undefined | string>
  fields?: DeepPartial<undefined | Array<CardField>>
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  startDate?: DeepPartial<undefined | string>
  style?: DeepPartial<CardStyle>
  tagIds?: Array<string>
  taskStatus?: DeepPartial<CardTaskStatus>
  title?: string
  title="type">type?: readonly 'card'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Card>
createConnector
(props: {
  captions?: DeepPartial<undefined | Array<ConnectorCaption>>
  createdAt?: readonly string
  createdBy?: readonly string
  end?: DeepPartial<undefined | Endpoint>
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  shape?: DeepPartial<ConnectorShape>
  start?: DeepPartial<undefined | Endpoint>
  style?: DeepPartial<ConnectorStyle>
  title="type">type?: readonly 'connector'
  width?: readonly number
}) => Promise<Connector>
createEmbed
(props: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly DeepPartial<undefined | number>
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  mode?: DeepPartial<EmbedMode>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  previewUrl?: string
  relativeTo?: DeepPartial<RelativeTo>
  title="type">type?: readonly 'embed'
  url?: readonly string
  width?: readonly DeepPartial<undefined | number>
  title="x">x?: number
  title="y">y?: number
}) => Promise<Embed>
createFrame
(props?: {
  childrenIds?: Array<string>
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  showContent?: DeepPartial<boolean>
  style?: DeepPartial<{ fillColor: string }>
  title?: string
  title="type">type?: readonly 'frame'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Frame>
createGroup
(props: {
  title="id">id?: readonly string
  itemsIds?: readonly Array<string>
  title="type">type?: readonly 'group'
}) => Promise<Group>
createImage
(props: ImageProps) => Promise<Image>
createPreview
(props: PreviewProps) => Promise<Preview>
createShape
(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content?: string
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  shape?: DeepPartial<ShapeType | 'rectangle' | 'circle' | 'triangle' | 'wedge_round_rectangle_callout' | '...'>
  style?: DeepPartial<ShapeStyle>
  title="type">type?: readonly 'shape'
  width?: readonly number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Shape>
createStickyNote
(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content?: string
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  shape?: DeepPartial<StickyNoteShape>
  style?: DeepPartial<StickyNoteStyle>
  tagIds?: Array<string>
  title="type">type?: readonly 'sticky_note'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<StickyNote>
createTag
(props?: {
  color?: DeepPartial<'red' | 'magenta' | 'violet' | 'light_green' | 'green' | '...'>
  title="id">id?: readonly string
  title?: string
  title="type">type?: readonly 'tag'
}) => Promise<Tag>
createText
(props?: {
  connectorIds?: readonly DeepPartial<undefined | Array<string>>
  content?: string
  createdAt?: readonly string
  createdBy?: readonly string
  groupId?: readonly DeepPartial<undefined | string>
  height?: readonly number
  title="id">id?: readonly string
  linkedTo?: DeepPartial<undefined | string>
  modifiedAt?: readonly string
  modifiedBy?: readonly string
  origin?: 'center'
  parentId?: readonly DeepPartial<'null' | string>
  relativeTo?: DeepPartial<RelativeTo>
  rotation?: number
  style?: DeepPartial<TextStyle>
  title="type">type?: readonly 'text'
  width?: number
  title="x">x?: number
  title="y">y?: number
}) => Promise<Text>
deselect
(filter?: F) => Promise<QueryReturn<Connector | AppCard | Card | Embed | Image | '...', F>>
events
RealtimeEvents
findEmptySpace
(dimensions: Rect & { offset?: number }) => Promise<Rect>
get
(filter?: F) => Promise<QueryReturn<Connector | AppCard | Card | Embed | Image | '...', F>>
getAppData
(key?: K_1) => Promise<conditional>
getById
(title="id">id: string) => Promise<Unsupported | Connector | AppCard | Card | Embed | '...'>
getIdToken
() => Promise<string>
getInfo
() => Promise<BoardInfo>
getLayerIndex
(item: BaseItem) => Promise<number>
getMetadata
(item: BaseItem, key?: K) => Promise<conditional>
getOnlineUsers
() => Promise<Array<OnlineUserInfo>>
getSelection
() => Promise<Array<Unsupported | Connector | AppCard | Card | Embed | '...'>>
getUserInfo
() => Promise<UserInfo>
goToLink
(item: BaseItem) => Promise<boolean>
group
(props: CreateGroupProps) => Promise<Group>
notifications
Notifications
remove
(item: BaseItem) => Promise<void>
select
(filter?: F) => Promise<QueryReturn<Connector | AppCard | Card | Embed | Image | '...', F>>
sendBehindOf
(items: OneOrMany<BaseItem>, target: BaseItem) => Promise<void>
sendToBack
(items: OneOrMany<BaseItem>) => Promise<void>
setAppData
(key: string, value: title="Json">Json) => Promise<D_1>
setMetadata
(item: BaseItem, key: string, value: title="Json">Json) => Promise<D>
storage
Storage
sync
(item: BaseItem) => Promise<void>
timer
Timer
ui
BoardUI
viewport
Viewport