Board
board
is a property of window.miro
that enables:
- Setting up your app.
- Making
board
and its properties available, as well as the Miro Web SDK methods.
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 viaawait miro.board.canUse('timer')
.
collaboration
Collaboration
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
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 methodbringToFront()
, 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 forapp_card:open
is to open a modal displaying content fetched from a specified URL.
For more information, seeapp_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:
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
andend
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
andposition.y
coordinates of each point. - Or specify the
snapTo
property for each point. - You cannot specify both
position
coordinates andsnapTo
properties for thestart
andend
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
andy
board coordinates where you want the content to be embedded.width
andheight
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
andheight
are set based on the corresponding retrieved values for the resource. - If
width
andheight
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:
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:
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):
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 tored
. - 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:
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:
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 itemid
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 itemtype
to deselect items matching the requested type.
Pass an array of types to deselect items matching one of the specified types. If you pass typegroup
, 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
andy
: define the starting central point to begin the search for an empty space.width
andheight
: 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 tagid
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 itemtype
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:
- To access app metadata, apps require the
boards:read
permission. - To store app metadata to the board, apps require the
boards:write
permission. getAppData
returns a new object, not a reference to the object that was previously set withsetAppData
.- If the specified key isn't found, the method returns
undefined
.
⚠️ 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 aBearer
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>
- callinggetLayerIndex()
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:
- Frames
- Unsupported board items
- groups
ℹ️ Note:
- To access board item metadata, apps require the
boards:read
permission. - To store board item metadata, apps require the
boards:write
permission. getMetadata
returns a new object, not a reference to the object that was previously set withsetMetadata
.- If the specified key isn't found, the method returns
undefined
.
⚠️ 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 thelinkedTo
property contains a valid value.false
: Link is not successfully associated to the item due to an invalid or missinglinkedTo
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 theboards: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, useremove()
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 itemid
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 itemtype
to select items matching the requested type.
Pass an array of types to select items matching one of the specified types. If you pass typegroup
, 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 methodsendToBack()
, 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
, orundefined
.
This clears the key. If you callgetAppData(key)
to retrieve a key that has been set tonull
orundefined
, the method returnsundefined
.
ℹ️ 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:
- Frames
- Unsupported board items
- groups
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
, orundefined
.
This clears the key. If you callgetMetadata(key)
to retrieve a key that has been set tonull
orundefined
, the method returnsundefined
.
ℹ️ Note:
- To access board item metadata, apps require the
boards:read
permission. - To store board item metadata, apps require the
boards:write
permission. - 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
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
Property | Type |
---|---|
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 |
Updated 2 months ago