🐤

【エラーコード別解説】Twitter の Account Activity API の Webhook URL が登録できないときの解決法

2021/03/02に公開

はじめに

Twitter の Account Activity API を使う機会があり、こちらの記事 を参考に Webhook URL を登録しようとしたのですが、なかなか登録できず、丸一日ほど費やしてしまいました。

Webhook の登録はかなり罠があり、調べても解決法が全然出てこなかったため、この記事では、発生するエラーコードを紹介し、その原因と解決法について解説します。参考になりましたら幸いです。

正しい設定方法だけ見たい

正しい設定方法

事前準備

Webhook URL を登録する際には POST リクエストを Twitter に送る必要があります。そのリクエストを送るために、本記事では Postman を利用します。あらかじめアカウント登録し、デスクトップ版アプリをインストールしておいてください。

cURL でもできる気がしますが、罠が多すぎていちいちパラメータをいじるのがめちゃくちゃ大変だったので Postman の使用をおすすめします。

アカウント登録

アカウントを持っていない場合は こちら からアカウントを作成してください。

アプリのインストール

アカウント登録またはサインイン後に Workspace に行き、画面右下の Desktop Agent から Download desktop agent をクリックしてダウンロードしてください。
スクリーンショット 2020-11-20 13.22.17.png

または、macOS をお使いの方は Homebrew Cask からインストールすることもできます。

$ brew cask install postman

その後、アプリを起動し、サインインしてください。

アプリをインストールする必要がありますか? ブラウザではダメですか?

Postman は Web 版で使用することもできます。しかし、ブラウザで検証したところ、CORS の制約に引っかかってしまいリクエストを送信することができませんでした。そのためアプリ版を使用する必要があります。

目次

発生したエラーコードの解説だけ知りたい方は以下の目次をご活用ください。

エラーコード 32

エラーメッセージは Could not authenticate you です。「認証できませんでした」ということなのですが、理由が全く書かれていないためこれだけではわかりません。

{
    "errors": [
        {
            "code": 32,
            "message": "Could not authenticate you."
        }
    ]
}

公式のトラブルシューティング を見ても「リクエストの認証データに問題がある」ということしかわからず、認証データの「どこ」に問題があるかはわかりません。
スクリーンショット 2020-11-19 22.44.01.png

ネットで調べてみると、このエラーで苦しんでいる人が多くいるようでした。何を隠そう、自分もこのエラーで苦しみました。

原因

このエラーが発生する原因として考えられるのは、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 にこのパラメータを入れること です。つまり、
スクリーンショット 2020-11-20 13.54.52.png
↑ こうではなく
スクリーンショット 2020-11-20 13.56.20.png
↑ こうしてください

Body タブを開き x-www-form-urlencoded を選択して、KEYurlVALUE にあなたの 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 をクリックして権限を変更します。
スクリーンショット 2020-11-20 14.13.24.png

一番下の Read + Write + Direct Messages を選択して保存します。
スクリーンショット 2020-11-20 14.18.00.png
DM の権限がいらない場合は、おそらく Read and Write でも問題ないかもしれませんが、試していません。少なくとも Read ではダメです。

次に、Keys and tokens のタブをクリックし、Access token & secret の権限を確認します。先ほど App permissionsRead only になっていた場合は、権限修正後もここが Read only になっているかと思います。その場合は Regenerate をクリックしてトークンを再発行します。
スクリーンショット 2020-11-20 14.18.28.png
トークンが変わるので、再度 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 をクリックし、環境をセットアップしてください。
スクリーンショット 2020-11-20 14.41.17.png

Dev environment labelApp を設定するダイアログが表示されます。Dev environment label には任意の名前、App は使用しているプロジェクトまたはアプリを選択します。
スクリーンショット 2020-11-20 14.42.54.png
Dev environment label は任意と言いましたが、URL の一部となるため、わかりやすい名前にするのが良いです。本番環境で使用するつもりのアプリなら prodproduction、開発環境で使用するつもりなら devdevelopment などです。

とりあえずテストで使うなら 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 を間違えていないことを確認してください。正しい KEYurl です。
スクリーンショット 2020-11-20 15.35.51.png

エラーコード 34

エラーメッセージは Sorry, that page does not exist です。ページが存在しないというエラーです。

{
    "errors": [
        {
            "message": "Sorry, that page does not exist",
            "code": 34
        }
    ]
}

原因

これはおそらく URL の :ENV_NAME の部分をそのままにしているパターンです。
スクリーンショット 2020-11-20 15.43.06.png

解決方法

:ENV_NAME には Dev environment label を指定します。詳細は「エラーコード 200」の解説を確認してください。

エラーコード 131

エラーメッセージは Internal error です。その名の通り内部エラーです。エラーが発生してエラー内容が「内部エラー」って何かのとんちですかね?

{
    "errors": [
        {
            "message": "Internal error",
            "code": 131
        }
    ]
}

原因

これはおそらく Webhook URL をサンプルのまま書いているパターンです。
スクリーンショット 2020-11-20 16.39.03.png

解決方法

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 で実装しましたが、他のプログラミング言語でも問題ありません。参考にしてみてください。

index.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}`);
});
.env
CONSUMER_SECRET=<YOUR_CONSUMER_SECRET>
command
$ 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 を含める際に、パーセントエンコーディングしてはいけません。

スクリーンショット 2020-11-20 16.30.29.png
↑ こうではなく
スクリーンショット 2020-11-20 16.31.19.png
↑ こうしてください

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 タブを開きます。そして以下の通りにパラメータ等を指定します。
スクリーンショット 2020-11-20 16.47.50.png

番号 補足
POST
Dev environment label に設定した値 詳しくは「エラーコード 200」の解説を参照
OAuth 1.0
Request Headers
Signature Method は HMAC-SHA1 を指定

なお、Consumer KeyConsumer Secret というのは Twitter Developer Portal の画面でいう API key & secret のことです。View Keys をクリックすれば見ることができます。
スクリーンショット 2020-11-20 17.02.05.png
Access token & secret は一度だけしか表示されずあとから見ることができませんので、忘れてしまった場合は Regenerate で再発行してください。

Headers

次に Headers タブを開きます。そして以下の通りにパラメータを指定します。
スクリーンショット 2020-11-20 17.08.39.png

KEY VALUE
Content-type application/x-www-form-urlencoded

これは設定しなくてもうまくいくかもしれません。うまくいかなかったら設定してみてください。

Body

最後に Body タブを開きます。そして以下の通りにパラメータ等を指定します。
スクリーンショット 2020-11-20 17.13.17.png

番号 補足
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 で紹介されている記事がほとんど見つからなかったのも地味に戸惑ったポイントでした。

この記事が参考になりましたら幸いです。

参考サイト

脚注
  1. 無料版は Free Premium という名前らしいですが、無料なのにプレミアムってなんか不思議なネーミングですね。 ↩︎

  2. 2020 年 11 月 20 日現在 ↩︎

GitHubで編集を提案

Discussion