店舗内メディアディスプレイAPI(Display API)の使い方
このガイドの目的
レシートローラーの店舗内メディアディスプレイAPI(Display API)を使って、店頭の Android 端末でメディアループ(画像・動画)を再生するアプリを実装する手順をまとめます。POS 端末併用のキオスクや、専用のサイネージ機(壁掛けタブレットなど)でレシートローラーのリテールメディアやキャンペーン動画を配信するためのガイドです。
前提
- Android 端末側でブラウザを立ち上げる OAuth フローは想定していません。各端末は長期有効なデバイストークンで認証します
- デバイストークンは「ペアリング」プロセスで取得します。店舗オーナーが管理画面で生成した6桁のコードを Android アプリに入力すると、端末ごとのトークンが発行されます
- ベースURL:
https://receiptroller.io
エンドポイント一覧
| エンドポイント | 用途 | 認証 |
|---|---|---|
POST /api/v1/displays/pair | 6桁のペアリングコードをデバイストークンに交換 | 不要(コードが認証) |
POST /api/v1/displays/{displayId}/heartbeat | 端末の生存通知(オンライン/オフライン判定用) | デバイストークン |
GET /api/v1/displays/{displayId}/playlist | 再生すべきメディアの順序付きリストを取得 | デバイストークン |
POST /api/v1/displays/{displayId}/impressions | 再生実績(プレイ)をバッチで報告 | デバイストークン |
ペアリングフロー
各端末は1回だけペアリングを行います。トークンは Android 側で永続化し、以後のすべてのリクエストで Authorization: Bearer {token} ヘッダーに付けます。
- 店舗オーナーが管理画面で新しいディスプレイを登録すると、6桁のペアリングコードが表示されます(有効期間10分・1回限り)
- Android アプリの初回起動画面でコードを入力
- Android が
POST /api/v1/displays/pairを呼び出し、トークンとdisplayIdを受け取ります - Android はトークンと displayId をローカルに永続化(暗号化推奨)
リクエスト例:
POST /api/v1/displays/pair
Content-Type: application/json
User-Agent: RRDisplay/1.0 (Android 14; Pixel Tablet)
{
"code": "123456",
"screenWidth": 1920,
"screenHeight": 1080,
"supportsVideo": true,
"supportsAudio": false
}
レスポンス例(200):
{
"displayId": "a1b2c3d4-...",
"organizationId": "7d325d1d-...",
"deviceToken": "dvc_3f9c1a8b7e2d6f4a1b8c5d2e9f7a3b6c"
}
エラーレスポンス:
400 missing_code— code フィールド未指定401 invalid_or_expired_code— コードが間違っているか、10分の有効期限を過ぎているか、既に使用済み
重要:
- トークンはレスポンスでしか取得できません。サーバー側にはハッシュしか保存していないため、紛失した場合は管理画面でディスプレイを削除し、再度ペアリングしてください
- 1つのペアリングコードは1回しか使えません。再ペアリング時は新しいコードを発行してください
ハートビート
端末がオンラインであることをサーバーに伝えます。管理画面の「オンライン/オフライン」表示はこのタイムスタンプを基準にしています(最後のハートビートから5分以内ならオンライン扱い)。
POST /api/v1/displays/{displayId}/heartbeat
Authorization: Bearer dvc_3f9c1a8b...
User-Agent: RRDisplay/1.0 (Android 14; Pixel Tablet)
レスポンス例(200):
{
"ok": true,
"serverTimeUtc": "2026-06-03T05:21:30Z",
"nextHeartbeatSeconds": 60
}
推奨呼び出し間隔: レスポンスの nextHeartbeatSeconds に従ってください(現在60秒)。サーバー側がポーリング負荷に応じて値を変更する可能性があるため、ハードコードせずレスポンスを参照することを推奨します。
プレイリスト取得
端末が再生すべきメディアの順序付きリストを取得します。各アイテムには SAS 署名済みの直接アクセスURL(1時間有効)が含まれます。
GET /api/v1/displays/{displayId}/playlist
Authorization: Bearer dvc_3f9c1a8b...
レスポンス例(200):
{
"displayId": "a1b2c3d4-...",
"generatedAt": "2026-06-03T05:21:30Z",
"pollIntervalSeconds": 60,
"items": [
{
"creativeId": "creative-001",
"name": "夏の新商品キャンペーン",
"type": "Image",
"mediaUrl": "https://strprdomnicon.blob.core.windows.net/creatives/...?sv=...&sig=...",
"durationSeconds": 10,
"hashHint": "creative-001_638549812340000000"
},
{
"creativeId": "creative-002",
"name": "新メニュー紹介動画",
"type": "Video",
"mediaUrl": "https://strprdomnicon.blob.core.windows.net/creatives/...?sv=...&sig=...",
"durationSeconds": 30,
"hashHint": "creative-002_638549812350000000"
}
]
}
運用ガイド:
- 再生順序 —
items配列の順番に再生し、最後まで再生したら最初に戻ってループ再生してください - キャッシュ —
hashHintが変わらない限り、メディアファイルは再ダウンロード不要です。ローカルキャッシュを推奨します。hashHintが変わったら再取得してください - SAS URL の有効期限 —
mediaUrlは1時間有効です。期限切れの URL でダウンロードを試みると 403 が返るので、pollIntervalSeconds間隔でプレイリストを再取得し、新しい URL を取得してください - durationSeconds — 画像は10秒(既定)、動画は実尺。アプリは指定秒数で次のアイテムに切り替えてください
- 空のプレイリスト — オーナー側でまだクリエイティブが承認されていない場合、
itemsは空配列です。空のときは黒画面または「準備中」プレースホルダーを表示することを推奨します
再生実績の報告(インプレッション)
再生した1スロットごとに「いつ・どのクリエイティブを・どれだけ再生したか」を Android からサーバーへバッチ送信します。Phase 3 / t-e9a2f501。
POST /api/v1/displays/{displayId}/impressions
Authorization: Bearer dvc_3f9c1a8b...
Content-Type: application/json
{
"events": [
{
"eventId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"creativeId": "creative-001",
"campaignId": "camp-001",
"placementId": "place-001",
"playedAtUtc": "2026-06-03T05:20:00Z",
"durationPlayedMs": 10000,
"completed": true
},
{
"eventId": "b2c3d4e5-f678-9012-3456-7890abcdef01",
"creativeId": "creative-002",
"campaignId": "camp-001",
"placementId": "place-001",
"playedAtUtc": "2026-06-03T05:20:10Z",
"durationPlayedMs": 30000,
"completed": true
}
]
}
レスポンス例(200):
{
"accepted": 2,
"duplicates": 0,
"rejected": 0,
"errors": []
}
運用ガイド:
- 送信頻度 — 60秒ごとに送信することを推奨します。1スロット再生ごとに送ると過剰なネットワーク負荷になります
- バッチ上限 — 1回のリクエストで最大500件まで。超過すると
400 batch_too_largeが返ります - eventId はクライアントが生成 — UUID v4 を推奨。サーバー側でこのIDを使って冪等性を保証しています。オフライン後に同じバッチを再送しても、サーバーは2回目をサイレントに
duplicatesとしてカウントします - completed フラグ — スロットを最後まで再生したら
true、途中で次に切り替えた場合はfalse。完了率の分析に使われます - オフライン対応 — ネットワーク失敗時はローカルキューに保持し、復旧後に再送してください。冪等性により重複送信は安全です
- placementId / campaignId は任意 — プレイリストアイテムには直接含まれていませんが、Android アプリが Phase 2 のプレイリスト構造を理解している場合は付与すると分析の粒度が上がります。空でも accepted されます
レスポンスフィールド:
accepted— 新規に記録された件数duplicates— 既に処理済みだった件数(再送による重複)rejected— 必須フィールド欠落などで処理できなかった件数errors— 拒否理由の配列(デバッグ用、内容はバージョンで変わる可能性あり)
典型的な実装フロー(Android)
- 初回起動 — トークンがローカルに存在しなければペアリング画面を表示。コード入力 →
POST /pair→ トークン取得 → 保存 - 常時実行ループ
- 起動時およびその後 60秒ごとに
GET /playlistを呼び出し hashHintが前回と異なるアイテムは再ダウンロード、同じアイテムはキャッシュから読み込み- 取得した順に画像/動画を全画面再生、
durationSecondsごとに次へ - 最後のアイテムまで再生したら先頭に戻る
- 起動時およびその後 60秒ごとに
- 並行 — 60秒ごとに
POST /heartbeatを呼び出してサーバーに生存を伝える - 並行 — 再生したスロットごとにローカルキューに記録し、60秒ごとに
POST /impressionsでバッチ送信 - エラー処理
401— トークン無効。再ペアリング画面に戻す403— トークンとパス上の displayId が一致しない(バグ)。ログを取って再ペアリング- ネットワーク失敗 — 最後に取得したプレイリストをそのまま再生し続け、インプレッションキューを保持してバックグラウンドで再試行
セキュリティ
- デバイストークンは長期有効です。Android Keystore など端末の暗号化ストレージに保存してください
- サーバー側にはトークンの SHA-256 ハッシュしか保存していません。紛失したトークンは管理画面でディスプレイを削除して再ペアリングすることで失効します
- 1つのトークン = 1つのディスプレイ。複数端末で同じトークンを使い回すと、管理画面の「最後のハートビート」「現在の解像度」が端末ごとに上書きされ混乱します
このAPIの今後
現在のプレイリストは「キャンペーン × プレイスメントによる時間帯・店舗ターゲティングと重み付けループ」に対応しています。今後のフェーズで以下を追加します:
- 店舗オーナー向け再生実績ダッシュボード(インプレッション数、完了率、ディスプレイ別ファンアウト)
- 頻度上限の実効化(プレイスメントの
frequencyCapPerHourは現在設定可能ですが、Phase 5 の実装まではノーオプ)
API スキーマは前方互換を保ちます — 既存の4つのエンドポイントのレスポンス形式は将来も変更しません(追加フィールドはあり得ます)。
関連情報
-
リクエストとレスポンスの基本(JSON)レシートローラーAPIのリクエスト形式、必須ヘッダー、レスポンス構造、ページネーション、フィルタリング、日時形式の規則を解説します。
-
ネイティブモバイルアプリ向けガイド: 複数ビジネスアカウントアクセスと OAuth フローAndroid / iOS のネイティブアプリ向け実装ガイド。アプリ登録時に「認可時に1つのビジネスアカウントへトークンを紐付ける」をオフにすると、user-scoped OAuth トークンが発行されます。/api/v1/me/organizations + ?organizationId= パターンで複数ビジネスアカウントを横断アクセスできます。
-
取引一覧API(Transactions API:POS+OMS統合フィード)の使い方レシートローラーのTransactions APIは、レジ売上(PosTransactions)と販売管理注文(OmsOrders)を1つのフィードに統合した読み取り専用APIです。Android/iOSアプリで「ビジネスアカウント全体の取引」を一覧表示する際の入り口になります。
-
PosTransactionDto 仕様 — 取引データのフィールドリファレンスレシートローラーが扱う取引データの正規モデル PosTransactionDto の全フィールドを解説します。識別子・日時・金額・明細・支払い・スタッフ・ステータス・CRM 連携の各カテゴリーごとに、フィールド名・型・意味・各 POS ベンダーからの埋め方をまとめた、開発者および外部システム連携担当者向けのリファレンスです。スマレジ・Square 双方のマッピング記事からも参照されます。
-
商品管理API(Products API)の使い方レシートローラーの商品管理API(/api/v1/products)でビジネスアカウント配下の商品をCRUD操作するためのガイドです。Android/iOSアプリやサーバー連携でPIM(商品マスター)を読み書きする際の入門記事です。