Connect & Payout Status
POST /io/wallet/connect/onboard and GET /io/wallet/connect/status — Stripe Connect Express onboarding and withdrawal eligibility.
Before a user can cash credits out to a bank account, they must complete Stripe Connect Express onboarding. These two endpoints start that flow and report its state.
POST https://api.misar.io/io/wallet/connect/onboard
GET https://api.misar.io/io/wallet/connect/statusAuthentication
Both endpoints accept either mode:
Authorization: Bearer <sso_access_token>x-wallet-service-key: <WALLET_SERVICE_KEY>With a service key, onboard reads user_id from the body and status reads it from the query string.
Start onboarding
/io/wallet/connect/onboardCreates a Stripe Connect Express account the first time it is called (persisted on the wallet), then always returns a fresh Account Link. Account Links are short-lived and single-use — call this endpoint again rather than caching the URL.
Request body
returnUrlstringbodyrequiredAbsolute URL the user returns to after Stripe's hosted onboarding. Must be an absolute URL on a Misar host — anything else is rejected.
user_idstringbodyRequired with a service key; ignored with an SSO bearer. Must be a valid UUID.
Response fields
urlstringThe Stripe-hosted onboarding URL. Redirect the user here.
accountIdstringThe Stripe Connect account id (acct_…) for this user.
curl -X POST "https://api.misar.io/io/wallet/connect/onboard" \
-H "Authorization: Bearer $SSO_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "returnUrl": "https://mail.misar.io/settings/billing" }'{
"url": "https://connect.stripe.com/setup/e/acct_1Qx.../abcdef",
"accountId": "acct_1QxAbCDeFgHiJkLm"
}Status codes
| Code | Meaning |
|---|---|
200 | Account link created. |
400 | Malformed JSON, user_id is not a valid UUID, or returnUrl is missing / not an absolute Misar URL. |
401 | Neither a valid SSO bearer nor a valid x-wallet-service-key was supplied. |
429 | Wallet write rate limit exceeded (50 write ops/user/60 s). Includes Retry-After. |
500 | The Connect account was created but could not be persisted. |
502 | Stripe rejected or failed the account / account-link creation. |
KYC happens inside Stripe
Identity verification runs entirely in Stripe's hosted flow. Misar never sees the documents. Stripe then fires account.updated, which flips payoutsEnabled on the wallet. Withdrawals stay blocked until that happens.
Read status
/io/wallet/connect/statusReturns the wallet's balances, cash-out eligibility, and Connect/KYC state in one call — enough to render a complete withdrawal screen without a second request.
Query parameters
user_idstringqueryRequired with a service key; ignored with an SSO bearer. Must be a valid UUID.
Response fields
balancenumberTotal credit balance.
withdrawablenumberPortion of the balance that is cash-out eligible (earned credit, not purchased credit).
effectiveWithdrawablenumberWhat can actually be withdrawn right now, after pending withdrawals and daily caps are applied.
minWithdrawalDollarsnumberMinimum a single withdrawal may be. Currently 10.
currencystringPayout currency.
connectAccountIdstring | nullThe Stripe acct_… id, or null if onboarding has never been started.
hasConnectAccountbooleanWhether a Connect account exists.
detailsSubmittedbooleanWhether the user finished Stripe's onboarding form.
payoutsEnabledbooleanWhether Stripe has cleared the account for payouts. Withdrawals are blocked until this is true.
connectStatusstringCoarse onboarding state, e.g. pending.
pendingWithdrawalsnumberWithdrawal requests currently in flight. Capped at 3 concurrently.
totalWithdrawnnumberLifetime credits paid out.
curl "https://api.misar.io/io/wallet/connect/status" \
-H "Authorization: Bearer $SSO_ACCESS_TOKEN"{
"balance": 142.5,
"withdrawable": 90,
"effectiveWithdrawable": 90,
"minWithdrawalDollars": 10,
"currency": "usd",
"connectAccountId": "acct_1QxAbCDeFgHiJkLm",
"hasConnectAccount": true,
"detailsSubmitted": true,
"payoutsEnabled": true,
"connectStatus": "active",
"pendingWithdrawals": 0,
"totalWithdrawn": 250
}Status codes
| Code | Meaning |
|---|---|
200 | Summary returned. |
400 | user_id is not a valid UUID. |
401 | Neither a valid SSO bearer nor a valid x-wallet-service-key was supplied. |
429 | Wallet read rate limit exceeded (200 read ops/user/60 s). Includes Retry-After. |
500 | The withdrawal summary could not be read. |
Withdrawal limits
| Limit | Value |
|---|---|
| Minimum withdrawal | $10 |
| Maximum withdrawal | $100,000 |
| Concurrent pending withdrawals | 3 |
| Daily withdrawal cap | $10,000 |
Recommended flow
Read status
Call GET /io/wallet/connect/status. If payoutsEnabled is true, show the withdrawal form.
Otherwise, onboard
Call POST /io/wallet/connect/onboard with a returnUrl and redirect the user to url.
Re-check on return
When the user lands back on returnUrl, read status again. payoutsEnabled flips only once Stripe clears the account, which may lag the redirect.
Withdraw
Call POST /io/wallet/withdraw, then track it via GET /io/wallet/withdrawals.