Sharing Data Through SumSub

Share existing SumSub verification with Wirex for pre-verified users.

Before You Start

Read the following guides before proceeding:

GuideWhy
Getting StartedPlatform overview and setup
Api BasicsRequired headers and request configuration
AuthenticationHow to obtain access tokens
WebhooksReceive status notifications
OnboardingUser and wallet registration
User ProfileUser capabilities and status

When to Use

  • Your users are already KYC-verified via SumSub
  • You want to avoid duplicate verification for your users
  • You have a data sharing agreement with Wirex and SumSub

Approval Required: This flow is only available after a detailed audit by Wirex and may be rejected. Contact your Wirex account manager to discuss eligibility and requirements.


Setup Requirements

Before using this flow, you must complete a one-time setup:

  1. Sign agreement - Contact your Wirex account manager to sign a 3-sided data sharing agreement between your company, Wirex, and SumSub

  2. Configure SumSub - Ensure your SumSub integration can generate share tokens for external clients


Generating a Share Token

Use the SumSub API to generate a share token for each user:

The share token allows Wirex to access the user's verification data from SumSub.


Request

POST /api/v2/user
{
  "wallet_address": "0xA7E41d5680dE394EaA2ed417169DFf56840Fb3EE",
  "sharing_data": {
    "sharing_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "email": "[email protected]"
  }
}

Field Requirements

Important: The wallet_address must be the user's EOA address (the signer), not the Smart Wallet address.

FieldTypeRequiredValidation
wallet_addressstringYesUser's EOA address
sharing_data.sharing_tokenstringYesValid SumSub share token for wirexapp.com_51921
sharing_data.emailstringYesValid email format, must be unique

Phone Number: The phone number from the user's SumSub verification is automatically marked as confirmed. It will be used for 3DS Authentication OTP codes and Read Card Details OTP verification. No separate confirmation step is required.


Code Examples

async function registerUserSharedKYC(accessToken, walletAddress, sharingToken, email, chainId, baseUrl) {
  const response = await fetch(`${baseUrl}/api/v2/user`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      'X-Chain-Id': chainId.toString(),
    },
    body: JSON.stringify({
      wallet_address: walletAddress,
      sharing_data: { sharing_token: sharingToken, email },
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Registration failed: ${error.error_description}`);
  }
  return response.json();
}

// Usage
const sharingToken = await generateSumSubShareToken(userId, 'wirexapp.com_51921');
const { id } = await registerUserSharedKYC(
  access_token,
  '0xA7E41d5680dE394EaA2ed417169DFf56840Fb3EE',
  sharingToken,
  '[email protected]',
  8453,
  'https://api-baas.wirexapp.com'
);
import requests

def register_user_shared_kyc(access_token, wallet_address, sharing_token, email, chain_id, base_url):
    response = requests.post(
        f"{base_url}/api/v2/user",
        headers={
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json",
            "X-Chain-Id": str(chain_id),
        },
        json={
            "wallet_address": wallet_address,
            "sharing_data": {"sharing_token": sharing_token, "email": email},
        },
    )
    response.raise_for_status()
    return response.json()

# Usage
sharing_token = generate_sumsub_share_token(user_id, "wirexapp.com_51921")
user = register_user_shared_kyc(
    access_token,
    "0xA7E41d5680dE394EaA2ed417169DFf56840Fb3EE",
    sharing_token,
    "[email protected]",
    8453,
    "https://api-baas.wirexapp.com"
)
func RegisterUserSharedKYC(accessToken, walletAddress, sharingToken, email string, chainID int, baseURL string) (string, error) {
    reqBody, _ := json.Marshal(map[string]interface{}{
        "wallet_address": walletAddress,
        "sharing_data":   map[string]string{"sharing_token": sharingToken, "email": email},
    })

    req, _ := http.NewRequest("POST", baseURL+"/api/v2/user", bytes.NewBuffer(reqBody))
    req.Header.Set("Authorization", "Bearer "+accessToken)
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-Chain-Id", fmt.Sprintf("%d", chainID))

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    var result struct{ ID string `json:"id"` }
    json.NewDecoder(resp.Body).Decode(&result)
    return result.ID, nil
}

Flow

sequenceDiagram
    participant Backend as Your Backend
    participant SumSub as SumSub API
    participant BaaS as Wirex API

    Backend->>SumSub: 1. Generate share token for wirexapp.com_51921
    SumSub-->>Backend: { sharing_token }

    Backend->>BaaS: 2. POST /api/v2/user { wallet_address, sharing_data }

    BaaS->>SumSub: 3. Fetch verification
    SumSub-->>BaaS: { user_data }

    Note over BaaS: 4. Validate & create account

    BaaS-->>Backend: { id }

    BaaS->>Backend: 5. POST /webhook/users (verification_status)

Webhooks

Wirex sends webhook notifications when verification status changes.

Note: This is a legacy webhook format that will be replaced with a v2 model in a future release.

Endpoint: POST {your_webhook_base_url}/webhook/users

You will receive status updates as verification progresses:

  • Applied → data received from SumSub, validation in progress
  • Approved → verification complete, user is active
  • Rejected → verification failed, contact Wirex support

See Webhooks for payload details.


What Happens Next

After registration with a valid share token:

  1. Wirex retrieves the user's verification data from SumSub using the share token
  2. Wirex validates the verification meets requirements
  3. Webhook notification sent with verification_status updates
  4. User account is activated upon approval

The user can perform all operations once verification is approved.


Error Handling

Validation Errors

FieldErrorPattern/Requirement
wallet_addressInvalid format^0x[a-fA-F0-9]{40}$ (EVM)
sharing_data.emailInvalid formatValid email address
sharing_data.emailMissingRequired field
sharing_data.sharing_tokenMissingRequired field
Mutual exclusivitysharing_data and initial_data cannot both be provided

Registration Errors

Error ReasonDescriptionResolution
ErrorNotFoundWallet not registered in Accounts contractComplete on-chain registration first
ErrorAlreadyExistsEmail already existsUse a different email address
ErrorAlreadyExistsWallet address already existsUser already registered

Share Token Errors

ErrorCauseResolution
Invalid sharing tokenToken expired or malformedGenerate a new token
Share token rejectedTarget client ID mismatchEnsure token is generated for wirexapp.com_51921
Verification not foundUser not verified in SumSubComplete user verification first
Agreement not activeData sharing agreement missingContact Wirex account manager

Error Response Format

{
  "error_reason": "ErrorInvalidField",
  "error_description": "Invalid sharing token",
  "error_category": {
    "category": "CategoryValidationFailure",
    "http_status_code": 400
  },
  "error_details": [
    { "key": "field", "details": "sharing_token" },
    { "key": "issue", "details": "invalid_format" }
  ]
}