Onboarding API
Swarm's Onboarding API lets you embed KYC (Know Your Customer) identity verification and Source of Funds (SoF) checks directly into your own application. When a user passes verification, they receive an on-chain NFT permission token — the credential required to trade on Swarm's platform.
This is a RESTful APIs working with JSON payloads over HTTPS. All requests must include Content-Type: application/json.
Base URL: https://api.app.swarm.com
OpenAPI spec: docs.onboarding.swarm.com
Note: If you are looking to complete KYC as an end user rather than integrate the API, visit dotc.eth.limo to go through the KYC flow directly. The content below is for developers integrating the Onboarding API into their own applications.
Authentication
The Onboarding API uses Bearer token authentication (JWT).
Include your token in the Authorization header on every request:
Authorization: Bearer
Your source_key — a unique identifier assigned to your organisation by Swarm — is also required as a query parameter when initiating onboarding. Contact the Swarm team to obtain your source_key.
| Credential | How to provide it | How to obtain it |
|---|---|---|
| JWT token | Authorization: Bearer <token> header | Issued by your authentication flow |
| source_key | Query parameter | Assigned by Swarm — contact the team |
Onboarding flow
A typical integration follows this sequence:
- Initiate onboarding → GET /onboarding/external Pass the user's wallet address and your source_key Returns a kyc_sumsub_access_token for launching the KYC SDK
- Launch KYC Select in your UI Use the access token to open the Sumsub identity verification widget The user submits their identity documents
- Submit Source of Funds → POST /sof/verifications/external Your app collects SoF details via a form and submits them to the API
- Poll for status → GET /onboarding/external Call the same initiate endpoint to check kyc_passed and sof_passed
- User receives NFT permission token on-chain They can now trade on Swarm
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /onboarding/external | Initiate a new onboarding session, or check an existing one |
| POST | /sof/verifications/external | Submit Source of Funds information for a user |
Initiating KYC + SoF
Use GET /onboarding/external to start the onboarding process for a user. This endpoint serves a dual purpose: it initiates a new session when called for the first time, and returns the current verification status on subsequent calls.
Endpoint: GET https://api.app.swarm.com/onboarding/external
Authentication: BearerAuth (JWT) + source_key query parameter
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| address | string | ✅ | Wallet address of the user being onboarded |
| source_key | string | ✅ | Your organisation's unique source key, assigned by Swarm |
Example request
http GET https://api.app.swarm.com/onboarding/external?address=0xAbC123...&source_key=your-source-key Authorization: Bearer Content-Type: application/json
Response — 200 Success
json { "data": { "type": "external_onboarding_status", "attributes": { "status": "in_progress_user", "kyc_passed": false, "kyc_sumsub_access_token": "string", "sof_passed": false } } }
| Field | Type | Description |
|---|---|---|
| status | string | Overall onboarding status — see status values below |
| kyc_passed | boolean | Whether identity verification has been approved |
| kyc_sumsub_access_token | string | Short-lived token for launching the KYC widget in your UI |
| sof_passed | boolean | Whether Source of Funds verification has been approved |
Status values
| Value | Meaning |
|---|---|
| in_progress_user | Awaiting user action — use the kyc_sumsub_access_token to launch the KYC widget |
| in_progress_review | Documents submitted; under review by the Swarm compliance team |
| approved | KYC and SoF both passed; NFT permission token issued |
| rejected | Verification rejected — user should be informed |
Launching the KYC widget
When the response includes a kyc_sumsub_access_token, use it to launch the KYC Select widget (powered by Sumsub) in your application. This widget handles identity document collection, selfie capture, and liveness checks on your behalf.
javascript // Example: initialise Sumsub SDK with the access token const snsWebSdk = require('@sumsub/websdk');
snsWebSdk.init( accessToken, // kyc_sumsub_access_token from the API response () => fetchNewToken(), // token expiry handler — re-call GET /onboarding/external ) .withConf({ lang: 'en' }) .withOptions({ addViewportTag: false, adaptIframeHeight: true }) .on('idCheck.onStepCompleted', (payload) => { console.log('Step completed', payload); }) .on('idCheck.onApplicantSubmitted', () => { // User has submitted — poll GET /onboarding/external for status }) .build();
Refer to the Sumsub Web SDK documentation for full widget integration details.
Error responses
| Status | Description |
|---|---|
| 400 | Bad request — check that address and source_key are present and correctly formatted |
| 500 | Internal server error |
Submitting Source of Funds
Use POST /sof/verifications/external to submit Source of Funds and suitability information for a user. Your application should collect this data via a form and submit it once the user completes the KYC identity step.
Endpoint: POST https://api.app.swarm.com/sof/verifications/external
Authentication: BearerAuth (JWT)
Request body
json { "data": { "type": "sof_external_verification_form", "attributes": { "address": "string", "terms_accepted": true, "answers_sof": { "amount": 150000, "source_of_income": "Salary", "show_other_source": true, "other_source": "Heritage", "invest_knowledge": "Poor/none", "annual_income": "Under $200,000", "net_worth": "Under $500,000", "document_url": "https://sof-verifications.s3.eu-central-1.amazonaws.com/00896053-fa02-4856-8af8-8fae6e332e4b.csv" }, "answers_suitability": { "knowledge_stocks": "Yes", "knowledge_bonds": "Yes", "school_qualification": "Economic secondary", "held_positions": "Yes", "risk_comfortable": "Yes", "investment_goal": "Provision for old age", "support_issues": "Yes" } } } }
Field reference
Top-level attributes:
| Field | Type | Required | Description |
|---|---|---|---|
| address | string | ✅ | User's wallet address |
| terms_accepted | boolean | ✅ | User has accepted the terms and conditions |
| answers_sof | object | ✅ | Source of Funds answers |
| answers_suitability | object | ✅ | Suitability assessment answers |
answers_sof fields:
| Field | Type | Description |
|---|---|---|
| amount | number | Intended investment amount in USD |
| source_of_income | string | Primary source of income (e.g. "Salary", "Business income", "Investments") |
| show_other_source | boolean | Whether an additional income source applies |
| other_source | string | Description of the additional income source (if show_other_source is true) |
| invest_knowledge | string | Self-reported investment knowledge level (e.g. "Poor/none", "Basic", "Good", "Expert") |
| annual_income | string | Annual income bracket (e.g. "Under $200,000", "$200,000–$500,000", "Over $500,000") |
| net_worth | string | Net worth bracket (e.g. "Under $500,000", "$500,000–$1,000,000", "Over $1,000,000") |
| document_url | string | URL to a supporting document uploaded to S3 (if required) |
answers_suitability fields:
| Field | Type | Description |
|---|---|---|
| knowledge_stocks | string | Has knowledge of stocks ("Yes" / "No") |
| knowledge_bonds | string | Has knowledge of bonds ("Yes" / "No") |
| school_qualification | string | Highest educational qualification (e.g. "Economic secondary", "University") |
| held_positions | string | Has held relevant professional positions ("Yes" / "No") |
| risk_comfortable | string | Comfortable with investment risk ("Yes" / "No") |
| investment_goal | string | Primary investment objective (e.g. "Provision for old age", "Capital growth", "Income") |
| support_issues | string | Has received investment support or advice ("Yes" / "No") |
Responses
| Status | Description |
|---|---|
| 204 | Created — SoF information received and submitted for verification |
| 401 | Unauthorised — JWT token is invalid or expired |
| 403 | Forbidden — source_key is not authorised for this operation |
| 409 | Conflict — a SoF submission already exists for this address |
| 500 | Internal server error |
Error response body (4xx/5xx)
json { "errors": [ { "title": "Unauthorized", "detail": "Session token is invalid. It either has expired or is corrupted. Please log in and obtain a new one.", "status": 401, "code": "session_token_not_found" } ] }
When to call this endpoint
Submit SoF information after the user has completed the KYC identity step in the Sumsub widget. The recommended flow is:
- Listen for the
idCheck.onApplicantSubmittedevent from the Sumsub widget - Present your Source of Funds form to the user
- On form submission, call
POST /sof/verifications/external - On
204, proceed to polling for status
If the SoF information is incomplete or fails validation, the endpoint returns the current status as in_progress_user and the user receives an email prompting them to resubmit. See Resubmitting Documents below.
Checking Verification Status
Use GET /onboarding/external — the same endpoint used to initiate onboarding — to check the current status of a user's KYC and SoF verification.
Endpoint: GET https://api.app.swarm.com/onboarding/external
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| address | string | ✅ | Wallet address of the user |
| source_key | string | ✅ | Your organisation's source key |
Polling approach
The API does not push status updates — your application needs to poll. Call GET /onboarding/external at a reasonable interval (e.g. every 30–60 seconds) while the user's application is under review.
javascript async function pollOnboardingStatus(address, sourceKey, bearerToken) { const response = await fetch( https://api.app.swarm.com/onboarding/external?address=${address}&source_key=${sourceKey}, { headers: { 'Authorization': Bearer ${bearerToken}, 'Content-Type': 'application/json' } } );
const { data } = await response.json(); const { status, kyc_passed, sof_passed } = data.attributes;
if (kyc_passed && sof_passed) { // User is fully verified — proceed return 'approved'; }
return status; }
Reading the response
| Scenario | kyc_passed | sof_passed | status | Recommended action |
|---|---|---|---|---|
| Just initiated | false | false | in_progress_user | Launch KYC widget using kyc_sumsub_access_token |
| KYC submitted, SoF pending | false | false | in_progress_user | Present SoF form |
| Both submitted, under review | false | false | in_progress_review | Show "under review" state in your UI |
| KYC passed, SoF pending | true | false | in_progress_user | Present SoF form if not yet submitted |
| Fully approved | true | true | approved | NFT token issued — user can trade |
| Rejected | — | — | rejected | Inform the user; contact Swarm support |
NFT permission token
When status is approved, Swarm automatically issues an on-chain NFT permission token to the user's wallet address. This token is the on-chain credential that gates access to trading on Swarm's platform. You do not need to take any action to trigger this — it is issued automatically upon approval.
Resubmitting Documents
If a user's KYC documents or Source of Funds information are incomplete or do not meet Swarm's regulatory requirements, they will be asked to resubmit. The flow differs slightly between KYC and SoF resubmissions.
KYC resubmission
If the identity documents provided are incomplete or rejected, the user receives an email with a link to resubmit. That link returns a new kyc_sumsub_access_token to your application.
Your application should:
- Detect that
kyc_passedis stillfalseafter the user has previously submitted - Call
GET /onboarding/externalto obtain a freshkyc_sumsub_access_token - Re-launch the KYC Select widget using the new token — the user will be taken directly to the step requiring resubmission
The Sumsub widget handles the resubmission UI internally. You only need to re-initialise it with the updated token.
javascript // Re-launch the widget on resubmission const { kyc_sumsub_access_token } = await getOnboardingStatus(address, sourceKey);
if (!kyc_passed && kyc_sumsub_access_token) { launchKYCWidget(kyc_sumsub_access_token); }
Source of Funds resubmission
If the SoF information submitted is incomplete, the POST /sof/verifications/external endpoint returns a status of in_progress_user and the user receives an email notification.
Your application should:
- Detect
sof_passed: falsealongsidestatus: "in_progress_user"after a prior SoF submission - Present the Source of Funds form to the user again
- Allow them to correct or complete their answers
- Resubmit to
POST /sof/verifications/external
Note that a 409 Conflict response indicates a SoF submission already exists for this address. If you receive a 409 during what should be a resubmission, check whether the user's status is in_progress_review — their first submission may still be under review and a resubmission is not yet needed.
Distinguishing resubmission from first submission
There is no separate resubmission endpoint. The same endpoints are used throughout the lifecycle:
| Action | Endpoint |
|---|---|
| Initiate / check status / get fresh KYC token | GET /onboarding/external |
| Submit or resubmit SoF | POST /sof/verifications/external |
The context for whether a call is a first submission or a resubmission is determined by the current status and kyc_passed / sof_passed values in the status response.
.png)