Skip to content
OpenSmartRoute
Skillv1.0.0

miro-hello-world

Create a minimal working Miro example with real board and item operations. Use when starting a new Miro integration, testing your setup, or learning the Miro REST API v2 item model. Trigger with phras

by jeremylongshore(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from jeremylongshore/tons-of-skills-marketplace (skills/.curated/miro-hello-world/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill miro-hello-world. Copyright stays with the author (MIT).

Miro Hello World

Overview

Minimal working example: create a board, add a sticky note, add a shape, connect them, and read the results back — all using the Miro REST API v2.

Prerequisites

  • Completed miro-install-auth setup
  • Valid access token with boards:read and boards:write scopes
  • @mirohq/miro-api installed

Instructions

Step 1: Create a Board

import { MiroApi } from '@mirohq/miro-api';

const api = new MiroApi(process.env.MIRO_ACCESS_TOKEN!);

async function createBoard() {
  // POST https://api.miro.com/v2/boards
  const response = await api.createBoard({
    name: 'Hello World Board',
    description: 'Created via REST API v2',
    policy: {
      sharingPolicy: {
        access: 'private',          // 'private' | 'view' | 'comment' | 'edit'
        inviteToAccountAndBoardLinkAccess: 'no_access',
      },
      permissionsPolicy: {
        collaborationToolsStartAccess: 'all_editors',
        copyAccess: 'anyone',
        sharingAccess: 'owners_and_coowners',
      },
    },
  });

  const boardId = response.body.id;
  console.log(`Board created: ${boardId}`);
  console.log(`View at: https://miro.com/app/board/${boardId}/`);
  return boardId;
}

Step 2: Add a Sticky Note

async function addStickyNote(boardId: string) {
  // POST https://api.miro.com/v2/boards/{board_id}/sticky_notes
  const response = await fetch(
    `https://api.miro.com/v2/boards/${boardId}/sticky_notes`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.MIRO_ACCESS_TOKEN}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        data: {
          content: 'Hello from the API!',
          shape: 'square',          // 'square' | 'rectangle'
        },
        style: {
          fillColor: 'light_yellow', // light_yellow | light_green | light_blue | light_pink | etc.
          textAlign: 'center',       // 'left' | 'center' | 'right'
          textAlignVertical: 'middle',
        },
        position: { x: 0, y: 0 },
        geometry: { width: 200 },
      }),
    }
  );

  const note = await response.json();
  console.log(`Sticky note created: ${note.id} (type: ${note.type})`);
  return note.id;
}

Step 3: Add a Shape

async function addShape(boardId: string) {
  // POST https://api.miro.com/v2/boards/{board_id}/shapes
  const response = await fetch(
    `https://api.miro.com/v2/boards/${boardId}/shapes`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.MIRO_ACCESS_TOKEN}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        data: {
          content: 'Next Step',
          shape: 'round_rectangle',  // rectangle | circle | triangle | rhombus | round_rectangle | etc.
        },
        style: {
          fillColor: '#4262ff',
          fontFamily: 'arial',
          fontSize: 14,
          textAlign: 'center',
          borderColor: '#1a1a2e',
          borderWidth: 2,
          borderStyle: 'normal',     // 'normal' | 'dashed' | 'dotted'
        },
        position: { x: 400, y: 0 },
        geometry: { width: 200, height: 100 },
      }),
    }
  );

  const shape = await response.json();
  console.log(`Shape created: ${shape.id} (type: ${shape.type})`);
  return shape.id;
}

Step 4: Connect Items with a Connector

async function connectItems(boardId: string, startId: string, endId: string) {
  // POST https://api.miro.com/v2/boards/{board_id}/connectors
  const response = await fetch(
    `https://api.miro.com/v2/boards/${boardId}/connectors`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.MIRO_ACCESS_TOKEN}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        startItem: { id: startId },
        endItem: { id: endId },
        captions: [{ content: 'leads to' }],
        style: {
          strokeColor: '#1a1a2e',
          strokeWidth: 2,
          startStrokeCap: 'none',
          endStrokeCap: 'stealth',   // none | stealth | arrow | filled_triangle | etc.
        },
      }),
    }
  );

  const connector = await response.json();
  console.log(`Connector created: ${connector.id}`);
  return connector.id;
}

Step 5: List All Items on the Board

async function listBoardItems(boardId: string) {
  // GET https://api.miro.com/v2/boards/{board_id}/items
  // Returns cursor-paginated results
  const response = await fetch(
    `https://api.miro.com/v2/boards/${boardId}/items?limit=50`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.MIRO_ACCESS_TOKEN}`,
      },
    }
  );

  const result = await response.json();
  console.log(`Board has ${result.data.length} items:`);
  for (const item of result.data) {
    console.log(`  - ${item.type}: ${item.id} (${item.data?.content ?? 'no content'})`);
  }

  // Handle pagination
  if (result.cursor) {
    console.log(`More items available. Next cursor: ${result.cursor}`);
  }
}

Step 6: Run the Complete Flow

async function main() {
  const boardId = await createBoard();
  const noteId = await addStickyNote(boardId);
  const shapeId = await addShape(boardId);
  await connectItems(boardId, noteId, shapeId);
  await listBoardItems(boardId);
  console.log('\nDone! Open the board in Miro to see your items.');
}

main().catch(console.error);

Miro REST API v2 Item Types

Type Create Endpoint Key Properties
sticky_note /v2/boards/{id}/sticky_notes content, shape, fillColor
shape /v2/boards/{id}/shapes content, shape, fillColor, borderStyle
card /v2/boards/{id}/cards title, description, dueDate, assigneeId
text /v2/boards/{id}/texts content, fontSize
frame /v2/boards/{id}/frames title, showContent, childrenIds
image /v2/boards/{id}/images url or data (base64)
document /v2/boards/{id}/documents url
embed /v2/boards/{id}/embeds url
app_card /v2/boards/{id}/app_cards title, description, fields, status
connector /v2/boards/{id}/connectors startItem, endItem, captions

All create endpoints require boards:write scope. All GET endpoints require boards:read.

Output

Following this guide produces the Miro integration outcome for its topic—configuration, validation evidence, operational recovery, or a documented migration result. Record command output and relevant identifiers so a failed step is traceable.

Examples

Start with the smallest applicable command or code example in the relevant section, using a dedicated test board and non-production credentials. Confirm the expected response or validation result before applying the pattern to production.

Error Handling

Error HTTP Status Cause Solution
boardNotFound 404 Invalid board_id Verify board exists and token has access
insufficientPermissions 403 Missing boards:write Add scope in app settings
invalidInput 400 Bad request body Check required fields per item type
rateLimitExceeded 429 Too many requests Implement backoff (see miro-rate-limits)

Resources

Next Steps

Proceed to miro-local-dev-loop for development workflow setup, or miro-core-workflow-a for board management patterns.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/jeremylongshore-tons-of-skills-marketplace-miro-hello-world/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

jeremylongshore-tons-of-skills-marketplace-miro-hello-world.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-miro-hello-world",
  "kind": "skill",
  "name": "miro-hello-world",
  "description": "Create a minimal working Miro example with real board and item operations. Use when starting a new Miro integration, testing your setup, or learning the Miro REST API v2 item model. Trigger with phrases like \"miro hello world\", \"miro example\", \"miro quick start\", \"first miro board\", \"create miro sticky note\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general_chat",
      "coding"
    ],
    "tags": [
      "skill-md",
      "saas",
      "miro",
      "quickstart",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Create a minimal working Miro example with real board and item operations. Use when starting a new Miro integration, testing your setup, or learning the Miro REST API v2 item model. Trigger with phrases like \"miro hello world\", \"miro example\", \"miro quick start\", \"first miro board\", \"create miro sticky note\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "skills/.curated/miro-hello-world/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/skills/.curated/miro-hello-world/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/skills/.curated/miro-hello-world/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit,",
      "Bash(npm:*),",
      "Bash(npx:*)"
    ],
    "license": "MIT"
  },
  "instructions": "# Miro Hello World\n\n## Overview\n\nMinimal working example: create a board, add a sticky note, add a shape, connect them, and read the results back — all using the Miro REST API v2.\n\n## Prerequisites\n\n- Completed `miro-install-auth` setup\n- Valid access token with `boards:read` and `boards:write` scopes\n- `@mirohq/miro-api` installed\n\n## Instructions\n\n### Step 1: Create a Board\n\n```typescript\nimport { MiroApi } from '@mirohq/miro-api';\n\nconst api = new MiroApi(process.env.MIRO_ACCESS_TOKEN!);\n\nasync function createBoard() {\n  // POST https://api.miro.com/v2/boards\n  const response = await api.cr",
  "cost": {
    "context_tokens": 1930
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-miro-hello-world/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.