await miroFetch(`/v2/boards/${boardId}`, 'PATCH', {
name: 'Sprint Retro — Week 12 (CLOSED)',
description: 'Archived — action items in Jira',
});
const note = await miroFetch(`/v2/boards/${boardId}/sticky_notes`, 'POST', {
data: { content: 'Went well: team communication', shape: 'square' },
style: { fillColor: 'light_green', textAlign: 'center' },
position: { x: -200, y: 0 },
geometry: { width: 199 },
});
const shape = await miroFetch(`/v2/boards/${boardId}/shapes`, 'POST', {
data: { content: 'Decision Point', shape: 'rhombus' },
style: { fillColor: '#ff6b6b', borderColor: '#333333', borderWidth: 2 },
position: { x: 0, y: 200 },
geometry: { width: 200, height: 200 },
});
const card = await miroFetch(`/v2/boards/${boardId}/cards`, 'POST', {
data: {
title: 'Improve deploy pipeline',
description: 'Reduce deploy time from 15min to 5min',
dueDate: '2025-04-01T00:00:00Z',
assigneeId: 'user-id-123',
},
style: { cardTheme: '#2d9bf0' },
position: { x: 200, y: 0 },
});
const frame = await miroFetch(`/v2/boards/${boardId}/frames`, 'POST', {
data: {
title: 'What went well',
format: 'custom',
type: 'freeform',
showContent: true,
},
position: { x: -400, y: -200 },
geometry: { width: 600, height: 400 },
});
const text = await miroFetch(`/v2/boards/${boardId}/texts`, 'POST', {
data: { content: '<strong>Action Items</strong>' },
style: { fontSize: 24, textAlign: 'left' },
position: { x: 0, y: -300 },
geometry: { width: 300 },
});
await miroFetch(`/v2/boards/${boardId}/sticky_notes/${noteId}`, 'PATCH', {
data: { content: 'Updated: team communication was excellent' },
style: { fillColor: 'light_blue' },
});
const tag = await miroFetch(`/v2/boards/${boardId}/tags`, 'POST', {
title: 'Action Item',
fillColor: 'red',
});
await miroFetch(`/v2/boards/${boardId}/items/${noteId}/tags`, 'POST', {
tagId: tag.id,
});
const members = await miroFetch(`/v2/boards/${boardId}/members?limit=50`);
await miroFetch(`/v2/boards/${boardId}/members`, 'POST', {
emails: ['colleague@company.com'],
role: 'commenter',
message: 'Check out our retro board!',
});
async function miroFetch(path: string, method = 'GET', body?: unknown) {
const response = await fetch(`https://api.miro.com${path}`, {
method,
headers: {
'Authorization': `Bearer ${process.env.MIRO_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
...(body ? { body: JSON.stringify(body) } : {}),
});
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new Error(`Miro ${method} ${path}: ${response.status} ${error.message ?? ''}`);
}
if (response.status === 204) return null;
return response.json();
}