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未承認では自動同期できず、プール送金は原資ウォレットと承認済みリレイヤーがない限り実行できません。
1. API境界を先に分ける
/api/merchant/v1/*
ユーザー管理・KYC状態・mask済みカード・Merchant帰属参照
/api/v1/payouts*
Payout指示の作成・状態照会
/api/v1/me/*
本人KYC・カード・本人残高
/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は異なります。
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_emailcountry_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
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:*" → CREDITEDTenant 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/cardsMerchant 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. 残高・取引は用途別に確認
/api/merchant/v1/users/balances自Merchantのユーザー残高を一括取得(最大200件/回、next_cursorで続き)
/api/merchant/v1/users/{id}/balanceMerchant帰属残高
/api/merchant/v1/users/{id}/transactionsMerchant帰属取引
/api/merchant/v1/payoutsMerchantに関連するPayout
/api/v1/me/balance本人V-REC残高
/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 needed10. Fail closed と再試行
SAKURA status不明、切断、tenant停止、execute権限OFFの場合は資金移転しない。
User作成、Physical link、Payout、Tenant Allocation、reverse/returnは同じ論理操作の再送で同じIdempotency-Keyを使う。新しいKeyで再送すると二重Operationになる可能性があります。
raw body署名検証。delivery id / payload idで重複排除。
11. 既存SAKURAユーザーを本人同意で接続
Merchant backend
POST /api/merchant/v1/user-links
Idempotency-Key: <same logical request key>
↓
authorization_url
↓
User opens SAKURA page
login → review V-REC Merchant → approve / deny
↓
SAKURA callback → V-REC
state + one-time code + remote link_request_id validation
↓
V-REC exchanges code for stable SAKURA user UUID
↓
Global User reuse/create + Tenant membership
↓
GET /api/merchant/v1/user-links/{id}
PENDING / COMPLETED / DENIED / EXPIRED
linked_user_id
membership.access_mode = FULL | READONLYMerchantはメールアドレスやSAKURA User IDで既存identityを強制指定できません。Source MerchantとTarget Merchantが同一ならFULL候補、異MerchantならREADONLYです。READONLYではカード情報・参照残高の閲覧を許可できますが、Tenant Allocation、Payout、spend等の新規資金移動は拒否されます。