API Integration
Build custom self-hosted verification flows with the REST API
The Wallet Verification Widget is the fastest way to go live, but you can also integrate directly via the API. Use the API when you want to build your own UI, support native mobile flows, or control each verification step from your backend.
Direct API integration follows the same pattern for every verification method:
- Create a wallet verification request.
- Submit proof of ownership for the selected flow.
- Read the updated status from the API or your webhook notification.
1. Create a Verification
Create the wallet verification before collecting proof from the wallet owner.
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"asset": "ETH",
"blockchain": "Ethereum",
"address": "0x32Be343B94f860124dC4fEe278FDCBD38C102D88",
"metadata": "customer-123",
"allowedFlows": ["SIGNATURE_PROOF", "VISUAL_PROOF", "SELF_DECLARED"],
"origin": "https://app.example.com"
}'
Mandatory fields:
asset: The virtual asset, for exampleETHorBTCblockchain: The blockchain name or supported EVM chain IDaddress: Self-hosted wallet address to verify
Optional fields:
metadata: Your own wallet, user, or case referenceallowedFlows: Restrict which proof methods can be usedorigin: Required when validating browser-origin-bound signature messagessatoshiFlow: Required when you allowSATOSHI_TEST; includedepositAddressand optionalamountreuse: Reusable verification matching input and policy
Example response:
{
"id": "9f3dc458-a2be-4a34-bcb7-f1f677a0864c",
"token": "97857f6c-396a-4d68-a1bf-563bfb76c5b6",
"url": "https://wallet-dev.cryptoswift.eu/?token=97857f6c-396a-4d68-a1bf-563bfb76c5b6",
"asset": "ETH",
"blockchain": "Ethereum",
"address": "0x32Be343B94f860124dC4fEe278FDCBD38C102D88",
"metadata": "customer-123",
"status": "PENDING",
"flow": null,
"allowedFlows": ["SIGNATURE_PROOF", "VISUAL_PROOF", "SELF_DECLARED"],
"reuse": null,
"createdAt": "2026-05-15T09:00:00.000Z"
}
Use id for all later status checks, proof submissions, manual updates, and webhook reconciliation.
Reusable Verification
Reusable verification can automatically complete a new verification by matching it with a previous eligible verified wallet verification for the same address and blockchain. Reuse matching is cross-tenant.
For a full explanation of matching policies, flow, and storage, see Reusable Wallet Verification.
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"asset": "ETH",
"blockchain": "Ethereum",
"address": "0x32Be343B94f860124dC4fEe278FDCBD38C102D88",
"allowedFlows": ["SIGNATURE_PROOF"],
"reuse": {
"subject": {
"type": "NATURAL",
"nameHash": "6f1c9d3d5c2f7b1e8a4f7c9b0d3a1e5f6c8b9a0d2e4f6a8b0c1d3e5f7a9b1c3"
},
"policy": {
"minimumMatchLevel": "MEDIUM",
"maxReuseAgeDays": 180
}
}
}'
nameHash is required for reusable verification. Hash the owner's full name after NFKC normalization, trimming, lowercasing, and collapsing repeated whitespace to one space. Send the lowercase 64-character SHA-256 hex digest, not the plain-text name.
Matching levels:
LOW: Address, blockchain, and subject type matchMEDIUM: Address, blockchain, and name hash matchHIGH: Address, blockchain, subject type, and name hash match
If a reusable match is found, the response has status: "VERIFIED" and reuse contains the applied match level, matched attributes, and policy. If no match is found, the response remains PENDING and you continue with proof submission.
2. Submit Proof of Ownership
Submit proof to the existing verification:
POST {{apiBaseUrl}}/wallet-verification/{id}/verification
The request body always includes verificationFlow. The rest of the payload depends on the selected flow.
Cryptographic Signature Proof
Cryptographic signature proofs verify that the user controls the wallet by signing an off-chain message with the wallet's private key.
CryptoSwift advocates open-source, industry-standard solutions for signature proofs. WalletConnect (now Reown) is the most robust option, with broad wallet compatibility. It supports 450+ wallets across networks like Bitcoin, Ethereum, Solana, Optimism, Arbitrum, Base, Polygon, BNB, Avalanche, and Cosmos. See the full list here.
Visit Reown or explore the Reown docs to get started. Also see the web-based Wallet Connect demo.
Once the user signs the message, submit the proof:
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification/9f3dc458-a2be-4a34-bcb7-f1f677a0864c/verification' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"verificationFlow": "SIGNATURE_PROOF",
"message": "app.example.com wants you to sign in with your blockchain account:\n0x32Be343B94f860124dC4fEe278FDCBD38C102D88\n\nURI:https://app.example.com/\nVersion: 1\nChain ID: eip155:1\nNonce: 1961\nIssued At: 2026-05-15T09:00:00Z",
"signature": "q7XUz9XJbWjK9YO2iA8eW3OmEDCuqKDG12tzmPVNlDb9X6G6MxwGqv8J8B4gEZq43vU3D9VaGRKqB1wnyCrR7A="
}'
Mandatory fields:
verificationFlow:SIGNATURE_PROOFmessage: The exact message signed by the wallet ownersignature: The cryptographic signature of the message
The request returns the updated verification. A successful signature proof sets status to VERIFIED.
Micro Transactions
A Satoshi Test verifies ownership by asking the wallet owner to send a specific amount of native asset from the self-hosted wallet to your deposit address.
Please ensure you set up a webhook before initiating a Satoshi Test verification.
Create the verification with SATOSHI_TEST allowed and provide satoshiFlow.depositAddress.
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"asset": "BTC",
"blockchain": "Bitcoin",
"address": "BsRdeZ75szhDiGN8hJs8v8PcqwBm7KsFcp",
"metadata": "customer-123",
"allowedFlows": ["SATOSHI_TEST"],
"satoshiFlow": {
"depositAddress": "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080"
}
}'
If satoshiFlow.amount is omitted, CryptoSwift generates a random amount. Share the returned satoshiFlow.depositAddress, asset, and satoshiFlow.amount with the wallet owner.
Then start transaction monitoring:
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification/9f3dc458-a2be-4a34-bcb7-f1f677a0864c/verification' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"verificationFlow": "SATOSHI_TEST"
}'
The verification stays PENDING until CryptoSwift detects a matching transaction. Satoshi Test verification expires 48 hours after createdAt.
Visual Proof
Visual Proof test let a user upload visual proof of wallet ownership for manual review.
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification/9f3dc458-a2be-4a34-bcb7-f1f677a0864c/verification' \ --header 'x-api-key: $API_KEY' \ --form 'verificationFlow="VISUAL_PROOF"' \ --form 'files=@"../wallet-screenshot.png"'
Mandatory fields:
verificationFlow:VISUAL_PROOFfiles: Up to 3 files
File limits:
- Images and PDFs:
jpeg,jpg,png, orpdf, max 5MB each - Videos:
mp4,webm,mov,avi,wmv,mkv,mpeg,m4v, or3gp, max 50MB each
Visual proof sets status to ACTION_REQUIRED. Review the uploaded proof and manually update the verification to VERIFIED or DECLINED.
Self-Declaration
Self-declaration lets the user declare wallet ownership without an on-chain transaction, screenshot, or signature.
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification/9f3dc458-a2be-4a34-bcb7-f1f677a0864c/verification' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"verificationFlow": "SELF_DECLARED"
}'
Self-declaration sets status to VERIFIED.
3. Receive Notification via Webhook
Webhook header: X-Event-Type: 'wallet-verification'
Example success payload:
{
"id": "9f3dc458-a2be-4a34-bcb7-f1f677a0864c",
"status": "VERIFIED",
"flow": "SIGNATURE_PROOF",
"verifiedTransactionHash": null
}
Use the webhook event as a trigger, then retrieve the current verification by ID before making compliance decisions.
curl --location 'https://api-dev.cryptoswift.eu/wallet-verification/9f3dc458-a2be-4a34-bcb7-f1f677a0864c' \ --header 'x-api-key: $API_KEY'
4. Manual Updates
For manual review flows, update the verification after your compliance team makes a decision.
curl --location --request PATCH 'https://api-dev.cryptoswift.eu/wallet-verification/9f3dc458-a2be-4a34-bcb7-f1f677a0864c' \
--header 'x-api-key: $API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"status": "VERIFIED",
"statusReasoning": "Manual approval",
"metadata": "case-456"
}'
Supported statuses:
PENDING: Verification has been created and is waiting for proof or completionVERIFIED: Ownership is verifiedACTION_REQUIRED: Manual VASP action is requiredDECLINED: Manual review rejected the proofFAILED: Automated verification failedDELETED: Verification was deleted