Skip to content

管理API・Stripe連携ガイド ​

販売者自身の決済サーバーから、MQLAuthの利用者を作成・通常化・延長・失効できます。 APIキーは販売者単位で、その販売者が所有するEA・インジケーターだけを操作できます。

各項目を管理画面のどこで見るか ​

APIに渡す値は、すべて管理画面から確認できます。

ユーザー管理(ユーザーID・口座番号・EA名) ​

サイドバーの「ユーザー管理」を開きます。

ユーザー管理画面での各項目の位置

APIの項目画面での場所
userIdユーザー名の下に「ユーザーID: 44798」と表示されます
accountNumber「口座番号」列。クリックでコピーできます
applicationName「EA・インジケーター」列のラベル

一覧右上の「CSV」ボタンで、表示中の利用者を一括で書き出せます。 先頭列が userId なので、既存の購入者をまとめて自社システムへ取り込むときに使えます。

EA・インジケーター(EA名) ​

サイドバーの「EA・インジケーター」でも applicationName を確認できます。カードの見出しがその名前です。

EA・インジケーター画面での名前の位置

値の渡し方の注意 ​

  • accountNumber は数値で送ります。"12345678" のように文字列にすると400になります
  • applicationName の前後の空白は自動で取り除かれます。大文字・小文字の違いも区別しません
  • userId は画面に表示されますが、作成APIの応答に含まれる値を保存するのが確実です

APIキーを発行する ​

管理画面のサイドバー、またはアカウント設定の「APIキー」を開き、名前を入力して「発行する」を押します。 平文のキーは発行直後の画面で一度だけ表示されます。サーバーのシークレット管理機能に保存してください。 紛失した場合は新しいキーを発行し、連携先を更新して古いキーを失効させます。失効は直ちに反映されます。 EAのソースコード、ブラウザー、公開リポジトリにキーを含めないでください。

すべてのリクエストに次のヘッダーを付けます。APIの基点は https://mql-auth.com/api/v1/manager/users です。

http
Authorization: Bearer <発行したmqak_で始まるキー>
Content-Type: application/json
Idempotency-Key: <この操作を一意に識別する値>

POSTには Idempotency-Key を付けてください(最大200文字、省略も可能)。同じ販売者の別キーへのローテーション後も再送を識別します。 同じキー・同じ送信先・同じボディの再送は、保存したHTTPステータスとJSONをそのまま返し、操作を再実行しません。 別ボディまたは別送信先への使い回しは422になります。JSONの空白やプロパティ順序も含め、送信バイト列を再利用してください。 エラー応答も保存されるため、入力やプランを修正して新しい操作を行う場合は新しいキーを使います。

日時は 2026-10-18T23:59:59+09:00 または 2026-10-18T14:59:59Z のようにオフセットを必ず付けます。 オフセットのない日付は400です。サーバーでローカル時刻へ変換し、本番では日本時間として扱います。

利用者を作成する ​

POST /api/v1/manager/users

json
{
  "applicationName": "SampleEA",
  "accountNumber": 12345678,
  "userName": "購入者",
  "email": "customer@example.com",
  "userPeriod": "2026-10-18T23:59:59+09:00",
  "isTestUser": false,
  "memo": "外部決済から登録"
}

applicationName・正の整数の accountNumber・userName・userPeriod は必須です。 email・memo は省略可能、isTestUser は省略するとfalseです。 同じEA・口座番号に有効な体験版があれば通常化し、体験版使用済み記録を残します。 その場合は購入者の名前・メールを適用し、購入期限が既存の通常期限より後であれば期限を更新します。 通常の作成では既存画面と同じ重複判定・ユーザー上限・体験版期限上限が適用されます。

成功時はHTTP 200で次の形式を返します。userId を自社DBとStripeのsubscription metadataに保存してください。 口座番号は利用者自身が変更できるため、以後の操作には userId を使います。

json
{
  "userId": 123,
  "applicationName": "SampleEA",
  "accountNumber": 12345678,
  "userName": "購入者",
  "email": "customer@example.com",
  "userPeriod": "2026-10-18T23:59:59.0000000+09:00",
  "isTestUser": false
}

通常化・延長・失効 ​

操作POSTのパスボディ
体験版を通常化/api/v1/manager/users/123/promote{} または空
指定期限まで延長(推奨)/api/v1/manager/users/123/extend{"until":"2026-11-18T23:59:59+09:00"}
月数で延長/api/v1/manager/users/123/extend{"months":1} または {"months":12}
指定日時で失効/api/v1/manager/users/123/expire{"at":"2026-10-18T23:59:59+09:00"}
今すぐ失効/api/v1/manager/users/123/expire{} または空

通常化は新しい通常ユーザーの userId を返します。同じEA・口座に通常ユーザーが既にある場合も200で既存ユーザーを返します。 通常化後は返された userId に保存値を更新してください。

until は期限を後退させません。現在の期限以下なら変更せず200を返します。 until と months が両方ある場合は until を優先します。 months は期限内なら現在の期限から、期限切れなら現在時刻から加算します。再送による二重加算を防ぐため必ず冪等キーを使ってください。 体験版には販売者に設定された体験版期限上限が適用されます。

expire は指定した利用者と同じEA・口座番号に属する未失効行すべて(体験版を含む)を at に設定します。 既に期限切れの行は変更しません。応答は {"user":{...上記の利用者情報...},"expiredCount":2} です。 指定したIDの行が期限切れでも、同じ組の有効な別行があれば対象になります。削除APIはありません。

既存利用者を検索する ​

GET /api/v1/manager/users?applicationName=SampleEA&accountNumber=12345678&email=customer%40example.com

各条件は省略でき、指定した条件をすべて満たす利用者を {"users":[...]} で返します。 期限切れ・体験版も含みます。Password・Memo・Messageは応答に含まれません。 移行時に検索して userId を保存し、以後の延長・失効はIDで指定してください。 まとめて取り込むなら、ユーザー管理画面の「CSV」ボタンでも同じ情報を書き出せます(先頭列が userId)。 再購読も保存済みの userId を使って延長します。有効な体験版がない場合の作成は、既存の通常ユーザーとメール・口座・EA・パスワードが完全一致すると400、異なる場合は別行を作るため、再購読のたびに作成APIを呼ばないでください。

EA・インジケーターの情報を取得する ​

GET /api/v1/manager/applications

所有しているEA・インジケーターの一覧を返します。?applicationName=SampleEA で1件に絞れます。

json
{"applications": [{
  "applicationId": 1166,
  "applicationName": "SampleEA",
  "version": "1.02",
  "downloadUrl": "https://example.com/SampleEA.zip",
  "autoAddUser": true,
  "message": "メンテナンスのお知らせ",
  "messageViewStart": "2026-09-20T00:00:00+09:00",
  "messageViewEnd": "2026-09-27T00:00:00+09:00",
  "userCount": 9,
  "trialCount": 3
}]}
項目内容
applicationId更新APIで指定するID
version / downloadUrlアップデート通知に使う最新バージョンとダウンロード先
autoAddUser体験版の自動作成が有効かどうか(読み取り専用)
message / messageViewStart / messageViewEnd一斉メッセージと表示期間。未設定なら空文字とnull
userCount / trialCount通常ユーザー数と体験版ユーザー数

バージョン・ダウンロードURL・一斉メッセージを更新する ​

PATCH /api/v1/manager/applications/{applicationId}

json
{
  "version": "1.03",
  "downloadUrl": "https://example.com/SampleEA_103.zip",
  "message": "v1.03を公開しました。ダウンロードしてご利用ください。",
  "messageViewStart": "2026-09-20T00:00:00+09:00",
  "messageViewEnd": "2026-09-27T00:00:00+09:00"
}

送ったプロパティだけが変わります。 version だけ送れば、一斉メッセージやダウンロードURLはそのままです。 更新後の状態を、取得APIと同じ形で返します。

  • message に空文字を送ると一斉メッセージを停止します
  • messageViewStart / messageViewEnd は日時のオフセットが必要です
  • applicationName と autoAddUser は変更できません(送ると400)。 EA名はソースコードに書き込んで配布しているため、変更すると配布済みのEA・インジケーターの 認証が通らなくなります。体験版の自動作成も、配布済みの動作が外部から変わってしまうため 除いています。どちらも管理画面からは従来どおり変更できます

ビルドから配布までを自動化している場合、公開処理の最後にこのAPIを呼ぶと、 バージョンの更新漏れがなくなります。

利用者へ個別メッセージを送る ​

PATCH /api/v1/manager/users/{userId}/message

json
{
  "message": "お支払いの確認が取れませんでした。サポートまでご連絡ください。",
  "messageViewStart": "2026-09-20T00:00:00+09:00",
  "messageViewEnd": "2026-09-27T00:00:00+09:00"
}

指定した利用者のチャートにだけ表示されます。利用期限・口座番号などほかの項目は変わりません。 空文字を送ると消去します。

決済が失敗した契約者へ案内を出す、といった用途に使えます。

エラーと再試行 ​

json
{"error":{"code":"manager_plan_restricted","message":"販売者のプラン制限により操作できません。プランを確認してください。"}}
HTTPcode対応
400 / 413invalid_request入力形式・必須項目・ボディサイズ(64KiBまで)を確認
401invalid_api_keyキーの設定・失効状態を確認
403manager_plan_restricted販売者のプラン期限・プラン制限を確認し、販売者にアラート
403user_cap_reached登録上限を確認し、販売者にアラート
404not_foundIDまたはEA名を確認。他販売者の利用者も404
422idempotency_conflict冪等キーの使い回しを修正
429rate_limit_exceededRetry-After(60秒)後に同じ要求を再送

既存管理画面と同じプラン制限を使います。Free枠内では操作できます。期限切れの通常ユーザー・体験版は通常ユーザー上限に数えません。 403を放置すると「購入者は支払ったのに利用できない」状態になるため、必ず運用担当へ通知してください。 Webhookの受信側は、署名検証したイベントを永続キューへ保存できた時点でStripeへ2xxを返し、MQLAuthへの送信はワーカーで行います。 403になった処理は運用担当がプラン修正後に再開します。この際、保存済み403の再生を避けるため、例えば event.id:extend:retry1 のように新しい冪等キーを採番・保存して再実行してください。Stripeの同一イベント再送だけでは403は解消しません。 キー単位で60秒間に120回までです。429・通信失敗・5xxでは同じ冪等キーとボディを使って間隔を空けて再送します。

Stripe連携の手順 ​

Webhookは自社のサーバーで受信し、Stripeの署名を検証してから永続キューに保存します。 イベントが欠落・重複・順序逆転しても再処理できるよう、subscription単位で処理順序を管理してください。 Stripeの署名検証と配送・再送の扱いは Stripe公式Webhookガイド を参照してください。

Stripeイベント推奨するMQLAuth操作
checkout.session.completed支払い完了を確認し create。返された userId をsubscription metadataへ保存
invoice.paidextend の until に支払い済み対象期間の current_period_end を送信
invoice.payment_failedMQLAuthへは何もしない。Stripe Smart Retriesに任せる
customer.subscription.deletedexpire の at に支払い済み期間の current_period_end を送信。即時失効にしない

決済イベントの意味とSmart Retriesは Stripe公式のsubscription Webhook説明 で確認できます。 Checkout完了でも非同期決済が未払いのことがあるため、支払い確定前に有料利用権を作らないでください。

current_period_end はUnix秒から new Date(periodEnd * 1000).toISOString() で変換します。 Stripe APIバージョン2025-03-31.basil以降では、期間はsubscription直下ではなく**対象subscription itemの current_period_end**です。 複数商品の契約では、対象EAに対応するitemを選びます。Stripeの変更説明

次は署名検証・支払い確認・対象item特定を済ませたワーカー内の処理例です。 paidPeriodEnd は支払い済みの期間を表すUnix秒で、自社DBに保存した値です。 初回送信前にパス・ボディ文字列・冪等キーを保存し、再試行時はその値を使ってください。

js
async function callMqlAuth(path, serializedBody, idempotencyKey) {
  const response = await fetch(`https://mql-auth.com/api/v1/manager/users${path}`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.MQLAUTH_API_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': idempotencyKey,
    },
    body: serializedBody,
  })
  const result = await response.json()
  if (!response.ok) {
    // キュー側で429/5xx/通信失敗を再試行。403は販売者へ通知する。
    throw Object.assign(new Error(result.error?.message), {
      status: response.status, code: result.error?.code,
    })
  }
  return result
}

// checkout.session.completed: この要求内容を永続化してから実行
const body = JSON.stringify({
  applicationName: 'SampleEA', accountNumber, userName, email,
  userPeriod: new Date(paidPeriodEnd * 1000).toISOString(), isTestUser: false,
})
const user = await callMqlAuth('', body, `${event.id}:create`)
await stripe.subscriptions.update(subscriptionId, {
  metadata: { mqlauth_user_id: String(user.userId) },
})
// metadataの更新失敗時も、保存したcreate要求を再送すれば同じuserIdを回収できる。

// invoice.paid: 保存済みuserIdを使用
await callMqlAuth(`/${userId}/extend`, JSON.stringify({
  until: new Date(paidPeriodEnd * 1000).toISOString(),
}), `${event.id}:extend`)

// customer.subscription.deleted: 支払い済み期間を残す
await callMqlAuth(`/${userId}/expire`, JSON.stringify({
  at: new Date(paidPeriodEnd * 1000).toISOString(),
}), `${event.id}:expire`)

invoice.paid が初回作成より先に届いた場合は、作成とmetadata保存が完了するまでキューで待ちます。 古い解約イベントで新しい購入を失効させないよう、外部側でも契約世代と支払い状態を照合してください。 猶予期間を設ける場合は、送信する期限にあらかじめ織り込みます。MQLAuthは自動で猶予を加えません。

MQLAuth マニュアル