【エラーコード別解説】Twitter の Account Activity API の Webhook URL が登録できないときの解決法
はじめに
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();
const express = require('express');
const app = express();
const port = 5000;
const crypto = require('crypto');
app.get('/webhook', (req, res) => {
console.log('GET /webhook');
const hmac = 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 で紹介されている記事がほとんど見つからなかったのも地味に戸惑ったポイントでした。
この記事が参考になりましたら幸いです。
参考サイト
- TwitterのAccount Activity APIとwebhookを使用する
- TwitterのAccount Activity APIとwebhookでDM自動応答Botを作成する
- TwitterのAccount Activity APIを叩くnodejsコード
- Twitter API 1.1でなぜか"Could not authenticate you"と言われる
- Twitter Account Activity API を使ってリプライ自動返信する(Go)
Discussion