アカウント連携・統合API(トークン交換・/me/identities・/account/merge)
この記事では、アプリがLINE・Apple・Googleで取得したIDトークンでレシートローラーにサインインするトークン交換と、ログイン方法を追加・解除する /api/v1/me/identities、2つのアカウントを統合する /api/v1/account/merge の仕様をまとめます。レシートローラー公式のiOS / Androidアプリと LINEミニアプリが使っているものと同じAPIです。
トークン交換(IDトークンでサインイン)
RFC 8693 のトークン交換で、プラットフォームSDKが返したIDトークンをレシートローラーのアクセストークンに交換します。ブラウザでの /oauth/authorize を経由しません。使えるのは、トークン交換を許可されたクライアントIDだけです。利用したい場合はサポートにご相談ください。
POST https://receiptroller.io/api/v1/auth/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&client_id={client_id}
&subject_token={IDトークン}
&subject_token_type=urn:ietf:params:oauth:token-type:id_token
&subject_issuer=line # line | apple | google
&organization_id={店舗のビジネスアカウントID} # 店舗独自のLINEチャネルのときだけ
&nonce={nonce} # SDKにnonceを渡した場合
&create_if_missing=true # アカウントがなければ作る
成功すると、通常のトークンに issued_token_type と account_created(この呼び出しでアカウントを作ったか)が加わります。
| 状態 | error | 意味 |
|---|---|---|
| 400 | invalid_request | subject_token / subject_token_type / subject_issuer の不足・誤り |
| 401 | invalid_client | トークン交換が許可されていないクライアント |
| 400 | invalid_grant | IDトークンを検証できない(期限切れ・別チャネル・nonce不一致など) |
| 404 | identity_not_found | このIDを使うアカウントがない。同じ確認済みメールのアカウントがあれば candidate_account(masked_email・sign_in_methods)が付きます。そのアカウントにサインインしてから連携するよう案内してください |
| 429 | rate_limit_exceeded | 同じ接続元からのアカウント作成が多すぎる |
本人確認(proof)
ログイン方法の追加・解除と統合では、トークンに加えて、今のアカウントの持ち主であることを proof で示します。
{ "type": "password", "password": "..." }
{ "type": "id_token", "issuer": "line", "idToken": "...", "nonce": null, "organizationId": null }
- アカウントのログイン方法(パスワード、またはつながっているLINE・Apple・Googleのいずれか)で示します
- ログイン方法をまだ持たないアカウント(スマホアプリで匿名で始めたもの)は
proofを省略できます - 足りないと 403
reauth_required、合わないと 403proof_rejectedが返り、どちらも使える方法をacceptedMethodsで示します
ログイン方法の管理 /api/v1/me/identities
GET /api/v1/me/identities:email、hasPassword、identities(id・provider・scope・linkedAt・lastUsedAt・canRemove)POST /api/v1/me/identities:{ issuer, idToken, nonce?, organizationId?, proof }でLINE・Apple・Googleを追加。すでに別のアカウントが使っていると 409identity_belongs_to_other_accountとmergeTicketが返りますDELETE /api/v1/me/identities/{id}:本文{ proof }。proof には解除する方法以外を使います。最後の1つは 409last_sign_in_methodPOST /api/v1/me/identities/password/code:{ email, proof }。メールに確認コードを送ります(202)。1時間あたりの回数に上限があります(429rate_limit_exceeded)POST /api/v1/me/identities/password:{ email, password, code, proof }。そのメールを別のアカウントが使っていれば 409identity_belongs_to_other_accountとmergeTicket。パスワードが条件を満たさないと 400password_rejected
アカウントの統合 /api/v1/account/merge
統合には、もう一方のアカウントの証明を表す mergeTicket(有効期限10分)が必要です。チケットは、それを取得したアカウントのトークンでしか使えません。
- もう一方のアカウントを証明してチケットを得る:
POST /api/v1/account/merge/tickets
確認コードは{ "proof": {...}, "other": { "type": "email_code", "email": "...", "code": "..." } } // type は id_token / password / email_codePOST /api/v1/account/merge/email-code({ email, proof })で送ります。アカウントの有無にかかわらず 202 を返します。 - 内容を確認する:
POST /api/v1/account/merge/preview({ mergeTicket, keep? })。keepはcurrent(今のアカウントを残す)かother。省略時はsuggestedKeep(本人が作ったアカウント、同種なら古い方) - 統合する:
POST /api/v1/account/merge({ mergeTicket, keep, confirm: true })。202 でmergeIdと、残るアカウントのtokensを返します。以降はこのトークンを使ってください。同じチケットを再送しても同じ統合が返ります - 進み具合:
GET /api/v1/account/merge/{mergeId}。statusはrunning/completed/failed/undone。canResumeが true ならPOST /api/v1/account/merge/{mergeId}/resumeで再開できます
POST /api/v1/account/merge/suggestions({ proof })は、同じ人のものと思われる別のアカウントを返します。same_line は同じLINEのIDを持つアカウントで、LINEが両方を証明しているため mergeTicket 付きです。same_email はLINEのIDトークンのメールが一致したアカウントで、チケットはなく、通常どおり証明が必要です。
| 状態 | error | 意味 |
|---|---|---|
| 400 | invalid_credentials / invalid_code / invalid_grant | もう一方のアカウントを証明できない(存在しないメールも同じ応答) |
| 400 | same_account | もう一方が今のアカウント自身 |
| 400 | invalid_ticket / confirm_required | チケットの期限切れ・不正 / confirm が true でない |
| 403 | ticket_not_yours | 別のアカウントが取得したチケット |
| 404 | other_account_not_found / merge_not_found | 相手のアカウント・統合が見つからない |
| 409 | already_merged / not_resumable | すでに統合済み / 再開できない状態 |
| 429 | locked_out / rate_limit_exceeded | パスワードの誤りが続いた / 確認コードの送りすぎ |
実装のヒント
- エラー本文は
errorコードで分岐してください。errorDescriptionの文言は変わることがあります - ログイン方法の追加・解除と統合は、利用者のメールとLINEに通知されます。アプリ側で別途知らせる必要はありません
- 統合はアプリからは取り消せません。30日以内であればサポートで元に戻せる場合があります
関連記事
-
店舗情報API(Store Information API)の使い方店舗の基本情報(店舗名・店舗種別・連絡先・住所)を取得・更新する REST API のガイドです。スタッフアプリなどのトークン認証クライアントから店舗情報の編集を実装できます。
-
トークンが取得できない(認証エラー)アクセストークンが取得できないときの原因切り分け。invalid_client、invalid_grant、redirect_uri_mismatch などの代表的エラーと対処を解説します。
-
リダイレクトURLの設定レシートローラーの開発者ポータルで設定するリダイレクトURI(コールバックURL)の役割、登録ルール、開発・本番環境の使い分け、よくあるエラーと対処方法を解説します。
-
定期予約・出欠・キャンセル待ちAPI の使い方レシートローラーの定期予約API(/api/v1/reservations/series)、出欠・振替API(/api/v1/reservations/attendance)、キャンセル待ちAPI(/api/v1/reservations/waitlist)のガイドです。毎週の定期予約の登録と生成、クラスの出欠記録、振替の受付、キャンセル待ちの管理を解説します。
-
営業時間API(Business Hours API)の使い方レシートローラーの営業時間API(/api/v1/stores/{storeId}/business-hours)のガイドです。曜日ごとの営業時間の取得・更新、特例営業日(臨時休業・営業時間変更)の登録、店舗の就業可能時間(シフト作成時の上限となる業務時間)の設定、現在営業中かどうかの判定までを解説します。