Skip to main content
This guide covers the Socket Swap V3 endpoints:
  • GET /v3/swap/quote — fetch executable transaction routes, deposit-address routes, and CEX withdraw routes
  • GET /v3/swap/status — poll the status of a submitted route
  • GET /v3/swap/supported-chains — list supported chains
  • GET /v3/swap/tokens/list — list supported tokens
  • GET /v3/swap/tokens/search — search tokens by address, name, or symbol
Use the production base URL:
https://dedicated-backend.socket.tech
The examples below use the dedicated endpoint with x-api-key and affiliate headers. For testing without credentials, use https://public-backend.socket.tech. See Get API Access for the full breakdown.

Endpoint Selection

Use /v3/swap/quote with userOps=tx for OpenRouter direct routes, which support:
  • Same-chain swaps when originChainId === destinationChainId
  • Cross-chain bridge routes when originChainId !== destinationChainId
For deposit-address flows, use userOps=deposit. See the Deposit Addresses Guide.

Common Token and Amount Rules

  • inputAmount is a string in the smallest token unit for EVM-style chains.
  • The native token address is 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE.
  • EVM addresses are normalized to lowercase by the API.
  • receiverAddress must be valid for the destination chain.
  • userAddress is required for OpenRouter transaction routes.
  • Same-chain quotes reject identical inputToken and outputToken.

Step 1: Get a Quote

Request

GET /v3/swap/quote
Required query parameters:
ParameterTypeDescription
userOpsstringComma-separated route types. Use tx for OpenRouter transaction routes. Also supports deposit and cex-withdraw.
originChainIdstringRequired for tx and deposit. Source chain ID.
destinationChainIdstringDestination chain ID.
inputTokenstringSource token address.
inputAmountstringSource amount in smallest units.
outputTokenstringDestination token address.
receiverAddressstringDestination receiver address.
userAddressstringRequired for tx. Source wallet that will sign the transaction.
Optional query parameters:
ParameterTypeDescription
slippagenumber stringSlippage percent, for example 0.5.
feeBpsnumber stringIntegrator fee in basis points. Supports decimals. Requires feeTakerAddress.
feeTakerAddressstringFee recipient. Required when feeBps is set.
includeProviderstringComma-separated provider IDs to include.
excludeProviderstringComma-separated provider IDs to exclude. Cannot overlap with includeProvider.
refueltrue or falseOptional refuel request. Defaults to false.
destinationPayloadhex stringDestination payload. Requires destinationGasLimit.
destinationGasLimitstringGas limit for destinationPayload. Requires destinationPayload.
refundAddressstringRequired for deposit and cex-withdraw.
exchangestringRequired for cex-withdraw, for example coinbase or binance.

Same-chain DEX provider IDs

Provider IDDisplay name
bebopPmmBebop
kyberswapKyberswap
openoceanOpenOcean
zeroxv20x

Cross-chain bridge provider IDs

Provider IDDisplay name
staked-relayRelay
staked-acrossAcross
staked-gnosis-nativeGnosis Native
staked-polygon-nativePolygon Native
staked-native-op-stackOP Stack Native
cctp-v2Circle CCTP V2
cctp-v2-slowCircle CCTP V2 Slow
staked-celerCeler
staked-arbitrum-nativeArbitrum Native Bridge
staked-near-intentsNear Intents
staked-oftOFT
staked-mayanMayan
staked-scroll-nativeScroll Native

Example: Same-chain swap

curl -sS -G "https://dedicated-backend.socket.tech/v3/swap/quote" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "affiliate: YOUR_AFFILIATE_ID" \
  --data-urlencode "userOps=tx" \
  --data-urlencode "originChainId=42161" \
  --data-urlencode "destinationChainId=42161" \
  --data-urlencode "inputToken=0xaf88d065e77c8cC2239327C5EDb3A432268e5831" \
  --data-urlencode "outputToken=0x912ce59144191c1204e64559fe8253a0e49e6548" \
  --data-urlencode "inputAmount=10000000" \
  --data-urlencode "userAddress=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" \
  --data-urlencode "receiverAddress=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" \
  --data-urlencode "slippage=0.5" \
  --data-urlencode "includeProvider=zeroxv2,kyberswap"

Example: Cross-chain bridge

curl -sS -G "https://dedicated-backend.socket.tech/v3/swap/quote" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "affiliate: YOUR_AFFILIATE_ID" \
  --data-urlencode "userOps=tx" \
  --data-urlencode "originChainId=8453" \
  --data-urlencode "destinationChainId=42161" \
  --data-urlencode "inputToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" \
  --data-urlencode "outputToken=0xaf88d065e77c8cC2239327C5EDb3A432268e5831" \
  --data-urlencode "inputAmount=1000000" \
  --data-urlencode "userAddress=0x1111111111111111111111111111111111111111" \
  --data-urlencode "receiverAddress=0x1111111111111111111111111111111111111111" \
  --data-urlencode "slippage=1"

Quote response

{
  "success": true,
  "statusCode": 200,
  "result": {
    "originChainId": 42161,
    "destinationChainId": 10,
    "userAddress": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
    "receiverAddress": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
    "input": {
      "token": {
        "chainId": 42161,
        "address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
        "name": "USDC",
        "symbol": "USDC",
        "decimals": 6,
        "logoURI": "https://...",
        "icon": "https://..."
      },
      "amount": "10000000",
      "priceInUsd": 1,
      "valueInUsd": 10
    },
    "routes": [
      {
        "userOp": "tx",
        "quoteId": "0x...",
        "expiresAt": 1760000000,
        "output": {
          "token": {
            "chainId": 10,
            "address": "0x...",
            "name": "USDC",
            "symbol": "USDC",
            "decimals": 6,
            "logoURI": "https://...",
            "icon": "https://..."
          },
          "amount": "9855420",
          "minAmountOut": "9806142",
          "priceInUsd": 1,
          "valueInUsd": 9.85542
        },
        "estimatedTime": 60,
        "slippage": 0.5,
        "suggestedSlippage": 0.5,
        "routeTags": ["SUGGESTED", "MAX_OUTPUT"],
        "routeDetails": {
          "dexDetails": null,
          "bridgeDetails": {
            "protocol": {
              "name": "staked-across",
              "displayName": "Across",
              "icon": "https://media.socket.tech/bridges/across.png"
            },
            "inputTokenAddress": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
            "outputTokenAddress": "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
            "amountIn": "10000000",
            "amountOut": "9855420",
            "minAmountOut": "9806142",
            "slippage": 0.5
          },
          "feeDetails": null
        },
        "approval": {
          "spenderAddress": "0x...",
          "amount": "10000000",
          "tokenAddress": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
          "userAddress": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"
        },
        "txData": {
          "kind": "evm_tx",
          "object": {
            "chainId": 42161,
            "to": "0x...",
            "data": "0x...",
            "value": "0"
          }
        },
        "gasFee": {
          "gasToken": {
            "chainId": 42161,
            "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
            "name": "Ether",
            "symbol": "ETH",
            "decimals": 18,
            "logoURI": "https://...",
            "icon": "https://..."
          },
          "gasLimit": "650000",
          "gasPrice": "100000000",
          "estimatedFee": "65000000000000",
          "feeInUsd": 0.01
        },
        "statusCheck": {
          "endpoint": "https://public-backend.socket.tech/v3/swap/status?quoteId=0x...",
          "method": "GET",
          "intervalSec": 5,
          "maxDurationSec": 600
        }
      }
    ]
  },
  "message": null
}
Important route fields:
FieldDescription
quoteIdStable route ID. Use it for status polling. For OpenRouter tx routes this is the on-chain request hash.
expiresAtUnix timestamp after which the quote should be discarded.
output.amountExpected destination output amount after applicable fees.
output.minAmountOutMinimum acceptable destination output amount.
suggestedSlippageSuggested slippage percent returned by the API.
routeTagsRanking labels: SUGGESTED, FASTEST, MAX_OUTPUT.
routeDetails.bridgeDetailsBridge leg metadata, including provider ID, token addresses, amounts, and slippage.
routeDetails.dexDetailsSame-chain or origin-swap DEX leg metadata when present.
routeDetails.feeDetailsIntegrator fee metadata when a fee applies. Otherwise null.
approvalPresent for ERC20 inputs. Approve this spender before sending txData.
txData.kindTransaction type. OpenRouter EVM routes use evm_tx.
txData.objectTransaction payload to send from userAddress.
gasFee.gasTokenNative gas token metadata for the source chain.
statusCheckSuggested polling endpoint and cadence.

Step 2: Check Approval

If the approval field is present in the route response, approve the approval.spenderAddress for approval.amount of approval.tokenAddress before submitting the transaction.
OpenRouter EVM routes usually ask the user to approve the AllowanceHolder contract, not the final bridge or DEX. The to address in txData is typically the AllowanceHolder.

Step 3: Submit the Transaction

Submit txData.object as a transaction from userAddress.
// Example using ethers.js / viem
const tx = await signer.sendTransaction({
  to: route.txData.object.to,
  data: route.txData.object.data,
  value: BigInt(route.txData.object.value),
});
Do not rebuild calldata client-side. Always use the returned txData.object exactly as provided.

Step 4: Poll Status

Request

GET /v3/swap/status?quoteId=<quoteId>
ParameterRequiredDescription
quoteIdYesQuote ID returned by /v3/swap/quote.
includeQuoteDetailsNoSet to true to include stored quote row details in the response.
The v3 status endpoint looks up execution state by quoteId.

Status response

{
  "quoteId": "0x...",
  "userOp": "tx",
  "status": "IN_PROGRESS",
  "statusCode": "PENDING",
  "origin": {
    "chainId": 42161,
    "status": "COMPLETED",
    "txHash": "0x...",
    "userAddress": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"
  },
  "destination": {
    "chainId": 10,
    "status": "PENDING",
    "txHash": null,
    "receiverAddress": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"
  },
  "routeDetails": {
    "name": "Across",
    "logoURI": "https://media.socket.tech/bridges/across.png"
  },
  "refund": null
}
Status values:
StatusMeaning
PENDINGQuote or route has not started.
IN_PROGRESSSource transaction is known, destination completion is pending.
COMPLETEDRoute is complete.
FAILEDRoute failed.
EXPIREDQuote or execution window expired.
REFUNDEDFunds were refunded.

Full Execution Flow

  1. Request quotes from /v3/swap/quote with userOps=tx.
  2. Select a route. Prefer routeTags or compare output.valueInUsd, estimatedTime, and gasFee.
  3. Check quote freshness with expiresAt — do not send expired quotes.
  4. If approval is present, approve approval.spenderAddress for approval.amount.
  5. Submit the route transaction from userAddress using txData.object.
  6. Poll status with the returned quoteId.
  7. Poll until the route reaches a terminal status.

Fees

Integrator fees are set with feeBps and feeTakerAddress. Rules:
  • feeBps and feeTakerAddress must be provided together.
  • feeBps must be greater than 0 and at most 10000.
  • For direct DEX routes, fees can be taken from input or output depending on the OpenRouter fee resolution.
  • For direct bridge no-swap routes, fees are forced to the input side.
  • The client-facing output amount is already net of applicable fees.
See the Charging Fees Guide for detailed implementation steps.

Validation and Error Notes

Common 400 errors:
  • Missing userOps for /v3/swap/quote.
  • Missing originChainId for userOps=tx.
  • Missing userAddress for userOps=tx.
  • Missing refundAddress for userOps=deposit or userOps=cex-withdraw.
  • Missing exchange for userOps=cex-withdraw.
  • Invalid slippage.
  • Invalid or unsupported chain ID.
  • destinationPayload without destinationGasLimit, or the reverse.
  • feeBps without feeTakerAddress, or the reverse.
  • Provider listed in both include and exclude filters.
Quote responses can return an empty route list when providers fail to quote, the route is unsupported, or filters exclude all providers.

Implementation Notes

  • OpenRouter EVM routes usually ask the user to approve the AllowanceHolder contract, not the final bridge or DEX.
  • Use quoteId exactly as returned — it is used for status lookup and source transaction recording.
  • Do not rebuild calldata client-side. Use the returned txData.
  • For same-chain swaps, routeDetails.dexDetails is populated when route metadata is available.
  • For cross-chain routes, routeDetails.bridgeDetails describes the bridge leg. If there is an origin swap leg, routeDetails.dexDetails may also be present.

Charging Fees

Add integrator fees to your quotes

Deposit Addresses

Accept deposits from any chain

Destination Payload

Execute calldata on the destination chain

Chain Support

See all supported networks