V-REC受け取る。使う。つながる。
実装フロー

V-REC 現行API 実装フロー

Merchantユーザー登録からKYC、Corporate Payout、Tenant Funding、ユーザーCREDIT、カード、残高照合までを現在の実装順に整理します。

現行版の重要な認可条件(2026-10-10)

Tenant FundingはV-RECのHMACスコープに加え、SAKURA側で加盟店の明示的再認可によるtenant_fundingスコープ、接続先Merchant/origin/programに一致するTenant binding、実行許可と照合状態が必要です。既存接続への自動スコープ付与は行いません。

GET /api/merchant/v1/tenant-funding/diagnostics?user_id=usr_... でschema・SAKURA接続・Membershipと実行可否を確認できます。READONLY会員はカードのmask表示が可能な場合でも新規資金割当不可です。

オンライン授業・Googleカレンダー・トークン送金フロー

External logged-in learner → Merchant backend (user-session check)
  → V-REC HMAC Merchant API → SAKURA Connected Apps → Merchant learning

1. GET  /api/merchant/v1/learning/users/{id}/progress
2. GET  /api/merchant/v1/learning/programs/{id}/sessions
3. User clicks google_calendar_add_url, or
   POST /api/merchant/v1/learning/users/{id}/calendar-sync (consented OAuth only)
4. After ends_at: POST /api/merchant/v1/learning/sessions/{id}/complete
5. GET  /api/merchant/v1/learning/rewards (check reward status)

Independent merchant-funded token transfer:
1. GET  /api/merchant/v1/token-pool
2. POST /api/merchant/v1/token-pool/transfers (request_id, amount, user_id, merchant_code)
3. GET  /api/merchant/v1/token-pool/transfers/{request_id}
4. Reconcile submitted / ambiguous operations before considering confirmation.

HMAC・Connected Apps双方の権限、ACTIVE/FULL会員とMerchant紐付けが必須です。Google未承認では自動同期できず、プール送金は原資ウォレットと承認済みリレイヤーがない限り実行できません。

API details / IN & OUT →

1. API境界を先に分ける

加盟店サーバーAPI

/api/merchant/v1/*

ユーザー管理・KYC状態・mask済みカード・Merchant帰属参照

法人/パートナーPayout API

/api/v1/payouts*

Payout指示の作成・状態照会

利用者セッションAPI

/api/v1/me/*

本人KYC・カード・本人残高

SAKURA連携アプリ(Connected Apps)

/api/integrations/vrec/*

内部連携。外部Merchantが直接呼ばない

外部サイト主導のeKYCリンク送付フロー

Merchant APIのCredentialに kyc.preload / kyc.link.issue を付与した加盟店は、本人の同意を記録したうえでV-RECとSAKURAにプロフィール・KYC書類を事前登録できます(権限はMerchant Portal → Merchant APIで加盟店自身が確認チェック付きで付与します)。最後に本人へSAKURAのeKYC短縮URLを送るため、V-REC/SAKURAの初回パスワード設定メールは不要です。

Merchant backend                 V-REC API                    SAKURA/MatchMove
1. GET /profile-options         -> current allowed country/dial codes
2. POST /users (ekyc_only)      -> SAKURA provision             -> user_ref
3. GET /users/{id}/kyc/schema   -> SAKURA KYCFORM             -> field types/options
4. POST /users/{id}/kyc/preload -> SAKURA draft submission     -> validated draft
5. GET /users/{id}/kyc/preload-status -> SAKURA state / owner
   POST /users/{id}/kyc/preload-reconcile (only authorized correction)
6. POST /users/{id}/kyc/onboarding-link -> SAKURA eKYC short URL
7. Deliver URL to verified user -> User agrees to SAKURA terms -> MatchMove eKYC
8. GET /users/{id}/kyc          -> Poll / stage=final_review if SAKURA not approved    -> final review result

APIキーの明示権限: users.write、kyc.preload、kyc.link.issue、kyc.read。eKYCリンク発行は202で準備中、409でKYC未完了等。本人確認の提出とAPPROVEDは異なります。

API details →

2. Merchantからユーザー登録

GET  /api/merchant/v1/context
GET  /api/merchant/v1/profile-options
POST /api/merchant/v1/users
     Idempotency-Key: merchant-user-123

Optional request controls:
  notifications.send_vrec_activation_email = true|false
  notifications.send_sakura_password_setup_email = true|false

Default when omitted: both = true

Save:
  user.public_id
  beneficiary_id
  activation_url (new V-REC login only)
  notifications.vrec_activation_email
  notifications.sakura_password_setup_email

country_code / dial_codeはprofile-optionsの返却値から選択します。SAKURAがプロフィール正本です。ユーザー作成APIではV-RECパスワード設定メールとSAKURAパスワード設定メールを独立してON/OFFできます。V-RECメールは新規ローカルログイン作成時のみ、SAKURAメールはSAKURAがone-time password_setup_urlを返した場合のみ対象です。SAKURAのsetup URLはMerchant APIへ返しません。

3. KYCは本人セッションへ引き渡す

Merchant backend:
POST /api/merchant/v1/users/{id}/kyc/start
        ↓ V-REC login URL only
User browser:
GET  /api/v1/me/kyc/form
POST /api/v1/me/kyc/submit
        ↓ next_action
SAKURA / MatchMove review
        ↓
Merchant webhook: user.kyc.updated
GET /api/merchant/v1/users/{id}/kyc   # reconciliation

従来のkyc/startは本人ログインを要求します。ただし運営承認済みの新フローkyc/onboarding-linkはeKYC URLを返します。

4. ユーザーへ資金を送る起点はPayout API

GET  /api/v1/beneficiaries/{beneficiary_id}/status
POST /api/v1/payouts
Idempotency-Key: corp-payment-20261021-001

{
  "beneficiary_id": "VREC-...",
  "amount": "100.00",
  "currency": "USD",
  "funding_mode": "MERCHANT_BALANCE",
  "source_asset": "MATCHMOVEUSD",
  "destination_asset": "MATCHMOVEUSD",
  "external_reference": "invoice-001",
  "purpose": "corporate_payout"
}
        ↓ 201 status=PENDING_FUNDS (KYC approved) / AWAITING_KYC
POST /api/v1/payouts/{id}/fund            body: {}
        ↓ 200  read status + merchant_transfer_status
  COMPLETED + CREDITED   → done
  RETRYABLE              → fix merchant_pre_submission_reject_code, /fund again (same payout) or /cancel
     └ corporate_payout_merchant_approval_required
         → Merchant approves in SAKURA → GET /approval-status (fund_retry_permitted=true) → /fund
  SUBMITTING / RECONCILE_REQUIRED / COMPLETED+FUNDED
                         → POST /api/v1/payouts/{id}/reconcile  body: {}   (never a new payout)

funding_mode・source_asset・destination_asset・external_reference は必須です。funding_modeを省略すると旧LEGACY_REFERENCEとして拒否されます。POST /payoutsの201は資金移動ではなく、/fund で送金し、SAKURAの送金証跡を検証できた時点でCREDITEDになります。署名方式・全エラーコードは開発者ページとPayout OpenAPIを参照してください。 Partner署名方式 →

帳票の組み立て方:Payout / Tenant Funding / Transactions

Tenant FundingとPayoutは別の入金起点です。CREDITは元イベントを資金台帳へ記録したものなので、2回入金されたものとして集計しません。

Direct Tenant Funding → vrec_tenant_allocations (COMPLETED) → ledger_lots + ledger_entries (CREDIT)
Corporate Payout → payouts (CREDITED) → ledger_lots + ledger_entries (CREDIT)
Tenant Return → vrec_tenant_returns (COMPLETED) → ledger_entries (TENANT_RETURN)
Card settlement → V-REC internal card_transactions + MatchMove issuer statement (distinct views)
USDT transfer → SAKURA wallet transfer history (USDT; not a USD tenant allocation)
Crypto sale → payment_asset: USDT or CUSTOM_TOKEN → goods: SGP-USD or merchant points

API・取引ID・資産表示の詳細を見る →

5. Tenant Funding:事前確認 → 直接Allocation / Payout → SAKURA確定

Merchant direct allocation
GET /api/merchant/v1/tenant-funding/balance
GET /api/merchant/v1/tenant-funding/users/{id}/capacity
        ↓
Required:
  membership.status = ACTIVE
  access_mode = FULL
  can_receive_tenant_funds = true
  source SAKURA Merchant = target Tenant Merchant
  SAKURA management_enabled = true
        ↓
  allocatable_amount = tenant available − funding_fee
        ↓
POST /api/merchant/v1/tenant-funding/allocations
Idempotency-Key: same logical operation
        ↓
POST SAKURA /api/integrations/vrec/tenant-funding/fund
        ↓
  amount + fee > available, Merchant wallet short,
  or another operation in progress (operation_in_progress / unresolved_request_exists)
    → HTTP 409 + status REJECTED (no funds moved; final — retry with a NEW Idempotency-Key)
  temporary conflict / network
    → HTTP 202 + status UNKNOWN (retry with the same Idempotency-Key)
        ↓
COMPLETED for exact principal (HTTP 201)
        ↓
V-REC creates tenant-origin provenance lot
+ expiry_policy / granted_at / expires_at snapshot

Payout route (historical LEGACY_REFERENCE payouts only)
PENDING_FUNDS → same guard → SAKURA fund → CREDITED
New MERCHANT_BALANCE payouts are never funded by Tenant Funding.

Result collection (cron)
GET /api/merchant/v1/tenant-funding/allocations?updated_since=…&limit=200
  → follow next_cursor while has_more = true
  → keep the last item's updated_at for the next run
  (or receive tenant.funding.allocation.updated webhooks)

Cronで結果を取得する場合は、前回取得した最後の updated_at を updated_since に指定し、has_more が false になるまで next_cursor で続きを取得してください。結果が変わったAllocationは updated_at が更新されるため、同じAllocationが再度返ることがあります(id で重複を除いてください)。COMPLETED / REJECTED / FAILED / MISMATCH は確定状態です。

READONLY Membershipはmask済みカード情報を参照できても、新規Tenant資金の割当は403で拒否します。SAKURA側でもSource MerchantとTenant Merchantの一致を再確認するため、表示権限からMatchMove上の資金移転権限へ昇格しません。

180日制限等はSAKURAが実行時に返すexpiry snapshotをlotへ保存します。期限はV-REC側で再起算しません。

6. V-RECでCREDITになる条件

Corporate Payout (MERCHANT_BALANCE, MATCHMOVEUSD → MATCHMOVEUSD)
  SAKURA status = COMPLETED
  AND same payout_ref, beneficiary (user_ref), asset, currency and amount
  AND MatchMove provider_tx_id AND SAKURA transfer_uuid present and not reused
        ↓ evidence stored: underlying_fund_confirmed = 1, status = FUNDED
  AND beneficiary KYC = APPROVED AND membership can_spend
        ↓
Create ledger lot (source_type = CORPORATE_PAYOUT)
        ↓
Payout status = CREDITED   (otherwise stays FUNDED; /reconcile retries the lot only)

Tenant-funded payout (historical LEGACY_REFERENCE only)
  SAKURA tenant fund request COMPLETED → funding_reference "sakura:*" → CREDITED

Tenant Funding対象Merchantは従来のmanual fund-confirmではCREDITできません。SAKURA COMPLETEDを経由した資金だけをユーザー残高へ反映します。

7. カードは本人Session API

KYC APPROVED
   ↓
POST /api/v1/me/cards/VIRTUAL
or POST /api/v1/me/cards/PHYSICAL
   ↓
SAKURA / MatchMove issue
   ↓
V-REC automatically stores card linkage
   ↓
GET /api/v1/me/cards

Merchant APIからはmask済みカード参照と既存Physical CardのProxy紐付けのみ可能です。PAN/CVVは本人がcurrent_passwordでstep-upした /api/v1/me/cards/{id}/sensitive だけです。

カード本人操作(V-RECログインのみ)

POST /api/v1/me/cards/{id}/sensitive
  _csrf + current_password  → PAN / expiry / CVV (no-store)
POST /api/v1/me/cards/{id}/pin
  _csrf + current_password + pin + pin_confirmation  → {"success":true}
GET /api/v1/me/cards/{id}/issuer-transactions?from=YYYY-MM-DD&to=YYYY-MM-DD&page=1
  → issuer card transactions (limit=20)

PIN設定は物理かつACTIVEカードのみ。SAKURA Connected Appのcard_sensitiveスコープが必要です。履歴はcardsスコープを使用し、V-RECのSGPUSD台帳や保留審査履歴とは別です。これらをMerchant HMACで呼ぶことはできません。

8. 残高・取引は用途別に確認

GET/api/merchant/v1/users/balances

自Merchantのユーザー残高を一括取得(最大200件/回、next_cursorで続き)

GET/api/merchant/v1/users/{id}/balance

Merchant帰属残高

GET/api/merchant/v1/users/{id}/transactions

Merchant帰属取引

GET/api/merchant/v1/payouts

Merchantに関連するPayout

GET/api/v1/me/balance

本人V-REC残高

GET/api/v1/me/payouts

本人が受け取ったPayout

Merchant帰属残高と本人残高は同一概念ではありません。表示用途に応じて使い分けてください。

SAKURAのSGPUSD残高は総残高と外部利用可能額を区別します。V-REC暗号資産売買由来の保留ロットは、AML承認および手動prefund確認が終わるまでカード充当・銀行/エージェント出金・V-Pay残高決済に利用できません。通常のP2Pでは承認状態を引き継ぎます。V-RECのGET /api/v1/me/balanceはMatchMoveカード充当可能額を返すAPIではありません。

Webhook詳細仕様:会員登録・テナント資金・通知時刻・状態・MatchMove 3Dセキュア →

9. Webhookを主系、GETを照合系にする

SAKURA / provider change
        ↓
V-REC re-reads authoritative state
        ↓
Signed Merchant / Partner webhook
        ↓
Receiver verifies raw-body HMAC
        ↓
Idempotent processing by event/delivery id
        ↓
GET status endpoint when reconciliation is needed

10. Fail closed と再試行

テナント資金管理

SAKURA status不明、切断、tenant停止、execute権限OFFの場合は資金移転しない。

冪等性

User作成、Physical link、Payout、Tenant Allocation、reverse/returnは同じ論理操作の再送で同じIdempotency-Keyを使う。新しいKeyで再送すると二重Operationになる可能性があります。

Webhook通知

raw body署名検証。delivery id / payload idで重複排除。