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
| Attribute | Required | Source | Notes |
|---|---|---|---|
data-api-key | Yes | Dashboard | Use a publishable key (pk_live_) for browser/widget installs. |
data-user-id | Yes | Partner app | Use the wallet address that owns the embedded inventory. |
data-user-signature | Yes | Partner backend | Hex HMAC-SHA256 signature over swaps-user:{userId}:{timestamp}. |
data-user-timestamp | Yes | Partner backend | Unix-second timestamp. Signatures expire after 24 hours and tolerate 5 minutes of future clock skew. |
data-inventory | Recommended | Partner app | JSON string array of NFT IDs. Invalid JSON or non-string entries are ignored. |
data-blockchain | Recommended | Partner app | ethereum, base, or solana; set explicitly to avoid default-chain surprises. |
data-theme | Optional | Partner app | dark or light; defaults to light. |
data-layout | Optional | Partner app | overlay or push; defaults to overlay. |
data-base-url | Optional | Partner app | Defaults 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/updatePOST /api/v2/wantsGET /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-eventsPOST /api/v2/swaps/{swapId}/acceptPOST /api/v2/swaps/{swapId}/passPOST /api/v2/blockchain/trades/broadcastGET /api/v2/trending
Common Failures
| Symptom | Likely Cause | Fix |
|---|---|---|
Missing required headers | One of the signed user headers is absent. | Return userId, signature, and timestamp together from your signing endpoint. |
Signature expired | Timestamp 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 signature | HMAC secret, user ID, timestamp, or message format does not match. | Sign exactly swaps-user:{userId}:{timestamp} with hex HMAC-SHA256. |
| Empty inventory after mount | data-inventory is invalid JSON or contains non-string IDs. | Pass a JSON string array of NFT IDs. |
| Wrong chain behavior | data-blockchain omitted or mismatched. | Set data-blockchain="ethereum", data-blockchain="base", or data-blockchain="solana" explicitly. Unsupported explicit values do not mount. |