Skip to main content

Widget Integration

Use the V2 widget when you want SWAPS inside a marketplace page without building the full trade UI yourself. The widget mounts from a script tag, reads signed user context from data-* attributes, syncs wallet inventory, shows available swaps and For You recommendations, prepares wallet approval transactions, reports wallet broadcasts, and surfaces claimable unused-fee refunds in Activity.

Script Tag

<script
src="https://www.swapsapi.com/widget/widget.js"
data-api-key="pk_live_your_publishable_key"
data-user-id="HaGvQgaU8NyjyDc7BFu47aZQYjRCTLGqeQeCNP9SSdiN"
data-user-signature="hmac_hex"
data-user-timestamp="1710590400"
data-inventory='["GM4zYgkVopM4VPW4mMgbuNn5eVsGyRNVZjJMhFdakh2N"]'
data-blockchain="solana"
data-theme="dark"
data-layout="overlay"
></script>

Set data-blockchain explicitly. The current loader accepts ethereum, base, or solana; if omitted, the code falls back to solana. The example above is the Solana card-marketplace shape. Ethereum and Base marketplaces use EVM wallets and token IDs with data-blockchain="ethereum" or data-blockchain="base"; Base approval switches the wallet to the server-provided Base chain ID before signing. Any other explicit value prevents the widget from mounting instead of selecting the wrong wallet family.

Attributes

AttributeRequiredSourceNotes
data-api-keyYesDashboardUse a publishable key (pk_live_) for browser/widget installs.
data-user-idYesPartner appUse the wallet address that owns the embedded inventory.
data-user-signatureYesPartner backendHex HMAC-SHA256 signature over swaps-user:{userId}:{timestamp}.
data-user-timestampYesPartner backendUnix-second timestamp. Signatures expire after 24 hours and tolerate 5 minutes of future clock skew.
data-inventoryRecommendedPartner appJSON string array of NFT IDs. Invalid JSON or non-string entries are ignored.
data-blockchainRecommendedPartner appethereum, base, or solana; set explicitly to avoid default-chain surprises.
data-themeOptionalPartner appdark or light; defaults to light.
data-layoutOptionalPartner appoverlay or push; defaults to overlay.
data-base-urlOptionalPartner appDefaults to https://www.swapsapi.com; mainly useful for sandbox or local testing.

Backend Signing Endpoint

Generate the signature on your backend. Never send the HMAC secret to the browser.

import crypto from 'crypto';

export function signSwapsWidgetUser(userId: string, hmacSecret: string) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = crypto
.createHmac('sha256', hmacSecret)
.update(`swaps-user:${userId}:${timestamp}`, 'utf8')
.digest('hex');

return { userId, signature, timestamp };
}

The widget sends these headers on publishable-key requests:

X-Swaps-User-Id: <userId>
X-Swaps-User-Signature: <hmac_signature>
X-Swaps-User-Timestamp: <unix_timestamp>

Auth Refresh

Listen for signature expiry and refresh only the signature and timestamp. Keep data-user-id stable for the wallet session.

window.Swaps?.on('swaps:auth_expired', async () => {
const response = await fetch('/api/swaps-widget-signature');
const { signature, timestamp } = await response.json();
window.Swaps.refreshAuth(signature, timestamp);
});

Widget API

After the widget mounts, it exposes window.Swaps.

await window.Swaps.want('0x3333333333333333333333333333333333333333:5');
await window.Swaps.unwant('0x3333333333333333333333333333333333333333:5');
await window.Swaps.setInventory([
'0x3333333333333333333333333333333333333333:1',
'0x3333333333333333333333333333333333333333:2'
]);
await window.Swaps.track('card_viewed', {
nftId: '0x3333333333333333333333333333333333333333:5',
surface: 'marketplace'
});
window.Swaps.open();
window.Swaps.close();

want, unwant, setInventory, and track return promises. open and close update panel state.

For publishable-key widget calls, SWAPS ignores a mismatched route or body wallet and uses the HMAC-verified data-user-id as the authoritative wallet identity.

Live V2 Calls

The widget uses the current V2 endpoints:

  • POST /api/v2/inventory/update
  • POST /api/v2/wants
  • GET /api/v2/wants/{walletAddress}
  • DELETE /api/v2/wants/{wantId}
  • GET /api/v2/swaps/{walletAddress}
  • GET /api/v2/explore/{walletAddress}
  • GET /api/v2/delegations/refunds/{walletAddress}
  • POST /api/v2/preference-events
  • POST /api/v2/swaps/{swapId}/accept
  • POST /api/v2/swaps/{swapId}/pass
  • POST /api/v2/blockchain/trades/broadcast
  • GET /api/v2/trending

Common Failures

SymptomLikely CauseFix
Missing required headersOne of the signed user headers is absent.Return userId, signature, and timestamp together from your signing endpoint.
Signature expiredTimestamp is older than 24 hours, malformed, or too far in the future.Generate Unix-second timestamps server-side and refresh with Swaps.refreshAuth.
Invalid user signatureHMAC secret, user ID, timestamp, or message format does not match.Sign exactly swaps-user:{userId}:{timestamp} with hex HMAC-SHA256.
Empty inventory after mountdata-inventory is invalid JSON or contains non-string IDs.Pass a JSON string array of NFT IDs.
Wrong chain behaviordata-blockchain omitted or mismatched.Set data-blockchain="ethereum", data-blockchain="base", or data-blockchain="solana" explicitly. Unsupported explicit values do not mount.