こんにちは、最近は寒すぎて電気カーペットの上で直接寝てしまう木佐貫(@nori4k)です。
非エンジニアとのタスク共有にWunderlistを使っています。
機能もUIもシンプルで分かりやすいので普段はスマホくらいしか触らない人でも負担なく導入することができとても重宝しています。
WunderlistからAPIも提供されているのでどんな風につかうのか早速試してみました。
Wunderlist とは
Wunderlist は、タスク管理を支援するシンプルな ToDo リスト アプリです。家族との買い物リストの共有からプロジェクト管理、休暇の計画まで、Wunderlist を使えば、ToDo の入力、共有、そして実行を簡単に行うことができます。Wunderlist はスマートフォン、タブレット、PC の間で瞬時に同期するAため、あらゆるタスクにどこからでもアクセスできます。
(iPhoneアプリの説明欄から引用)
Wunderlistではリスト - タスク - サブタスク の3階層構造でタスクを管理する仕組みになっています。
例えば、「買い物」というリストがあり、その中に「ティッシュ」「ミルク」「醤油」「夕飯の買い出し」などのタスクを作って管理します。場合によっては「夕飯の買い出し」に更にサブタスクを作ることができます。
また、リストをカテゴリ分けするためのフォルダという機能もあります。
これは文字通りリストをフォルダ分けすることができる機能です。
APIを使うための準備
APIを利用するためにはClientIDとAccessTokenが必要です。
-
register your app をクリック
-
Create NewAppという画面が開くので必要情報を入力
今回は次のように入力しsaveをクリック
Name: hoge
Description: hogehoge
App icon: なし
App url: http://myapp.net
Auth Callback url: http://myapp.net -
My Appという画面が開く
ClientIDをメモする。
Create Access TokenをクリックしてAccessTokenを生成しメモしておく。
これでAPIを使用する準備が整いました!
APIの動作確認
今回はcurlを使ってAPIの動作を見てみることにします。
詳しくは公式ドキュメントをご覧ください。
リスト一覧の取得
リスト一覧を取得してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/lists
レスポンス
[
{
"created_at": "2017-02-03T16:00:54.570Z",
"id": 289113886,
"list_type": "inbox",
"owner_id": 48481118,
"owner_type": "user",
"public": false,
"revision": 1,
"title": "inbox",
"type": "list"
},
{
"created_at": "2017-02-03T16:01:05.807Z",
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lwf70ac84aecf208b6e54cb227755032",
"id": 289113923,
"list_type": "list",
"owner_id": 48481118,
"owner_type": "user",
"public": false,
"revision": 4,
"title": "食料品",
"type": "list"
}
]
inbox
と食料品
という2つのリストが取得できました。
フォルダ一覧の取得
フォルダ一覧を取得してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/folders
レスポンス
[
{
"created_at": "2017-02-03T16:12:24.161Z",
"created_by_id": 48481118,
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw0e0b4864b5ea8e8300b002d7f656fb",
"id": 6754585,
"list_ids": [
289113923
],
"revision": 2,
"title": "Folder01",
"type": "folder",
"updated_at": "2017-02-03T16:12:29.360Z",
"user_id": 48481118
}
]
タスク一覧の取得
タスク一覧を取得してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/tasks?list_id=289113923
レスポンス
[
{
"completed": false,
"created_at": "2017-02-03T16:06:02.482Z",
"created_by_id": 48481118,
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw9716f473956e5aa3d4e5459e3211e5",
"id": 2501790935,
"list_id": 289113923,
"revision": 2,
"starred": false,
"title": "タスク",
"type": "task"
}
]
タスク一覧が取得できました。この例ではタスクが1つしかありませんでしたが、複数あれば配列の形で一括取得できそうです。
revision
はタスクに対して何かしらの修正が行われたときにインクリメントされるみたいです。
サブタスク一覧の取得
サブタスク一覧を取得してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/subtasks?list_id=289113923
レスポンス
[
{
"completed": true,
"completed_at": "2017-02-03T16:16:49.162Z",
"created_at": "2017-02-03T16:16:39.874Z",
"created_by_id": 48481118,
"created_by_request_id": "subtask:498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw332052f52407696b86632c27d0c9f1",
"id": 1363942139,
"revision": 2,
"task_id": 2501790935,
"title": "サブタスク1",
"type": "subtask"
},
{
"completed": false,
"created_at": "2017-02-03T16:16:46.296Z",
"created_by_id": 48481118,
"created_by_request_id": "subtask:498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lwe9ed06158ac87dcd846b060d671630",
"id": 1363942171,
"revision": 1,
"task_id": 2501790935,
"title": "サブタスク3",
"type": "subtask"
},
{
"completed": false,
"created_at": "2017-02-03T16:16:42.900Z",
"created_by_id": 48481118,
"created_by_request_id": "subtask:498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw34349df41802ba2c13f4faecfa5d18",
"id": 1363942150,
"revision": 1,
"task_id": 2501790935,
"title": "サブタスク2",
"type": "subtask"
}
]
サブタスク一覧が取得できました。
list_idを指定することで、リスト内のサブタスクを一括取得できるのが便利です。
もちろんtask_idをしていすることで特定のタスク配下のサブタスクのみを取得することも可能です。
メモ一覧の取得
メモ一覧を取得してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/notes?list_id=289113923
レスポンス
[
{
"content": "こちらがノート",
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lwef206de86e88ab1d34ad3e39f08f7d",
"id": 172985213,
"revision": 1,
"task_id": 2501790935,
"type": "note"
}
]
コメント一覧の取得
コメント一覧を取得してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/task_comments?list_id=289113923
レスポンス
[
{
"author": {
"avatar": "https://a.wunderlist.com/api/v1/avatar?user_id=48481118",
"id": 48481118,
"name": "your name"
},
"created_at": "2017-02-03T16:13:17.000Z",
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw242a3dc76707a21b3661383e388407",
"id": 54718254,
"local_created_at": "2017-02-03T16:13:21.711Z",
"revision": 1,
"task_id": 2501790935,
"text": "コメントだよ",
"type": "task_comment"
}
]
添付ファイル一覧の取得
添付ファイル一覧を取得してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/files?list_id=289113923
レスポンス
[
{
"content_type": "image/png",
"created_at": "2017-02-03T16:15:04.303Z",
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw7f6545b24ab8d9e4cd8bff539f903f",
"file_name": "SnapCrab_My Apps Wunderlist Developer - Google Chrome_2017-2-4_1-4-55_No-00.png",
"file_size": 147744,
"id": 22489318,
"local_created_at": "2017-02-03T16:15:04.000Z",
"revision": 1,
"task_id": 2501790935,
"type": "file",
"updated_at": "2017-02-03T16:15:04.646Z",
"url": "https://download.wunderlist.io/d519bf30-cc59-0134-9abe-22000a0a0772-1486138498-834452?AWSAccessKeyId=AKIAJEN6W4AO3LJODOAA&Expires=1488557704&Signature=vr%2BPL9WLuhP8wF4gY%2FOS3uf%2BdyE%3D",
"user_id": 48481118
}
]
webhookの作成
Webhookも試してみます。
Webhookを登録しておくとWunderlistに変更があった場合に変更内容の通知を受け取ることができます。
ポーリングする必要がなくなるのでWunderlistと連携したアプリ開発をするときには必須ですね。
webhookはリスト毎に設定でき、一つのリストに複数のwebhookを設定できます。
url=xxxxxx
の部分にcallback URLを設定します。
curl -H "X-Access-Token: xxxxxx" \
-H "X-Client-ID: yyyyyy" \
-X POST \
-F "list_id=289113923" \
-F "url=http://myapp.net/callback.php" \
-F "processor_type=generic" \
-F "configuration=" \
a.wunderlist.com/api/v1/webhooks
callback.phpも用意しておきます。
<?php
$json_string = file_get_contents('php://input');
echo $json_string;
$obj = json_decode($json_string);
var_dump($obj);
レスポンス
{
"id": 2502681,
"list_id": 289113923,
"url": "http://myapp.net/callback.php"
}
最初はコールバックURLをhttps
で指定していたのですが、wunderlist側からのアクセスがあるもののjsonを受け取ることができせんでした。SSLを諦めてhttp
で指定したら無事jsonを受け取れるようになりました。
SSL化に無料で使える"Let's Encrypt"の証明書を使っていたのが悪かったのかもしれません。
webhookの取得
設定されたwebhookの情報を取得してみます。
リスト毎にしか取得できないので、全リストのwebhookを一括取得できるAPIもほしい。。。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" a.wunderlist.com/api/v1/webhooks?list_id=289113923
レスポンス
[
{
"id": 2502681,
"list_id": 289113923,
"url": "http://myapp.net/callback.php"
}
]
webhookの削除
webhookを削除してみます。
curl -H "X-Access-Token: xxxxxx" -H "X-Client-ID: yyyyyy" -X DELETE a.wunderlist.com/api/v1/webhooks/2502681
レスポンス
なし
webhookを削除するには「webhookの取得」で取得したwebhookのidを指定します。
思い込みでlist_idを指定していてエラーの原因がわかるのに小一時間くらいかかりました。。。
callbackされるjson
通知はタスク / サブタスク / メモ / ファイル / コメント などの作成・更新・削除のタイミングで行われます。
リストの共有なぜか通知されなかったです。
タスクを完了させたときのjsonを参考に掲載しておきます。
{
"after": {
"completed": true,
"completed_at": "2017-02-03T22:17:06.268Z",
"completed_by_id": 48481118,
"created_at": "2017-02-03T16:06:02.482Z",
"created_by_id": 48481118,
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c291:f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw9716f473956e5aa3d4e5459e3211e5",
"id": 2501790935,
"is_recurrence_child": false,
"list_id": 289113923,
"revision": 41,
"starred": false,
"title": "タスク",
"updated_at": "2017-02-03T22:17:06.271Z",
"updated_by_id": 48481118
},
"before": {
"completed": false,
"created_at": "2017-02-03T16:06:02.482Z",
"created_by_id": 48481118,
"created_by_request_id": "498d3ffc44ddfa2f275b:92840a96-1d01-463c-956b-dff9594c2941:f43d7f5-5be5-45b1-a70c-b3a9-7dc9583d:48481118:lw9716f473956e5aa3d4e5459e3211e5",
"id": 2501790935,
"is_recurrence_child": false,
"list_id": 289113923,
"revision": 40,
"starred": false,
"title": "タスク",
"updated_at": "2017-02-03T22:17:05.319Z",
"updated_by_id": 48481118
},
"cause": null,
"client": {
"device_id": "92840a96-1d01-463c-956b-dff9594c2941",
"id": "498d3ffc44ddfa2f275b",
"instance_id": "f43da7f5-5be5-45b1-a70c-b3a9-7dc9583d",
"request_id": "15b8ced2-99b8-4798-8785-3827-91ff2fd9",
"user_id": "48481118"
},
"data": {
"completed": true,
"completed_at": "2017-02-03T22:17:06.268Z",
"completed_by_id": 48481118,
"revision": 41,
"updated_at": "2017-02-03T22:17:06.271Z"
},
"enqueued_at": 1486160226.2807422,
"operation": "update",
"subject": {
"id": 2501790935,
"parents": [
{
"id": 289113923,
"type": "list"
}
],
"previous_revision": 40,
"revision": 41,
"type": "task"
},
"type": "mutation",
"user_id": 48481118,
"version": 1
}
URL Scheme
APIとは直接関係ない話になってしまいますが、
iPhoneにはURL Schemeという機構があり、URL形式のリンクをクリックすることでアプリを起動させることができます。(Androidでもあるんでしたっけ?)
WunderlistもURL Schemeに対応しているのですが公式ドキュメントにも説明がなかったので私が見つけたURL Schemeをメモしておきます。
アプリの起動
wunderlist://
特定のリスト
wunderlist://lists/:list_id
特定のタスク
wunderlist://tasks/:task_id
スター付きのタスク
wunderlist://lists/starred
期限が今日までのタスク
wunderlist://lists/today
期限が今週までのタスク
wunderlist://lists/week
すべてのタスク
wunderlist://lists/all
完了済みのタスク
wunderlist://lists/completed
自分に割り当てられたタスク
wunderlist://lists/assigned
感想
apiの構想がシンプルなので学習コストが低くすぐに使えるようになりました。
calbackの受取にすこしハマったのでそこくらいですね。