MisarMisar Docs
MisarMailMisarBlogMisarReachMisarPostMisarDevMisarCoderMisarSEOMisar PlatformMisar SSO
Universal Wallet

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/status

Authentication

Both endpoints accept either mode:

SSO bearer (own wallet)
Authorization: Bearer <sso_access_token>
Service key (any wallet)
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

POST/io/wallet/connect/onboard

Creates 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

returnUrlstringbodyrequired

Absolute URL the user returns to after Stripe's hosted onboarding. Must be an absolute URL on a Misar host — anything else is rejected.

user_idstringbody

Required with a service key; ignored with an SSO bearer. Must be a valid UUID.

Response fields

urlstring

The Stripe-hosted onboarding URL. Redirect the user here.

accountIdstring

The Stripe Connect account id (acct_…) for this user.

Request
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" }'
200 — Account link created
{
  "url": "https://connect.stripe.com/setup/e/acct_1Qx.../abcdef",
  "accountId": "acct_1QxAbCDeFgHiJkLm"
}

Status codes

CodeMeaning
200Account link created.
400Malformed JSON, user_id is not a valid UUID, or returnUrl is missing / not an absolute Misar URL.
401Neither a valid SSO bearer nor a valid x-wallet-service-key was supplied.
429Wallet write rate limit exceeded (50 write ops/user/60 s). Includes Retry-After.
500The Connect account was created but could not be persisted.
502Stripe 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

GET/io/wallet/connect/status

Returns 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_idstringquery

Required with a service key; ignored with an SSO bearer. Must be a valid UUID.

Response fields

balancenumber

Total credit balance.

withdrawablenumber

Portion of the balance that is cash-out eligible (earned credit, not purchased credit).

effectiveWithdrawablenumber

What can actually be withdrawn right now, after pending withdrawals and daily caps are applied.

minWithdrawalDollarsnumber

Minimum a single withdrawal may be. Currently 10.

currencystring

Payout currency.

connectAccountIdstring | null

The Stripe acct_… id, or null if onboarding has never been started.

hasConnectAccountboolean

Whether a Connect account exists.

detailsSubmittedboolean

Whether the user finished Stripe's onboarding form.

payoutsEnabledboolean

Whether Stripe has cleared the account for payouts. Withdrawals are blocked until this is true.

connectStatusstring

Coarse onboarding state, e.g. pending.

pendingWithdrawalsnumber

Withdrawal requests currently in flight. Capped at 3 concurrently.

totalWithdrawnnumber

Lifetime credits paid out.

Request
curl "https://api.misar.io/io/wallet/connect/status" \
  -H "Authorization: Bearer $SSO_ACCESS_TOKEN"
200 — OK
{
  "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

CodeMeaning
200Summary returned.
400user_id is not a valid UUID.
401Neither a valid SSO bearer nor a valid x-wallet-service-key was supplied.
429Wallet read rate limit exceeded (200 read ops/user/60 s). Includes Retry-After.
500The withdrawal summary could not be read.

Withdrawal limits

LimitValue
Minimum withdrawal$10
Maximum withdrawal$100,000
Concurrent pending withdrawals3
Daily withdrawal cap$10,000

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.