Skip to main content
At the end of this page, you will have a user whose safe_creation_status is completed, whose primary_smart_wallet_address is populated, and a wallet assets call that returns a JSON body listing their balances. This is the full partner onboarding flow — account creation, , Safe deployment, and first read. When the Safe lands, the identity is live. Everything downstream is a read against what this flow wrote. The final read:

Prerequisites

  • A Platform API JWT from your configured auth provider — Dynamic Labs, Privy, or . See Authentication.
  • Your Sumvin organisation ID for the x-juno-orgid header — every partner integration scopes requests to an org.
  • SumSub sandbox credentials — only required for the full WebSDK KYC flow. Skip if you plan to use document-only mode.
  • Base URL https://api.sumvin.com/v0.
  • Default chain for this quickstart: chain_id: 1329 (Sei).
SumSub sandbox credentials are only needed when you integrate SumSub’s hosted WebSDK or run the hybrid KYC flow. If your integration uses document-only mode, you upload documents through the Sumvin API and do not need SumSub credentials yourself — contact your account manager only if WebSDK or hybrid is in scope.
1

Create the user

Create the user record with their primary EOA address. The response includes a safe_creation_status: processing — the Safe deployment worker has started in the background while you work through the remaining steps.
The EOA must already be verified by your auth provider (Dynamic Labs or Privy) before this call. Sumvin rejects unverified addresses — the JWT in x-juno-jwt is how we confirm the user owns the EOA. If the provider has not completed its wallet verification step, the account creation call returns 403 Forbidden.POST /v0/user/ — Create the user account.
curl -X POST https://api.sumvin.com/v0/user/ \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{
    "primary_eoa_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD78",
    "chain_id": 1329
  }'
Using TanStack Query? See mutation patterns for the retry + isNonRetryable filter useCreateUser applies on failure.
Response: 201 Created with user.safe_creation_status: "processing".
2

Walk the onboarding state machine

The onboarding state machine is server-driven — you fetch the current step, submit the prompted data, and poll again. Step statuses are pending, current, submitted, completed, or skipped.
curl "https://api.sumvin.com/v0/user/me?expand=onboarding" \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response: 200 OK
{
  "user": {
    "id": "usr_abc123",
    "safe_creation_status": "processing"
  },
  "onboarding": {
    "current_step": "phone_verification",
    "is_complete": false,
    "steps": [
      { "step": "created", "status": "completed", "gated": false, "meta": null },
      { "step": "phone_verification", "status": "current", "gated": false, "meta": null },
      { "step": "kyc_verification", "status": "pending", "gated": false, "meta": null },
      { "step": "open_banking", "status": "pending", "gated": false, "meta": null },
      { "step": "card_setup", "status": "pending", "gated": false, "meta": null },
      { "step": "feature_selection", "status": "pending", "gated": false, "meta": null },
      { "step": "complete", "status": "pending", "gated": false, "meta": null }
    ]
  }
}
For phone_verification, request a code and then confirm it. kyc_verification advances automatically as soon as the SumSub review completes. See the onboarding guide for every step in detail.
3

Complete KYC

Sumvin supports three KYC modes:
  • websdk — launch SumSub’s hosted web SDK on the client. Simplest flow.
  • hybrid — mix of Sumvin-collected fields plus SumSub SDK.
  • document_only — upload document images directly through the KYC documents endpoint.
The quickstart path is websdk:
To use the WebSDK path, your organisation needs its own SumSub access token provisioned on the Sumvin side. Contact Sumvin directly to have it set up before you reach this step — without it, the access-token exchange returns 500 Internal Server Error with KYC-500-002. Document-only mode does not require this.POST /v0/kyc/access-token — Exchange for a SumSub access token.
# 1. Exchange for a SumSub access token.
curl -X POST https://api.sumvin.com/v0/kyc/access-token \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response:
{ "access_token": "_act-sbx-...", "expires_at": 1740000900000 }
# 2. Launch the SumSub Web SDK on the client with that token.
#    (SumSub's own JS SDK — not a Sumvin API call.)

# 3. Poll for KYC status once the user finishes the SDK flow.
curl "https://api.sumvin.com/v0/kyc/status?refresh=true" \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response when approved:
{
  "status": "approved",
  "verified_at": 1740001200000,
  "_links": {
    "self": { "href": "/v0/kyc/status" },
    "user": { "href": "/v0/user/me" }
  }
}
See the KYC guide for the hybrid and document_only branches.
4

Add the smart account wallet

Adding a wallet and marking it primary triggers Safe deployment on the wallet’s chain if a Safe does not already exist there. Create the wallet record, then PATCH it to promote it.
The wallet’s EOA address must be verified by your auth provider (Dynamic Labs or Privy) before this call — credential_id references a verified credential on the provider side. If Sumvin can’t resolve the credential on the provider, the endpoint returns 404 Not Found with DYN-404-001 (credential not present) or 502 Bad Gateway with DYN-502-001 (provider unreachable). For the adjacent POST /v0/user/ flow, passing a primary_eoa_address that isn’t in your verified credentials returns 403 Forbidden with WAL-403-003 (WALLET_NOT_VERIFIED).
# Create the wallet
curl -X POST https://api.sumvin.com/v0/wallets/ \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{ "credential_id": "cred_abc123" }'

# Promote to primary — triggers Safe creation on chain 1329
curl -X PATCH https://api.sumvin.com/v0/wallets/wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{ "is_primary": true }'
Using TanStack Query? See optimistic mutationsuseUpdateWallet flips is_primary in the cache during onMutate and rolls back on error, so the UI never waits for the 202 round trip.
PATCH response: 202 Accepted
{
  "id": "wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD78",
  "chain_id": 1329,
  "is_primary": true,
  "is_eoa": true,
  "nickname": null,
  "logo_uri": null,
  "created_at": 1740000001000,
  "deleted_at": null,
  "safe_creation_event_id": "evt_safe_9a7d2f",
  "_links": {
    "self": { "href": "/v0/wallets/wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4" },
    "user": { "href": "/v0/user/me" },
    "safe-status": { "href": "/v0/user/me" }
  }
}
See the wallets guide for the three ownership verification methods (credential_id, SIWE, and raw address).
5

Poll for Safe deployment

Poll the user account endpoint until safe_creation_status is completed and primary_smart_wallet_address is populated.GET /v0/user/me — Fetch the user account.
curl https://api.sumvin.com/v0/user/me \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Response: 200 OK
{
  "user": {
    "id": "usr_abc123",
    "primary_eoa_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD78",
    "primary_smart_wallet_address": "0x9f8e7d6c5b4a39281726354091827364501928a7",
    "safe_creation_status": "completed"
  },
  "_links": {
    "self": { "href": "/v0/user/me" },
    "wallets": { "href": "/v0/wallets" },
    "kyc-status": { "href": "/v0/kyc/status" }
  }
}
On Sei testnet, Safe deployment typically completes in under 60 seconds. Poll on a 2–5 second interval and give up after ~3 minutes — any longer indicates an infra issue worth escalating.
6

Read balances

This is the working artefact. Query the new primary wallet’s assets and confirm the integration is live.
curl https://api.sumvin.com/v0/wallets/wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/assets \
  -H "x-juno-jwt: <your-jwt-token>" \
  -H "x-juno-orgid: <your-org-id>"
Using TanStack Query? See stale-while-revalidateuseWalletAssets caches for 5 minutes and refetches in the background, so balance reads stay snappy without hammering the endpoint.
Response: 200 OK
{
  "wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD78",
  "wallet_chain_id": 1329,
  "assets": [
    {
      "symbol": "ETH",
      "name": "Ether",
      "chain_id": 1329,
      "balance": "0.05423100",
      "balance_usd": "173.54",
      "balance_updated_at": 1740000010000,
      "transactions_href": "/v0/wallets/wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/assets/eth-1329/transactions",
      "_links": {
        "self": { "href": "/v0/wallets/wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/assets" }
      }
    }
  ],
  "total_assets": 1,
  "_links": {
    "self": { "href": "/v0/wallets/wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4/assets" },
    "wallet": { "href": "/v0/wallets/wal-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4" }
  }
}
Your partner user has a live, KYC-verified Sumvin account with a deployed Safe and a real balance. You are ready to enrol them in agentic flows.

What’s next

  1. Enrol in perpetual search — create an IPA and watch it transition through the agentic commerce lifecycle.
  2. Onboarding guide — full reference for every onboarding step and status.
  3. KYC guidewebsdk, hybrid, and document_only KYC modes in depth.
  4. Wallets guide — multi-chain wallet management and Safe deployment details.