はじめに
Twitter の Account Activity API を使う機会があり、こちらの記事を参考に Webhook URL を登録しようとしたのですが、なかなか登録できず、丸一日ほど費やしてしまいました。
Webhook の登録はかなり罠があり、調べても解決法が全然出てこなかったため、この記事では、発生するエラーコードを紹介し、その原因と解決法について解説します。参考になりましたら幸いです。
正しい設定方法だけ見たい
事前準備
Webhook URL を登録する際には POST リクエストを Twitter に送る必要があります。そのリクエストを送るために、本記事では Postmanを利用します。あらかじめアカウント登録し、デスクトップ版アプリをインストールしておいてください。
cURL でもできる気がしますが、罠が多すぎていちいちパラメータをいじるのがめちゃくちゃ大変だったので Postman の使用をおすすめします。
アカウント登録
アカウントを持っていない場合は こちらからアカウントを作成してください。
アプリのインストール
アカウント登録またはサインイン後に Workspaceに行き、画面右下の Desktop Agentから Download desktop agentをクリックしてダウンロードしてください。
または、macOS をお使いの方は Homebrew Cask からインストールすることもできます。
$ brew cask install postman
その後、アプリを起動し、サインインしてください。
アプリをインストールする必要がありますか? ブラウザではダメですか?
Postman は Web 版で使用することもできます。しかし、ブラウザで検証したところ、CORS の制約に引っかかってしまいリクエストを送信することができませんでした。そのためアプリ版を使用する必要があります。
目次
発生したエラーコードの解説だけ知りたい方は以下の目次をご活用ください。
エラーコード 32
エラーメッセージは Could not authenticate youです。「認証できませんでした」ということなのですが、理由が全く書かれていないためこれだけではわかりません。
{"errors":[{"code":32,"message":"Could not authenticate you."}]}公式のトラブルシューティングを見ても「リクエストの認証データに問題がある」ということしかわからず、認証データの「どこ」に問題があるかはわかりません。
ネットで調べてみると、このエラーで苦しんでいる人が多くいるようでした。何を隠そう、自分もこのエラーで苦しみました。
原因
このエラーが発生する原因として考えられるのは、Webhook URL をクエリパラメータとして設定していることです。つまり、リクエストの URL を、以下のように指定しているためです。
https://api.twitter.com/1.1/account_activity/all/:ENV_NAME/webhooks.json?url=https%3A%2F%2Fyour_domain.com%2Fwebhook%2Ftwitter
:ENV_NAMEには、設定した Dev environment label が入ります。何を意味しているかわからない場合は「エラーコード 200」の解説をご覧ください。
公式ドキュメントにはクエリパラメータとして Webhook URL を指定する例が載っているのでこれが正しそうな気がしますが、なぜかこれではうまくいきません。
解決方法
これの解決方法は、POST リクエストの Body にこのパラメータを入れることです。つまり、
↑ こうではなく
↑ こうしてください。
Bodyタブを開き x-www-form-urlencodedを選択して、KEYに url、VALUEにあなたの Webhook URL を指定してください。
このときの注意点として、Webhook URL はパーセントエンコーディングしてはいけません。上記の例で説明すると、https%3A%2F%2Fyour_domain.com%2Fwebhook%2Ftwitterではなく https://your_domain.com/webhook/twitterと記載してください。
エラーコード 261
エラーメッセージは Application cannot perform write actionsです。書き込み権限がないというエラーです。
{"errors":[{"code":261,"message":"Application cannot perform write actions. Contact Twitter Platform Operations through https://help.twitter.com/forms/platform."}]}エラーメッセージに「Twitter プラットフォームオペレータに連絡してください」とありますが、アカウントが凍結したりアプリが停止処理を受けていない限りは連絡しても解決しません。そもそもまだ Webhook URL の登録すらできていないのでアプリが停止処理を受けているなんてことはふつうありえません。
原因
このエラーが発生する原因として考えられるのは、アプリに書き込み権限を与えていないことです。
解決方法
Twitter Portal Dashboardにアクセスし、アプリの権限を変更してやります。
左カラムの Projects & Appsのタブを開き、使用しているプロジェクトまたはアプリを開き、App permissionsを確認します。ここが Read onlyになっている場合は右上の Editをクリックして権限を変更します。
一番下の Read + Write + Direct Messagesを選択して保存します。
DM の権限がいらない場合は、おそらく Read and Writeでも問題ないかもしれませんが、試していません。少なくとも Readではダメです。
次に、Keys and tokensのタブをクリックし、Access token & secretの権限を確認します。先ほど App permissionsで Read onlyになっていた場合は、権限修正後もここが Read onlyになっているかと思います。その場合は Regenerateをクリックしてトークンを再発行します。
トークンが変わるので、再度 Webhook URL 登録のリクエストを送る際に忘れずにトークンを変更してください。
エラーコード 89
エラーメッセージは Invalid or expired tokenです。トークンが無効か期限切れであるというエラーです。
{"errors":[{"code":89,"message":"Invalid or expired token."}]}原因
おそらくこれは先ほどのエラーコード 261 の解決法の手順でトークンを変更したのを忘れていた場合に発生すると思います。
解決方法
Regenerateを実行したあとはキーやトークンが変わるので忘れずに変更してください。
エラーコード 200
エラーメッセージは Forbiddenです。これまたシンプルなメッセージですね。シンプルすぎて原因が不明です。
{"errors":[{"code":200,"message":"Forbidden."}]}原因
このエラーが発生する原因として考えられるのは、Account Activity API の Dev environment label を、認証しようとしているアプリに紐づけていないためです。何を言っているのかわからないかと思いますのでスクリーンショットで解説します。
解決方法
左カラムの Productsのタブを開き、Dev Environmentsを開きます。すると 3 つの環境をセットできる画面が表示されます。そのうちの Account Activity API / Sandboxの項目を見てください。まだ何も設定していない場合は NOT SET UPと表示されているはずです。その場合は Set up dev environmentをクリックし、環境をセットアップしてください。
Dev environment labelと Appを設定するダイアログが表示されます。Dev environment labelには任意の名前、Appは使用しているプロジェクトまたはアプリを選択します。
Dev environment labelは任意と言いましたが、URL の一部となるため、わかりやすい名前にするのが良いです。本番環境で使用するつもりのアプリなら prodや production、開発環境で使用するつもりなら devや developmentなどです。
とりあえずテストで使うなら testとしても良いですが、一度設定してしまうと、あとから環境を作り直しても同じ Dev environment label 名は使用することができないそうなので十分注意してください。
そして、ここで設定した Dev environment label を、Webhook URL を登録する POST リクエストの URL の :ENV_NAMEの部分に当てはめます。
https://api.twitter.com/1.1/account_activity/all/:ENV_NAME/webhooks.json
たとえば Dev environment label を prodcutionとした場合、
https://api.twitter.com/1.1/account_activity/all/production/webhooks.json
としてください。
エラーコード 357
エラーメッセージは url: queryParam is requiredです。Webhook URL が設定されていないのが原因です。
原因
このエラーが発生する原因として考えられるのは、主に Webhook URL を指定し忘れているか、指定するキーが間違っていることです。
解決方法
Postman を使用している場合は、Webhook URL のパラメータにチェックが入っていることと、KEYを間違えていないことを確認してください。正しい KEYは urlです。
エラーコード 34
エラーメッセージは Sorry, that page does not existです。ページが存在しないというエラーです。
{"errors":[{"message":"Sorry, that page does not exist","code":34}]}原因
これはおそらく URL の :ENV_NAMEの部分をそのままにしているパターンです。
解決方法
:ENV_NAMEには Dev environment label を指定します。詳細は「エラーコード 200」の解説を確認してください。
エラーコード 131
エラーメッセージは Internal errorです。その名の通り内部エラーです。エラーが発生してエラー内容が「内部エラー」って何かのとんちですかね?
{"errors":[{"message":"Internal error","code":131}]}原因
これはおそらく Webhook URL をサンプルのまま書いているパターンです。
解決方法
https://your_domain.com/webhook/twitterはあくまで例なので、実際に自分が用意した Webhook URL を使用してください。
エラーコード 214
エラーコード 214 は原因によって 4 種類のエラーメッセージが発生しました。一つずつ解説します。
Unable to connect during CRC GET request
エラーメッセージは Unable to connect during CRC GET requestです。「こちらが指定した Webhook URL に Twitter が GET リクエストを送信したところ、GET リクエストが送信できなかった」というエラーです。
{"errors":[{"code":214,"message":"Unable to connect during CRC GET request."}]}原因
これの原因として考えられるのは、Webhook URL が間違っていて Webhook 先のサーバにアクセスできないということです。Postman で Webhook URL として指定した URL をコピーしてその後ろに ?crc_token=fooとつけてブラウザでアクセスしてください。たとえば以下のような URL です。
https://your_domain.com/webhook/twitter?crc_token=foo
このときブラウザでは以下のように表示されることが期待されます。
{"response_token":"sha256=2rzGn72Vut3ALp+QtkkTgnQ/dE3tmn/HXT+XThpve4B="}もし Web サイトにアクセスできなかった場合はこのエラーメッセージに該当するはずです。ドメインが間違っていたり、DNS の設定がまだ反映されていなかったり、自分で設定した Webhook 先のサーバがダウンしていたりなどが原因として挙げられます。
Non-200 response code during CRC GET request (i.e. 404, 500, etc)
エラーメッセージは Non-200 response code during CRC GET request (i.e. 404, 500, etc)です。「こちらが指定した Webhook URL に Twitter が GET リクエストを送信したところ、200 OK ではない HTTP ステータスが返ってきた」というエラーです。
{"errors":[{"code":214,"message":"Non-200 response code during CRC GET request (i.e. 404, 500, etc)."}]}Unable to connect during CRC GET requestと同じように Webhook URL の後ろに ?crc_token=fooとつけてアクセスした際に 404 Not Found や 500 Internal Server Error などが表示されるはずです。
原因
おそらくこれは Nginx などの Web サーバの設定が間違っているか、Webhook を受け付けるスクリプトの実装が間違っているかです。どちらもサーバのログを見てエラー内容を調べる必要があります。
参考スクリプト
ぼくが使用した Node.js のスクリプトを載せておきます。Node.js で実装しましたが、他のプログラミング言語でも問題ありません。参考にしてみてください。
require('dotenv').config();constexpress=require('express');constapp=express();constport=5000;constcrypto=require('crypto');app.get('/webhook',(req,res)=>{console.log('GET /webhook');consthmac=crypto.createHmac('sha256',process.env.CONSUMER_SECRET).update(req.query.crc_token).digest('base64');res.send('{"response_token":"sha256='+hmac+'"}');});app.listen(port,()=>{console.log(`App listening at http://localhost:${port}`);});CONSUMER_SECRET=<YOUR_CONSUMER_SECRET>
$ npm init
$ npm install express --save$ npm install dotenv --save$ node index.js
事前に Express.js や dotenv のインストールが必要です。また、http://localhost:5000を Nginx 等でリバースプロキシする必要があります。
Webhook URL does not meet the requirements
エラーメッセージは Webhook URL does not meet the requirementsです。Webhook URL が要件を満たしていないというエラーです。
{"errors":[{"code":214,"message":"Webhook URL does not meet the requirements. Please use HTTPS."}]}原因
主な原因としては 2 つ考えられます。
HTTPS 対応していない
エラーメッセージに Please use HTTPSと書かれていることからもわかる通り、Webhook URL は HTTPS でなければなりません。もし HTTPS になっていない場合は Let’s Encrypt などを使用して HTTPS 対応をしてください。
Nginx + Let’s Encrypt での対応方法については以前に記事にまとめていますので参考にしてください。
Nginx+リバースプロキシ環境でWebサーバを停止させずに Let's Encrypt (Certbot) のSSL証明書を自動更新する
URL の指定方法が間違っている
有効な URL が指定されていないとこのメッセージが表示されます。ご丁寧にも Please use HTTPSと書かれているのが逆にややこしいですが、http://になっているだけでなく、それ以外の無効な URL だった場合も同様のメッセージなので、正しい URL かどうかを確認してください。
よくありがちなのは、パーセントエンコーディングしてしまっている場合です。「エラーコード 32」のときにも書きましたが、POST リクエストの Body に Webhook URL を含める際に、パーセントエンコーディングしてはいけません。
Too many resources already created
エラーメッセージは Too many resources already createdです。すでに Webhook URL の登録が完了しています。おめでとうございます 🎉
{"errors":[{"code":214,"message":"Too many resources already created."}]}補足しておくと、無料版1では 1 つしか Webhook URL を設定することができません。
2 つ以上の Webhook URL を登録したかったら 有料版を契約する必要がありますが、有料版は一番安くても $339 / month (約 35,000 円 / 月)2なので一般人には手が出せませんね……。おそらくこれは企業向けだと思います。
なので、遊びで複数のサービスやアプリを作りたくて、なおかつ Account Activity API を使用する場合は、一つの Webhook URL を使い回すことになります。登録した Webhook URL に Twitter からアクティビティがリアルタイムで届くので、それを受け取るスクリプトを用意しておいて、受け取ったデータを各サービスやアプリにパススルーするような実装になると思います。
正しい設定方法
正しい設定方法でまとめると、以下のようになります。以下は Postman での設定例です。
Authorization
まず Authorizationタブを開きます。そして以下の通りにパラメータ等を指定します。
| 番号 | 値 | 補足 |
|---|---|---|
| ① | POST | |
| ② | Dev environment label に設定した値 | 詳しくは「エラーコード 200」の解説を参照 |
| ③ | OAuth 1.0 | |
| ④ | Request Headers | |
| ⑤ | Signature Method は HMAC-SHA1を指定 |
なお、Consumer Keyと Consumer Secretというのは Twitter Developer Portalの画面でいう API key & secretのことです。View Keysをクリックすれば見ることができます。
Access token & secretは一度だけしか表示されずあとから見ることができませんので、忘れてしまった場合は Regenerateで再発行してください。
Headers
次に Headersタブを開きます。そして以下の通りにパラメータを指定します。
| KEY | VALUE |
|---|---|
Content-type | application/x-www-form-urlencoded |
これは設定しなくてもうまくいくかもしれません。うまくいかなかったら設定してみてください。
Body
最後に Bodyタブを開きます。そして以下の通りにパラメータ等を指定します。
| 番号 | 値 | 補足 |
|---|---|---|
| ⑥ | x-www-form-urlencoded | |
| ⑦ | KEY に url | |
| ⑧ | VALUE に Webhook URL | https://your_domain.com/webhook/twitterではなく、自分の Webhook URL を設定すること |
終わりに
結構罠があって大変でしたがなんとか Webhook URL を登録することができたと思います。エラーコードで調べてもあまり大した情報がないということと、Twitter のトラブルシューティングやドキュメントページが丁寧なようでいまいちよくわからない内容だったということがあって原因を解決するのに時間がかかりました。
特に罠だと思ったのが、公式ドキュメントにはクエリパラメータとして Webhook URL を指定する例が載っているのにこれではうまくいかないという点ですね。
それから、Twitter のアプリを登録するページの UI や URL が昔とだいぶ変わっていて、現在の UI で紹介されている記事がほとんど見つからなかったのも地味に戸惑ったポイントでした。
この記事が参考になりましたら幸いです。

