API Reference
Download OpenAPI Spec
Authentication
The API accepts two types of Bearer tokens:
- JWT — Obtain one instantly by completing the Sign-In with Ethereum (SIWE) flow below (GET /nonce → POST /verify). JWTs are short-lived session tokens.
- API Key — Long-lived platform keys for server-to-server integrations. Contact us at support@clkd.xyz to request one.
Pass either token in the Authorization header — the server auto-detects the format.
Important: The address used for authentication must be the address derived from your private spending key (privateKeyToAccount(p_spend)), NOT your connected wallet address. The server identity is this derived auth address — your wallet address never touches the server.
Endpoints marked with 🔒 require a valid Bearer token.
Get HPKE public key
/.well-known/hpke-public-keyRetrieve the server's HPKE public key. Clients must encrypt stealth key material with this key before submitting it during account creation or signer enrollment.
200Default Response
{
"publicKey": "0x...",
"publicKeyBase64": "...",
"format": "hex",
"kem": "X25519-HKDF-SHA256",
"aead": "AES-128-GCM"
}Try it
curl -X GET \
"https://api-stg.clkd.xyz/.well-known/hpke-public-key"Validate invite code
/invite-codes/validateCheck whether an invite code is valid and unused, without consuming it. Public endpoint used during onboarding to give the user immediate feedback before they attempt account creation.
| Name | In | Type | Description |
|---|---|---|---|
code* | query | string | The invite code to validate |
200Default Response
{
"valid": true,
"reservedSubdomain": "string"
}Try it
codecurl -X GET \
"https://api-stg.clkd.xyz/invite-codes/validate"Get nonce
/nonceGenerate a one-time nonce tied to the given address. This is the first step of Sign-In with Ethereum (SIWE) — the nonce must be included in the SIWE message passed to verifySignin. Nonces expire after 5 minutes.
| Name | In | Type | Description |
|---|---|---|---|
address* | query | string | The auth address to tie the nonce to. This must be the address derived from your private spending key (i.e. `privateKeyToAccount(p_spend).address`), not your connected wallet address. |
200Random nonce string
"a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}429Default Response
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Maximum 20 requests per 1 minute."
}Try it
addresscurl -X GET \
"https://api-stg.clkd.xyz/nonce"Verify sign-in
/verifyComplete Sign-In with Ethereum by submitting the signed SIWE message. Returns a JWT session token and the associated accountId if the address already has a stealth account, or null if the user still needs to register.
200Default Response
{
"ok": true,
"address": "0x...",
"token": "string",
"accountId": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}422Default Response
{
"error": "Unprocessable Entity",
"message": "string",
"code": "UNPROCESSABLE_ENTITY"
}429Default Response
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Maximum 10 requests per 1 minute."
}Try it
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"message": "",
"signature": ""
}' \
"https://api-stg.clkd.xyz/verify"Logout
/logoutClear the server-side cache for the authenticated user. JWT tokens are stateless, so the client should also discard the token. Auth is optional — unauthenticated calls succeed without clearing any cache.
200Default Response
{
"ok": true
}Try it
curl -X POST \
"https://api-stg.clkd.xyz/logout"Account Management
Account creation, signers, subdomains, and setup
Check subdomain availability
/subdomain/checkCheck whether a subdomain name is available for registration. Public endpoint — no authentication required. Use before calling setSubdomain to avoid conflicts.
| Name | In | Type | Description |
|---|---|---|---|
name* | query | string | — |
200Default Response
{
"available": true
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}Try it
namecurl -X GET \
"https://api-stg.clkd.xyz/subdomain/check"Create account
/accounts/🔒Register a new stealth account by submitting HPKE-encrypted key material. The caller must already have a JWT from the SIWE sign-in flow, which proves ownership of the Ethereum address. The server decrypts and stores the stealth keys, enabling stealth address generation for this account. Requires an invite code when gated access is enabled. Returns the new accountId, or indicates if the address already has an account.
200Default Response
{
"accountId": "string",
"alreadyExisted": true
}Try it
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"ciphertext": "",
"encapsulatedKey": "",
"inviteCode": ""
}' \
"https://api-stg.clkd.xyz/accounts/"Get account
/accounts/{accountId}🔒Retrieve account metadata including the owner address, stealth material status, and ENS subdomain. Useful for determining onboarding state (e.g., whether the user still needs to claim a subdomain).
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"accountId": "string",
"address": "string",
"hasStealthMaterial": true,
"hasEnsName": true,
"subdomain": "string",
"lastConsumedNonce": 0
}Try it
accountIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}"List account signers
/accounts/{accountId}/signers🔒List every signer enrolled in the account, with their address and enrollment date. Use to display co-signers in a group account or to verify multi-device enrollment.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"signers": [
{
"signerId": "string",
"address": "string",
"enrolledAt": "string",
"ownerId": "string"
}
]
}Try it
accountIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/signers"Add account signer
/accounts/{accountId}/signers🔒Enroll an additional signer (device or co-owner) into a stealth account by submitting their stealth key material. Supports HPKE-encrypted or plaintext (dev-only) payloads. Used for multi-device access and group (multi-sig) accounts.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"signerId": "string"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"ciphertext": "",
"encapsulatedKey": "",
"ownerId": ""
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/signers"Get account config
/accounts/{accountId}/config🔒Retrieve the signer configuration history for the account, showing threshold and signer changes over time. Useful for auditing multi-sig setup changes.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"configs": [
{
"id": "string",
"version": 0,
"threshold": 0,
"signerIds": [
"string"
],
"status": "string",
"createdAt": "string",
"retiredAt": "string"
}
]
}Try it
accountIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/config"Set subdomain
/accounts/{accountId}/subdomain🔒Claim an ENS subdomain (e.g. alice.clkd.eth) for this account so senders can pay the user via a human-readable name instead of a raw address.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"success": true,
"message": "string",
"subdomain": "string"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"subdomain": ""
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/subdomain"Generate subdomain
/accounts/{accountId}/subdomain/generate🔒Generate a random available subdomain for the user to preview during onboarding. The name is not reserved — call setSubdomain to claim it.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"subdomain": "example-123.clkd.eth"
}Try it
accountIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/subdomain/generate"Recovery
Optional recovery hierarchy — orgs recover teams, teams recover accounts. Without a team, an account can only be recovered by its own signers.
Create team
/teams/Create a team whose multisig serves as the recovery signer for its member accounts. Accounts deployed with this team can be recovered by the team's signers if all device keys are lost. If no org is provided, a default one is auto-created.
201Default Response
{
"id": "string",
"name": "string",
"orgId": "string",
"externalId": "string",
"accounts": [
{
"accountId": "string",
"label": "string"
}
]
}Try it
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"name": "",
"orgId": "",
"externalId": "",
"accounts": [
{
"accountId": "",
"label": ""
}
]
}' \
"https://api-stg.clkd.xyz/teams/"Get team
/teams/{teamId}🔒Retrieve team details and its member accounts, including each account's threshold and signer count. Use to see which accounts this team can recover. Only accessible by team members.
| Name | In | Type | Description |
|---|---|---|---|
teamId* | path | string (uuid) | — |
200Default Response
{
"id": "string",
"name": "string",
"orgId": "string",
"externalId": "string",
"createdAt": "string",
"accounts": [
{
"accountId": "string",
"label": "string",
"threshold": 0,
"signerCount": 0
}
]
}Try it
teamIdcurl -X GET \
"https://api-stg.clkd.xyz/teams/{teamId}"Add team account
/teams/{teamId}/accounts🔒Add an existing stealth account to a team, making it recoverable by the team's multisig. The account must be redeployed with the team's recovery keys to take effect on-chain.
| Name | In | Type | Description |
|---|---|---|---|
teamId* | path | string (uuid) | — |
201Default Response
{
"teamId": "string",
"accountId": "string",
"label": "string"
}Try it
teamIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"accountId": "",
"label": ""
}' \
"https://api-stg.clkd.xyz/teams/{teamId}/accounts"Create org
/orgs/Create an organization whose multisig serves as the recovery signer for its teams. The org is the root of the recovery hierarchy.
201Default Response
{
"id": "string",
"name": "string",
"accountId": "string",
"externalId": "string"
}Try it
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"name": "",
"externalId": "",
"accountId": ""
}' \
"https://api-stg.clkd.xyz/orgs/"Get org
/orgs/{orgId}🔒Retrieve the organization and its full recovery tree — teams and their member accounts. Only accessible by accounts that belong to a team within the org.
| Name | In | Type | Description |
|---|---|---|---|
orgId* | path | string (uuid) | — |
200Default Response
{
"id": "string",
"name": "string",
"accountId": "string",
"externalId": "string",
"createdAt": "string",
"teams": [
{
"id": "string",
"name": "string",
"accountId": "string",
"externalId": "string",
"accounts": [
{
"accountId": "string",
"label": "string",
"threshold": 0,
"signerCount": 0
}
]
}
]
}Try it
orgIdcurl -X GET \
"https://api-stg.clkd.xyz/orgs/{orgId}"Receive
Payment address generation, receive pages, and ENS resolution
Get receive page
/u/{username}Serve the public payment page for a username. Generates a fresh stealth address on every visit and renders an HTML page with a QR code for receiving funds. Supports optional invoice query params (?amount=&token=&chain=) for pre-filled payment requests. Development only — production uses hostname routing (https://<username>.clkd.id).
| Name | In | Type | Description |
|---|---|---|---|
username* | path | string | Username/subdomain |
200HTML page with stealth address and QR code
"string"400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}404Default Response
{
"error": "Not found",
"message": "string"
}Try it
usernamecurl -X GET \
"https://api-stg.clkd.xyz/u/{username}"Create payment address
/accounts/{accountId}/payment-address🔒Derive a one-time stealth payment address so a sender can transfer tokens to this account without revealing the recipient on-chain.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"address": "string",
"chainId": 0,
"nonce": "string"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"memo": "",
"chainId": 0
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/payment-address"Resolve ENS
/ens/gateway/{sender}EIP-3668 (CCIP-Read) gateway that resolves Cloaked ENS subdomains. Called automatically by ENS clients — generates a fresh stealth address for addr() lookups and returns signed responses for text records, contenthash, and multicall batches.
| Name | In | Type | Description |
|---|---|---|---|
sender* | path | string | The address making the request (0x...) |
200Default Response
{
"data": "0x..."
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}429Default Response
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Maximum 200 requests per 5 minutes."
}503Default Response
{
"error": "Service Unavailable",
"message": "string"
}Try it
sendercurl -X POST \
-H "Content-Type: application/json" \
-d '{
"data": ""
}' \
"https://api-stg.clkd.xyz/ens/gateway/{sender}"Send
Quoting, submitting, and managing transactions
Get quote signer public key
/.well-known/quote-signer-public-keyRetrieve the server's P-256 ECDSA public key so clients can verify that quote responses were authentically signed by the server and haven't been tampered with.
200Default Response
{
"publicKey": "04...",
"format": "hex",
"curve": "P-256",
"algorithm": "ECDSA"
}Try it
curl -X GET \
"https://api-stg.clkd.xyz/.well-known/quote-signer-public-key"Create quote
/accounts/{accountId}/quote🔒Build a send quote that locks spendable UTXOs and returns signing data. Individual accounts receive intents and delegations for immediate client-side signing; group accounts receive a stored quoteId for multi-sig signature collection.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"intents": [
null
],
"delegations": [
null
],
"lockId": "string",
"expiresAt": "string",
"resolvedDestination": "string",
"selfSend": true,
"tokenPriceInEth": 0,
"priceValidUntil": "string",
"signature": "string",
"quoteId": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"chainId": 0,
"token": "",
"amount": "",
"decimals": 0,
"destinationAddress": "",
"ttl": 0
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/quote"List quotes
/accounts/{accountId}/quotes🔒List active (pending and submitted) quotes for the account so signers can see which transactions await their signature or have already been relayed.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"quotes": [
{
"quoteId": "string",
"status": "string",
"chainId": 0,
"token": "string",
"amount": "string",
"destinationAddress": "string",
"intentCount": 0,
"signatureCount": 0,
"threshold": 0,
"expiresAt": "string",
"txHash": "string",
"createdAt": "string"
}
]
}Try it
accountIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/quotes"Submit quote signatures
/accounts/{accountId}/quotes/{quoteId}/signatures🔒Submit one signer's EIP-712 signatures for a multi-sig quote. When enough signers have signed (threshold met), the transaction is automatically relayed on-chain.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | — |
quoteId* | path | string (uuid) | — |
200Default Response
{
"accepted": true,
"thresholdMet": true,
"signatureCount": 0,
"threshold": 0,
"txHash": "string"
}Try it
accountIdquoteIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"signerAddress": "",
"signatures": [
{
"intentIndex": 0,
"signature": ""
}
]
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/quotes/{quoteId}/signatures"Submit transaction
/accounts/{accountId}/submit🔒Submit client-signed intents and delegations from a quote to relay the transaction on-chain. Validates signatures, checks price slippage, and submits via the server relayer so the user pays no gas directly.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"success": true,
"txHash": "string",
"status": "string",
"message": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}404Default Response
{
"error": "Not found",
"message": "string"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"intents": [
null
],
"delegations": [
null
],
"lockId": "",
"tokenPriceInEth": 0,
"priceValidUntil": ""
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/submit"Unlock spendables
/accounts/{accountId}/unlock🔒Release the UTXO lock held by a quote so the funds become available for a new transaction. Use when the user cancels a send or the client decides not to submit.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"success": true,
"message": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}404Default Response
{
"error": "Not found",
"message": "string"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"lockId": ""
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/unlock"Get max sendable
/accounts/{accountId}/max-sendable🔒Calculate the maximum sendable amount for a token after deducting relay fees, so the UI can show a reliable "max" button without over-committing funds.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"maxSendable": "string",
"feeEstimate": "string",
"spendableCount": 0
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"chainId": 0,
"token": ""
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/max-sendable"Balance & Activity
Balance queries, transaction history, and supported tokens
List supported chains
/supported-chainsList every chain the platform supports, including explorer URLs, logo base names, and testnet/mainnet mapping. Use to populate chain pickers or build explorer links.
200Default Response
[
{
"name": "string",
"chainId": 0,
"isTestnet": true,
"explorerUrl": "string",
"explorerTxPath": "string",
"mainnetChainId": 0,
"logoBaseName": "string",
"isSquareLogo": true
}
]Try it
curl -X GET \
"https://api-stg.clkd.xyz/supported-chains"Get token catalog
/token-catalogReturn the full curated token list (Uniswap default list + native ETH + testnet extras), pinned symbols for the swap picker, and testnet-to-mainnet chain-ID mapping.
200Default Response
{
"tokens": [
{
"address": "string",
"symbol": "string",
"name": "string",
"decimals": 0,
"chainId": 0,
"logoURI": "string"
}
],
"pinnedSymbols": [
"string"
],
"testnetToMainnet": null
}Try it
curl -X GET \
"https://api-stg.clkd.xyz/token-catalog"Get balances
/accounts/{accountId}/balance🔒Retrieve token balances across every supported chain for this account, including available and pending amounts and USD values. Returns a totalUsdAmount summarizing all holdings.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"balances": [
{
"chainId": 8453,
"chainName": "Base",
"token": "0x...",
"tokenSymbol": "USDC",
"decimals": 6,
"logoUrl": "https://...",
"available": "1000000",
"pending": "500000",
"usdAmount": 1.5,
"spam": false
}
],
"totalUsdAmount": 1.5
}401Default Response
{
"error": "Unauthorized",
"message": "string",
"code": "UNAUTHORIZED"
}404Default Response
{
"error": "Not found",
"message": "string"
}429Default Response
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Maximum 60 requests per 1 minute."
}Try it
accountIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/balance"Get chain balances
/accounts/{accountId}/balance/{chainId}🔒Retrieve token balances filtered to a single chain. Same response shape as getBalances but scoped to the given chainId.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
chainId* | path | string | Chain ID (e.g., 8453 for Base) |
200Default Response
{
"balances": [
{
"chainId": 8453,
"chainName": "Base",
"token": "0x...",
"tokenSymbol": "USDC",
"decimals": 6,
"logoUrl": "https://...",
"available": "1000000",
"pending": "500000",
"usdAmount": 1.5,
"spam": false
}
],
"totalUsdAmount": 1.5
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}401Default Response
{
"error": "Unauthorized",
"message": "string",
"code": "UNAUTHORIZED"
}404Default Response
{
"error": "Not found",
"message": "string"
}429Default Response
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Maximum 60 requests per 1 minute."
}Try it
accountIdchainIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/balance/{chainId}"Get token balance
/accounts/{accountId}/balance/{chainId}/{token}🔒Retrieve the balance for a single token on a specific chain. Returns a zero-balance object if the token has never been received.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
chainId* | path | string | Chain ID |
token* | path | string | Token address (0x...) |
200Default Response
{
"chainId": 8453,
"chainName": "Base",
"token": "0x...",
"tokenSymbol": "USDC",
"decimals": 6,
"logoUrl": "https://...",
"available": "1000000",
"pending": "500000",
"usdAmount": 1.5,
"spam": false
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}401Default Response
{
"error": "Unauthorized",
"message": "string",
"code": "UNAUTHORIZED"
}404Default Response
{
"error": "Not found",
"message": "string"
}429Default Response
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Maximum 60 requests per 1 minute."
}Try it
accountIdchainIdtokencurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/balance/{chainId}/{token}"Get activities
/accounts/{accountId}/activities🔒List send, receive, and self-transfer transactions for the account with cursor-based pagination. Each activity includes transfer details, fees, USD amounts, and a failure flag.
| Name | In | Type | Description |
|---|---|---|---|
limit | query | string | Maximum number of activities to return (1-500, default: 100) |
cursor | query | string | Base64-encoded cursor for pagination |
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"activity": [
{
"txHash": "0x...",
"chainId": 8453,
"chainName": "Base",
"activityType": "string",
"date": "string",
"transfer": {
"tokenAddress": "0x...",
"decimals": 6,
"tokenSymbol": "USDC",
"logoUrl": "https://...",
"fromAddress": "0x...",
"toAddress": "0x...",
"value": "1000000",
"usdAmount": 1
},
"transferIn": {
"tokenAddress": "0x...",
"decimals": 6,
"tokenSymbol": "USDC",
"logoUrl": "string",
"fromAddress": "0x...",
"toAddress": "0x...",
"value": "1000000",
"usdAmount": 1
},
"fee": {
"tokenAddress": "0x...",
"decimals": 18,
"tokenSymbol": "ETH",
"logoUrl": "string",
"value": "1000000000000000",
"usdAmount": 0.001
},
"isFailure": false,
"isLikelySpam": false
}
],
"pagination": {
"limit": 100,
"nextCursor": "string"
}
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}401Default Response
{
"error": "Unauthorized",
"message": "string",
"code": "UNAUTHORIZED"
}404Default Response
{
"error": "Not found",
"message": "string"
}Try it
accountIdlimitcursorcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/activities"Swap
Get max swappable
/accounts/{accountId}/max-swappable🔒Calculate the maximum swappable amount for a token after deducting relay + swap fees, so the UI can show a reliable "max" button for swaps.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"maxSwappable": "string",
"feeEstimate": "string",
"spendableCount": 0
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"chainId": 0,
"token": ""
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/max-swappable"Create swap preview
/accounts/{accountId}/swap-preview🔒Get a swap preview (price discovery) without locking spendables.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"expectedOutput": "string",
"minimumOutput": "string",
"outputToken": "string",
"outputDecimals": 0,
"outputSymbol": "string",
"routing": "string",
"slippageBps": 0,
"feeEstimate": "string",
"estimatedFillTimeMs": 0,
"protocolFeeBps": 0,
"protocolFeeAmount": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}429Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}502Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}503Default Response
{
"error": "Service Unavailable",
"message": "string"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"chainId": 0,
"tokenIn": "",
"tokenOut": "",
"amountIn": "",
"slippageBps": 0,
"tokenOutChainId": 0
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/swap-preview"Create swap quote
/accounts/{accountId}/swap-quote🔒Get a swap quote via Uniswap. Returns intents and delegations for client signing.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"intents": [
null
],
"delegations": [
null
],
"lockId": "string",
"expiresAt": "string",
"expectedOutput": "string",
"minimumOutput": "string",
"outputToken": "string",
"outputDecimals": 0,
"outputSymbol": "string",
"outputRecipient": "string",
"slippageBps": 0,
"routing": "string",
"signature": "string",
"estimatedFillTimeMs": 0,
"fillDeadline": 0,
"protocolFeeBps": 0,
"protocolFeeAmount": "string",
"planId": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}429Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}502Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}503Default Response
{
"error": "Service Unavailable",
"message": "string"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"chainId": 0,
"tokenIn": "",
"tokenOut": "",
"amountIn": "",
"slippageBps": 0,
"tokenOutChainId": 0
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/swap-quote"Bridge
Get bridge status
/accounts/{accountId}/bridge-status🔒Get the status of a cross-chain bridge swap.
| Name | In | Type | Description |
|---|---|---|---|
txHash* | query | string | Source chain transaction hash |
chainId* | query | number | Source chain ID |
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"status": "string",
"swapType": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}502Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}503Default Response
{
"error": "Service Unavailable",
"message": "string"
}Try it
accountIdtxHashchainIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/bridge-status"Get bridge swaps
/accounts/{accountId}/bridge-swaps🔒List bridge swap records for the account.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
200Default Response
{
"bridgeSwaps": [
{
"id": "string",
"sourceTxHash": "string",
"sourceChainId": 0,
"sourceChainName": "string",
"sourceTokenAddress": "string",
"sourceTokenSymbol": "string",
"sourceDecimals": 0,
"sourceLogoUrl": "string",
"sourceAmount": "string",
"destChainId": 0,
"destChainName": "string",
"destTokenAddress": "string",
"destTokenSymbol": "string",
"destDecimals": 0,
"destLogoUrl": "string",
"destExpectedAmount": "string",
"outputRecipient": "string",
"estimatedFillTimeMs": 0,
"fillDeadline": 0,
"planId": "string",
"status": "string",
"destTxHash": "string",
"destActualAmount": "string",
"createdAt": "string",
"updatedAt": "string"
}
]
}401Default Response
{
"error": "Unauthorized",
"message": "string",
"code": "UNAUTHORIZED"
}Try it
accountIdcurl -X GET \
"https://api-stg.clkd.xyz/accounts/{accountId}/bridge-swaps"Create bridge swap
/accounts/{accountId}/bridge-swaps🔒Create a bridge swap tracking record for a cross-chain swap.
| Name | In | Type | Description |
|---|---|---|---|
accountId* | path | string (uuid) | Stealth account ID |
201Default Response
{
"id": "string"
}400Default Response
{
"error": "Bad request",
"message": "string",
"code": "BAD_REQUEST"
}401Default Response
{
"error": "Unauthorized",
"message": "string",
"code": "UNAUTHORIZED"
}Try it
accountIdcurl -X POST \
-H "Content-Type: application/json" \
-d '{
"sourceTxHash": "",
"sourceChainId": 0,
"sourceTokenAddress": "",
"sourceTokenSymbol": "",
"sourceDecimals": 0,
"sourceLogoUrl": "",
"sourceAmount": "",
"destChainId": 0,
"destTokenAddress": "",
"destTokenSymbol": "",
"destDecimals": 0,
"destLogoUrl": "",
"destExpectedAmount": "",
"outputRecipient": "",
"estimatedFillTimeMs": 0,
"fillDeadline": 0,
"planId": ""
}' \
"https://api-stg.clkd.xyz/accounts/{accountId}/bridge-swaps"
