API と Webhook
ここでの操作はすべて、あなたのアカウントがメンバーになっているアーティストに対して、それぞれのロールの範囲で行われます。リクエストもレスポンスも HTTPS 上の JSON です。
API と Webhook は Label プラン(30日間の無料体験を含む)で使えます。キーと Webhook はダッシュボードの「API」で作成します。
https://listenthru.com/api/v1 · release.created release.live fan.confirmed
認証
ダッシュボードの API で個人用のキーを作成し、読み取りか読み取りと書き込みを選びます。キーは一度だけ表示されます。シークレット管理に保存し、Web ページや配布するアプリには入れないでください。形式は lt_0123456789ab_… です。
すべてのリクエストで Bearer トークンとして送ります。キーはあなたとして動き、あなたがメンバーのアーティストを、それぞれのロールで許される範囲で操作します。キーはダッシュボードからいつでも無効にでき、すぐに使えなくなります。各キーには最後に使われた日時が表示されます。
curl https://listenthru.com/api/v1/artists \
-H "Authorization: Bearer $LISTENTHRU_KEY"
ロールとスコープ
| ロール | できること |
|---|---|
| viewer(閲覧者) | リリースと分析を見る。 |
| editor(編集者) | 加えて、リリースとアーティストページの作成・編集。 |
| admin(管理者) | 加えて、メンバー、広告の計測、ファンとその書き出し。 |
| owner(オーナー) | 加えて、請求、リリースの削除、オーナーの引き継ぎ。 |
読み取りキーで使えるのは GET だけです。変更には読み取りと書き込みキーと、それに見合うロールの両方が必要です。
レート制限
キーごとに1分あたり 60 リクエストまで。すべてのレスポンスに X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset(秒)が付きます。超えると 429 と Retry-After を返します。
エラー
エラーは HTTP ステータスと、分岐に使える変わらない code で返します。message は人が読むためのもので、変わることがあります。原因の入力がわかる場合は field に入ります。
HTTP/1.1 403 Forbidden
{ "error": { "code": "insufficient_scope", "message": "This key can only read. Make a read and write key to change things." } }| コード | ステータス | 意味 |
|---|---|---|
unauthorized | 401 | キーが送られていません。 |
invalid_key | 401 | キーが正しくないか、無効にされています。 |
plan_required | 402 | Label(または体験)が終了しているか、アーティストが Pro ではありません。 |
insufficient_scope | 403 | 読み取りキーで変更しようとしました。 |
forbidden | 403 | このアーティストでのロールでは許されていません。 |
not_found | 404 | アーティスト、リリース、エンドポイントがありません。 |
method_not_allowed | 405 | パスはありますが、そのメソッドは使えません。 |
invalid_request | 400 | 送った値が正しくありません。field を確認してください。 |
conflict | 409 | その slug は使われています。 |
unresolvable | 422 | リンク、ISRC、UPC が見つかりませんでした。 |
rate_limited | 429 | リクエストが多すぎます。Retry-After まで待ってください。 |
internal_error | 500 | こちら側の問題です。もう一度お試しください。 |
アーティスト
あなたのアカウントがメンバーのアーティストと、それぞれでのロール。
/api/v1/artists読み取りキー · viewercurl https://listenthru.com/api/v1/artists \
-H "Authorization: Bearer $LISTENTHRU_KEY"レスポンス
{
"data": [
{ "id": "8saidwait", "name": "8saidwait", "role": "owner", "plan": "pro",
"url": "https://listenthru.com/8saidwait", "createdAt": "2026-10-01T03:00:00.000Z" }
]
}/api/v1/artists/{artist}読み取りキー · viewerリリース
ストアのリンク(Spotify、Apple Music、YouTube、Deezer、プリセーブページ)か、isrc(曲)または upc(アルバム・EP)からリリースページを作ります。タイトル、アートワーク、配信のある各サービスへのリンクが自動で入り、自分で送った値が優先されます。"status": "live" を送らない限り下書きで作成されます。任意項目:title、subtitle、releaseDate(YYYY-MM-DD)、kind(single、ep、album、video)、slug、links、artworkUrl、country(探すストアの国。既定は JP)。
リリース日まではページにプリセーブのボタンが出て、リリース日に listenthru が各サービスのリリースそのものへのリンクに切り替えます(これが release.live の Webhook です)。
/api/v1/artists/{artist}/releases読み取りキー · viewercurl https://listenthru.com/api/v1/artists/8saidwait/releases \
-H "Authorization: Bearer $LISTENTHRU_KEY"/api/v1/artists/{artist}/releases/{slug}読み取りキー · viewercurl https://listenthru.com/api/v1/artists/8saidwait/releases/say-it-again \
-H "Authorization: Bearer $LISTENTHRU_KEY"レスポンス
{
"data": {
"slug": "say-it-again", "url": "https://listenthru.com/8saidwait/say-it-again",
"title": "say it again", "subtitle": "", "status": "live", "releaseDate": "2026-10-16",
"kind": "single", "isrc": "JPAB01234567", "upc": "",
"artwork": "https://listenthru.com/media/a/8saidwait/…webp",
"links": [{ "id": "a1b2c3d4", "service": "spotify", "label": "Spotify", "url": "https://open.spotify.com/track/…" }],
"createdAt": "…", "updatedAt": "…", "upgradedAt": ""
}
}
/api/v1/artists/{artist}/releases読み取りと書き込みキー · editorリンクから
curl -X POST https://listenthru.com/api/v1/artists/8saidwait/releases \
-H "Authorization: Bearer $LISTENTHRU_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://open.spotify.com/track/…", "releaseDate": "2026-11-20"}'ISRC から
curl -X POST https://listenthru.com/api/v1/artists/8saidwait/releases \
-H "Authorization: Bearer $LISTENTHRU_KEY" \
-H "Content-Type: application/json" \
-d '{"isrc": "JPAB01234567", "status": "live"}'
/api/v1/artists/{artist}/releases/{slug}読み取りと書き込みキー · editorcurl -X PATCH https://listenthru.com/api/v1/artists/8saidwait/releases/say-it-again \
-H "Authorization: Bearer $LISTENTHRU_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "live", "subtitle": "out now"}'
分析
ダッシュボードと同じ数字です。訪問、聴きに行った数(サービスへのタップ)、訪問の流入元、オーディエンス。days は Pro と Label で 1〜90(Free は 7 まで)。
/api/v1/artists/{artist}/insights?days=28&release={slug}読み取りキー · viewer/api/v1/artists/{artist}/releases/{slug}/insights?days=28読み取りキー · viewercurl "https://listenthru.com/api/v1/artists/8saidwait/insights?days=28" \
-H "Authorization: Bearer $LISTENTHRU_KEY"
curl "https://listenthru.com/api/v1/artists/8saidwait/releases/say-it-again/insights?days=7" \
-H "Authorization: Bearer $LISTENTHRU_KEY"レスポンス
{
"data": {
"days": 28, "from": "20261001", "to": "20261028",
"totals": { "views": 1520, "clicks": 610, "rate": 0.401, "presaves": 42, "reminders": 18 },
"series": [{ "day": "20261001", "views": 40, "clicks": 15 }, …],
"byService": [{ "service": "spotify", "label": "Spotify", "clicks": 380 }, …],
"bySource": [{ "source": "instagram", "views": 700, "clicks": 300, "rate": 0.43 }, …],
"byRelease": […], "byCountry": […], "byDevice": […], "byApp": […], "byCampaign": […],
"countryEstimated": true
}
}
ファン
確認済みのファン登録(ダブルオプトイン)を古い順に返します。管理者とオーナーのみ。since で新しい登録だけを取得できます。
/api/v1/artists/{artist}/fans?since={ISO time}読み取りキー · admincurl "https://listenthru.com/api/v1/artists/8saidwait/fans?since=2026-10-01T00:00:00Z" \
-H "Authorization: Bearer $LISTENTHRU_KEY"レスポンス
{
"data": [
{ "email": "fan@example.com", "confirmedAt": "2026-10-02T11:04:00.000Z",
"source": "instagram", "release": "say-it-again", "lang": "ja" }
]
}
Webhook
ダッシュボードの API で https のアドレスを追加し、イベントを選びます。あなたが管理者かオーナーのアーティストでイベントが起きるたびに、JSON を POST します。署名用のシークレットは一度だけ表示されます。
| イベント | タイミング |
|---|---|
release.created | ダッシュボードか API でリリースページが作られたとき。 |
release.live | リリース日、プリセーブのボタンが各サービスのリリースに切り替わったとき。 |
fan.confirmed | ファンが登録を確認したとき。メールアドレスを含みます。 |
署名の検証
X-Listenthru-Signature は t=<UNIX 時刻>,v1=<"t.本文" の HMAC-SHA256(16進)> で、鍵はあなたのシークレットです。受け取ったままの本文で照合し、古いタイムスタンプは拒否してください。10秒以内に 2xx を返し、時間のかかる処理はその後に。同じイベントが二度届くことがあるので、id で重複を除いてください。
POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: listenthru-webhooks/1 (+https://listenthru.com/developers)
X-Listenthru-Event: release.live
X-Listenthru-Delivery: dlv_6f0c…
X-Listenthru-Signature: t=1792900000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
{
"id": "evt_0b6c…", "type": "release.live", "created": "2026-11-20T00:05:12.000Z",
"artist": { "id": "8saidwait", "name": "8saidwait" },
"data": { "release": { "slug": "say-it-again", "status": "live", "links": […], … } }
}Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';
// raw: the request body exactly as received (a string or Buffer), before any JSON parsing
export function verify(raw, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const want = createHmac('sha256', secret).update(`${t}.${raw}`).digest();
const got = Buffer.from(parts.v1 || '', 'hex');
return got.length === want.length && timingSafeEqual(got, want);
}
再送
2xx が返らない(またはタイムアウトした)配信は、およそ 1、2、4、8、16 時間後に再送します(合計 6 回)。10 回続けて失敗すると Webhook は停止し、ダッシュボードに表示されます。ワンクリックで再開できます。リダイレクトはたどりません。プライベート、ループバック、リンクローカルのアドレスには送れません。