GET /api/embed/tracking/{id}
Returns the public payload for a tracking page. This is the same data the iframe widget renders; use it to build a custom UI.
Request
GET /api/embed/tracking/{trackingPageId} HTTP/1.1
Host: walletsleuth.app
Authorization: Bearer ws_pub_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Origin: https://example.com
Path parameters
| Name | Type | Description |
|---|---|---|
trackingPageId | string | The tracking page ID. Visible in the Wallet Sleuth dashboard URL. |
Headers
| Header | Required | Notes |
|---|---|---|
Authorization | yes | Bearer <api_key>. Public or secret tier accepted. |
Origin | yes for public keys | Must be on the key's allowlist (unless allowNullOrigin is set). |
Query parameters
None.
Body
None — this is a GET.
Success response
200 OK, JSON body:
{
"tokenName": "Solana",
"tokenSymbol": "SOL",
"tokenMint": "So11111111111111111111111111111111111111112",
"publicTitle": "Team + early holders",
"publicComments": "Updated every few minutes.",
"wallets": [
{
"id": "wallet-doc-id",
"address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
"publicAlias": "Core dev",
"tokenBalance": 125000,
"tags": [
{ "id": "tag-1", "name": "Team member", "color": "purple" }
]
}
],
"tags": [
{ "id": "tag-1", "name": "Team member", "color": "purple" },
{ "id": "tag-2", "name": "Bad actor", "color": "red" }
]
}
Response fields
| Field | Type | Notes |
|---|---|---|
tokenName | string | From the tracking page's token metadata. |
tokenSymbol | string | Ticker. Displayed with $ prefix in the widget. |
tokenMint | string | Base58 mint address of the tracked token. |
publicTitle | string | null | Secondary header set by the owner. Null if unset. |
publicComments | string | null | Short blurb set by the owner. Null if unset. |
wallets | array | Every tracked wallet not marked hideFromPublic. |
wallets[].id | string | Wallet document ID — stable across calls. |
wallets[].address | string | Base58 Solana address. |
wallets[].publicAlias | string | null | Owner-configured display name. Null if unset. |
wallets[].tokenBalance | number | Raw token balance (not USD). Zero if never observed. |
wallets[].tags | array | Tag objects applied to the wallet. Subset of top-level tags. |
tags | array | All tags defined on the tracking page. Wallet tag arrays are subsets of this. |
tags[].id | string | Tag document ID. |
tags[].name | string | Owner-configured display name. |
tags[].color | string | Color token name (e.g. "purple", "red"). |
The list is already filtered: wallets with hideFromPublic: true on their public settings doc are never returned.
Error responses
All errors follow the shape { "error": "<code>" }. HTTP status and code combinations:
| Status | error | Meaning |
|---|---|---|
| 401 | missing_key | No Authorization: Bearer … header. |
| 401 | invalid_key | Key prefix is wrong, key doesn't exist, or key belongs to a different page. |
| 401 | revoked_key | Key has been revoked. |
| 401 | missing_origin | Public-key request had no Origin or Referer header. |
| 403 | origin_not_allowed | Origin isn't on the key's allowlist. |
| 403 | embed_disabled | Tracking page is private or has embedding disabled. |
| 404 | not_found | Tracking page doesn't exist, or its data can't be built. |
| 429 | rate_limit_key | Per-key rate limit exceeded. Retry-After included. |
| 429 | rate_limit_ip | Per-IP rate limit exceeded. Retry-After included. |
For the complete table across every endpoint, see Errors and status codes.
Preflight (OPTIONS)
Browsers will issue a preflight OPTIONS request before cross-origin GETs with custom headers. The server responds 204 No Content with:
Access-Control-Allow-Origin: <your origin>
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 600
Vary: Origin
Preflight runs a lightweight version of the origin check: if any public, non-revoked key for the tracking page has your origin allowlisted, preflight succeeds. The actual GET then does the full check against the specific key you presented.
Caching
The server does not set Cache-Control. Don't cache this response in shared caches — the wallet list changes as owners add and remove wallets, and tokenBalance changes as transactions land. The global per-key and per-IP rate limits are generous enough for polling at roughly 1 req/s if you need near-live updates.
Example (cURL)
curl -s https://walletsleuth.app/api/embed/tracking/abc123 \
-H 'Authorization: Bearer ws_pub_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
-H 'Origin: https://example.com'
Example (fetch)
const res = await fetch(
`https://walletsleuth.app/api/embed/tracking/${pageId}`,
{
headers: {
Authorization: `Bearer ${publicKey}`,
},
credentials: 'include',
},
);
if (!res.ok) {
const { error } = await res.json();
throw new Error(error);
}
const payload = await res.json();
Browsers set Origin automatically. credentials: 'include' is needed only if you also want the embed session cookie to be sent (required for GET /session/submissions).
Related
- POST /siws/nonce — start a wallet submission.
- POST /submissions — finish a wallet submission.
- Customization — owner-configurable fields.