Miro API入門

### 2020/3/17追記

[ZOZO TECH BOOK VOL.1](https://techbookfest.org/product/5468500248231936)の第4章でMiro Web-Plugin SDKの概要から使い方、Miroアプリの作り方まで紹介しています。もしご興味ある方は是非！より詳細な目次は[弊社ブログ記事](https://techblog.zozo.com/entry/techbookfest-zozotechbook1)から確認できます！

# はじめに
この記事は[ZOZOテクノロジーズ #5 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech5)の25日目の記事となります。
昨日は、@taquaki-satwoさんの「[インフラ未経験でAWS認定クラウドプラクティショナーを受けてきたのでレポートします](https://qiita.com/taquaki-satwo/items/97ec90764cadfeec016d)」でした。

また、今年は全部で5つのAdvent Calendarが公開されています。

[ZOZOテクノロジーズ #1 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech)
[ZOZOテクノロジーズ #2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech2)
[ZOZOテクノロジーズ #3 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech3)
[ZOZOテクノロジーズ #4 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech4)
[ZOZOテクノロジーズ #5 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zozo_tech5)

# Miroとは？

[Miro](https://miro.com/)は仮想的なホワイトボードを複数人でリアルタイムに編集できるサービスです。Webブラウザ版の他、Mac/Windowsアプリ、iOS/Androidアプリが公開されています(詳細は[こちら](https://miro.com/apps/))。

実際のホワイトボードを使う感覚で図を書き付箋を貼ることもできますが、3rdパーティーのアプリ(Slack、JIRA、コンフルなど多数)との連携や、スクリーンキャストやビデオチャット、画像や動画を貼るなど多種多様な使い方ができるのも魅力です。公式サイトトップの動画を見るとどんなものなのか具体的イメージが掴めるかと思います。

企業での使用事例としては、Ubie社の事例がとても参考になります。

[チームコラボレーションサービス「Miro」いいなぁという話](http://sys1yagi.hatenablog.com/entry/2019/12/10/090303)

ZOZOテクノロジーズでも全社で導入する前の検証として有料版を一部のチーム(ZOZOTOWNアプリチームなど)で利用しはじめています。検証のためにiPad ProとApple Pencilの購入申請をしたので届くのが楽しみです！

# Miro API

MiroにはWeb-Plugins SDKとREST APIが用意されています。

https://miro.com/api/

この記事では、REST APIについて紹介します。

# 準備

Miro REST APIへ実際にリクエストを投げるには次のステップが必要です。

- ステップ 1 — Developer Teamの登録
- ステップ 2 — アプリの作成
- ステップ 3 — Scopeの確認
- ステップ 4 — Tokenの発行

## Developer Teamの登録

Build Your Appの「[Step 1 — Get developer team](https://developers.miro.com/docs/getting-started#section-step-1-get-developer-team)」を開き、「Get Dev Team to Create an App」をクリックします。

|<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/072edbe0-bc15-6623-7dd7-060f0d8c8316.png">|
|:-:|

次のダイアログが表示されるので「Build app」をクリックします。

|<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/ded761ce-f754-202d-cda2-d2bc510b4276.png">|
|:-:|

## アプリの作成

Profile settingsのAPI,SDK & Embedから「Create new app」をクリックします。

|<img width="800" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/68bc896a-05c0-dd20-ebba-ce4fd4e8926b.png">|
|:-:|

次のダイアログが表示されるので「App name」と「Description」を入力します。teamは「Dev team」が選択されているはずです。「Create App」をクリックすればアプリが作成されます。

|<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/ce326e5d-e2c7-4ffc-b884-9cf4c5975858.png">|
|:-:|

作成したアプリは次のように「Created apps」の項目に表示されます。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/2b9b97dd-5e30-188c-4622-6542a7b7d62b.png)|
|:-:|

## Scopeの確認

アプリで提供したい機能を実現するためにどのScopeが必要なのか確認します。こちらのページから確認しましょう。

https://developers.miro.com/reference#scopes

今回は`boards:read`と`boards:write`を使用してボードを操作してみようと思います。

## Access Tokenの発行

作成したアプリの詳細ページの「OAuth scopes」からAccess Tokenを発行できます。`boards:read`と`boards:write`にチェックを付け、「Install app and get OAuth Token」をクリックします。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/2a99e9a5-e6a2-3017-3f28-3a7a688b2649.png)|
|:-:|

「Dev team」を選択し、「Install」をクリックします。これでAccess Tokenを発行できました。

|<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/a06205fb-0f3a-3c00-400d-d7bf11501606.png">|
|:-:|

# APIリクエストを実行する

Access Tokenを取得したので実際にAPIリクエストを実行してみます。個人的にMiroで気に入っている点の一つがAPIリファレンスがとてもわかりやすいところで、APIリファレンスで実際にAPIを叩いて試すことができます。

## Boardを作る

Boardを作るには、Boards APIを使用します。APIリファレンスはこちらを参照します。

https://developers.miro.com/reference#create-board

### Access Tokenの入力

人型のアイコンをクリックすると次のようにフォームが開くので、先程取得したTokenを入力します。これで「Try」をクリックすることでAPIを実際に試せます。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/3c3b9890-b78f-5c87-0132-264ffdd3e5bc.png)|
|:-:|

### リクエストパラメータの入力

APIリファレンスのBODY PARAMSでパラメータを入力できます。パラメータ`name`と`description`を次のように設定しました。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/da829ca7-e38a-1d99-14dd-6edbc1745cf6.png)|
|:-:|

実際に実行してみるとBoardが作成されました！

|<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/387959ce-4ae1-4400-5a2b-9978077b49c1.png">|
|:-:|

また、cURL、Node、Ruby、JavaScript、Pythonの5つの方法でサンプルコードが提供されるので、実際にAPIを利用して実装する際の参考になります。

|<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/53197a2b-7125-4f8c-eae1-b003459e9432.png">|
|:-:|

### レスポンスのフィールドを制御する

「QUERY PARAMS」のfieldパラメータに値をセットすることでfieldでレスポンスのフィールドを制御することができます。

filedパラメータに何も指定しない場合次のようなレスポンスになります。

```json
{
  "type":"board"
  "viewLink":"https://realtimeboard.com/app/board/o9J_kvsCTts="
  "description":"メリークリスマス"
  "sharingPolicy":{...}
  "picture":NULL
  "account":{...}
  "team":{...}
  "currentUserConnection":{...}
  "name":"Mery Christmas🎄🎅🎄"
  "id":"1234_56789"
  "owner":{...}
  "modifiedAt":"2019-12-24T16:59:50Z"
  "modifiedBy":{...}
  "createdAt":"2019-12-24T16:59:50Z"
  "createdBy":{...}
}
```

ここで、fieldパラメータに`name`を指定してみます。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/1b3309ae-b813-fafe-005a-347afb3724ed.png)|
|:-:|

その結果、レスポンスは次のようになります。

```json
{
  "type":"board"
  "name":"Mery Christmas🎄🎅🎄"
  "id":"1234_56789"
}
```

## Widgetを作る

WidgetはBords上に自由に配置できるオブジェクトで、様々なタイプがあります。Widgetを作るにはwidgets APIを使用します。

https://developers.miro.com/reference#create-board-widgets

Widgetの作成には、Pathパラメータとして`board id`を指定し、BodyパラメータにjsonでWidgetのtypeに応じて必要なデータを記述します。

|<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/30638ff4-0090-d5cb-5e7c-446769f6727d.png">|
|:-:|

Widgetタイプの一覧は[こちら](https://developers.miro.com/reference#widget-types)から確認でき、代表的Widgetは次の通りです。

- Sticker
- Shape
- Text
- Line
- Card

### Stickerを作る

Stickerは付箋です。実際のホワイトボードに貼り付ける感覚で使えます。Stickerを作るには、リクエストBodyに次のようなjsonを指定します。

`type`はWidgetの種類を表し、`sticker`を指定します。`text`にはStickerで表示したい文字列を指定します。

```json
{
  "type": "sticker",
  "text": "<p>My Sticker</p>"
}
```

リクエストを実行すると次のように作成されます。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/c282b54e-306a-8f86-7377-b458e7617d10.png">

最低限`text`パラメータを指定すれば作れますが、`style`を指定することでより見た目をカスタマイズすることが可能です。`backgroundColor`でStickerの背景を指定し、`textAlign left`で左寄せにしてみます。

`backgroundColor`に指定できる色は予め決められており、次の中から選択する必要があります。

```
#f5f6f8, #fff9b1, #f5d128, #d0e17a, #d5f692, #a6ccf5, 
#67c6c0, #23bfe7, #ff9d48, #ea94bb, #f16c7f, #b384bb
```

`#ea94bb`を指定し、次のパラメータでリクエストします。

```json
{
  "type": "sticker",
  "text": "<p>My Sticker</p>",
  "style": {
    "backgroundColor": "#ea94bb",
    "textAlign": "left"
  }
}
```

作成できました！

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/732bd1ec-1ecc-6b67-9f10-5329eb25b5a9.png">

その他に指定できるパラメータについてはこちらをご覧ください。

https://developers.miro.com/reference#sticker

### Shapeを作る

Shapeでは様々な形状のオブジェクトを作成できます。Shapeを作るには`type`に`shape`を指定します。`text`にはShapeに表示したい文字列を指定します。

```json
{
  "type": "shape",
  "text": "<p>My Shape</p>"
}
```

これでShapeを作成できました。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/64983300-e39d-c5fc-4553-4579bab3e9a2.png">

これだけではシンプルすぎるのでカスタマイズしましょう。`style`にいくつかパラメータを指定します。`shapeType`ではShapeの形状を指定できます。指定できる形状は次の通りです。

```:allowed_shape_list
rectangle, circle, triangle, rounded_rectangle, "rhombus,
callout, parallelogram, star, arrow, arrow_left, pentagon,
hexagon, octagon, trapeze, predefined_process, arrow_left_right,
cloud, brace_left, brace_right, cross, barrel
```

`shapeType`に`octagon`、`backgroundColor`に`#ffae2b`、`fontFamily`に`Fredoka One`を指定してみます。


```json
{
  "type": "shape",
  "text": "<p>My Shape</p>",
  "style": {
    "shapeType": "octagon",
    "backgroundColor": "#ffae2b",
    "fontFamily": "Fredoka One"
  }
}
```

作成できました！

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/678ed53b-a390-afa3-2149-03b89c779b07.png">

その他に指定できるパラメータについてはこちらをご覧ください。

https://developers.miro.com/reference#shape

### Textを作る

Textでは文字列をBoard上に表示します。Textを作るには`type`に`text`を指定します。`text`には表示したい文字列を指定します。

```json
{
  "type": "text",
  "text": "<p>My Text</p>"
}
```

これでTextを作成できました。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/1e1e765a-d8c2-cc1a-8abc-d3339c7885c8.png">

他のwidgetと同様`style`で文字サイズやカラー等を指定できます。指定できるパラメータについてはこちらをご覧ください。

https://developers.miro.com/reference#text

### Lineを作る

Lineは、２つのオブジェクトを繋ぐ線を作成できます。Lineを作成するには、`startWidget`で始点となるWidgetの`id`を指定し、`endWidget`で終点となるWidgetの`id`を指定します。

Shapeでは様々な形状のオブジェクトを作成できます。Shapeを作るには`type`に`shape`を指定します。`text`にはShapeに表示したい文字列を指定します。

次のようにBodyパラメータを作成し予め作成したShape Widget2つをLineで繋いでみます。

```json
{
  "type": "line",
  "startWidget": {
    "id": "111111"
  },
  "endWidget": {
    "id": "222222"
  }
}
```

次のように2つのWidgetをLineで繋ぐことができました。

<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/fabf8620-1bf5-b0eb-c73e-cd18417609b9.png">

Lineをカスタマイズしてみます。`borderColor`に`#c71585`、`borderWidth`に`4.0`、`lineEndType`に`open_arrow`、`lineType`に`orthogonal`を指定します。

```json
{
  "type": "line",
  "startWidget": {
    "id": "111111"
  },
  "endWidget": {
    "id": "222222"
  },
  "style": {
    "borderColor": "#c71585",
    "borderWidth": 4.0,
    "lineEndType": "open_arrow",
    "lineType": "orthogonal"
  }
}
```

これで、次のようなLineを作成できました。

<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/733cb7ad-5fd3-7786-11ca-9e17e008d78b.png">


その他指定できるパラメータはについてはこちらをご覧ください。

https://developers.miro.com/reference#line

### Cardを作る

Cardはタイトルやデスクリプション、日付、Assigneeといった情報を表示できます。

Shapeでは様々な形状のオブジェクトを作成できます。Shapeを作るには`type`に`card`を指定します。`title`にはCardに表示したい文字列を指定します。

```json
{
  "type": "card",
  "title": "<p>My Card</p>"
}
```

もっともシンプルなCardを作成できました。

<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/756f40cb-aaa1-6a1d-2a85-6548360d3d4d.png">

デスクリプション、日付、Assigneeといった情報を追加します。

```json
{
  "type": "card",
  "title": "<p>アドベントカレンダーを書く</p>",
  "description": "<p>忘れない</p>",
  "date": "2019-12-25",
  "assignee": {
    "userId": "123456789"
  }
}
```

次のようにCardに情報を追加できました。

<img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/a04006b2-b5b2-ad24-12a4-38ab3e405c67.png">

デスクリプションの表示はこうなります。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/e1ce0db2-f82e-e8a5-bbce-970c853837ed.png">

その他の設定についてはこちらをご覧ください。

https://developers.miro.com/reference#card

# Web-Plugins SDK

Miroには、REST APIの他にWeb-Plugins SDKが用意されています。SDKは簡単に試すことができます。

まず、ボードを開きChromeのdev-toolsのconsoleを開きます。そして、`loadSDK()`を実行するとSDKがconsoleにロードされ、これで準備完了です。

次のコードは、Miroのdeveloperドキュメントで公開されているコードです。これをconsoleに貼り付けて実行します。

```javascript
const waitOneSec = () => new Promise(r => setTimeout(r, 1000))
let sticker = (await miro.board.widgets.create({type:'sticker', text: 'Hello'}))[0]
await miro.board.viewport.zoomToObject(sticker)
await waitOneSec() // timeout only for demo purpose
await miro.board.widgets.update({id: sticker.id, text: 'world!', style:{stickerBackgroundColor:'#7ac673'}}) // update sticker
await waitOneSec()
await miro.board.widgets.deleteById(sticker.id) // delete sticker
```

実行した結果はこちらです。数行のコードで簡単にボードを制御できました。

![12月-25-2019 20-23-19.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43438/23afba23-162e-59ce-fa63-479cdee7d176.gif)

Web-Plugins SDKを使用すると、iFrameを使用したMicro frontendsとしてプラグインを作成することができ、Miroにインストールして使用できるようになります。Miroのメニューに新しいボタンを追加するといったことも可能ですので、自由度が高いプラグイン開発ができそうです。

今回の記事ではWeb-Plugins SDKについて紹介しませんが、別途記事を書きたいと思います。

# まとめ

非常に多くのサービスやツールと連携でき、SDKやAPIが公開されているので自作のプラグインを開発することが可能なため、既存のワークフローに柔軟に取り込むことが可能だと感じています。今後、社内の開発フローにMiroを取り入れて開発フローの効率化を行っていきたいです。

# 最後に

会社のAdvent Calendarが5つもできてそれが全て埋まり、そして全て完走するなんてすごい！お疲れさまでした🎉🎉🎉

# 参考資料

- https://developers.miro.com/docs