Users API#
The Users API provides developer-facing endpoints for discovering users and viewing live presence. All developer API requests require an Azure API Management (APIM) subscription key. The APIM custom domain is the primary client endpoint; Azure Front Door (AFD) can be configured as an optional/fallback edge.
- Base URL: markup
https://api.pay.ledger1.ai/portalpay - Authentication (Developer APIs): APIM subscription key in header
- markup
Ocp-Apim-Subscription-Key: {your-subscription-key}
- Gateway posture: APIM custom domain is primary. If AFD is enabled, APIM accepts an internal markupheader per policy.
x-edge-secret - Rate limit headers (if enabled): markup,
X-RateLimit-Limitmarkup,X-RateLimit-RemainingmarkupX-RateLimit-Reset
GET /portalpay/api/users/search#
Search users by wallet/displayName text, XP range, and dynamic metrics (domains, platforms, languages).
Query parameters:
- markup(string, optional): case-insensitive text search across wallet and displayName
q - markup(string, optional): comma-separated list; user must have all of these domains in metrics
domains - markup(string, optional): comma-separated list; user must have all of these platforms in metrics
platforms - markup(string, optional): comma-separated list; user must have all of these languages in metrics
languages - markup(number, optional): minimum XP (>= 0)
minXp - markup(number, optional): maximum XP (>= 0)
maxXp - markup(boolean, optional): if
livemarkup, only returns users currently live and withtruemarkupspacePublic = true - markup(number, optional): number of results to return; clamped to [1, 100], default 25
limit - markup(number, optional): max items scanned server-side before filtering; clamped to [limit, 1000], default 400
scan
Headers:
markupOcp-Apim-Subscription-Key: {your-subscription-key}
Example requests
curl -X GET "https://api.pay.ledger1.ai/portalpay/api/users/search?q=alice&minXp=100&domains=gaming,defi&limit=25" \
-H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY"GET/portalpay/api/users/searchTry It: Users Search
Search users with filters.
Default is the APIM custom domain. For AFD, enter only the AFD endpoint host (e.g., https://afd-endpoint-pay-...) without any path; the /portalpay prefix is added automatically for /api/* and /healthz.
The key is kept only in memory while this page is open. Do not paste secrets on shared machines.
For public reads (GET /api/inventory, GET /api/shop/config), include the merchant wallet (0x-prefixed 40-hex). Non-GET requests should use JWT and will ignore this header.
Query ParametersUsing server-side proxy to avoid CORS. Requests go through /api/tryit-proxy to AFD/APIM.cURLcurl -X GET "https://api.pay.ledger1.ai/portalpay/api/users/search?limit=25"Response Status—Response Headers—Response Body—
Success (200 OK):
json{ "users": [ { "wallet": "0x1234...abcd", "displayName": "Alice", "pfpUrl": "https://cdn.example/pfp/alice.png", "xp": 1234, "live": true, "lastSeen": 1698790000000, "lastHeartbeat": 1698790100000, "domains": ["gaming", "defi"], "platforms": ["farcaster", "twitter"], "languages": ["en", "es"] } ], "total": 1 }
Degraded (Cosmos unavailable):
json{ "users": [], "degraded": true, "reason": "cosmos_unavailable" }
Notes:
- Ordering defaults to XP descending server-side.
- Filtering for domains/platforms/languages requires that the user has all requested keys in metrics.
- markupcontrols how many items are scanned before server-side filtering; results are then sliced to
scanmarkup.limit
Possible responses: 200 (OK), 429 (rate limited)
GET /portalpay/api/users/live#
Returns users with recent presence heartbeats, indicating they are currently live and public.
Behavior:
- Active if markupwithin the last 2 minutes
lastHeartbeat - Only returns users with markupand
live = truemarkupspacePublic = true
Headers:
markupOcp-Apim-Subscription-Key: {your-subscription-key}
Example requests
curl -X GET "https://api.pay.ledger1.ai/portalpay/api/users/live" \
-H "Ocp-Apim-Subscription-Key: $APIM_SUBSCRIPTION_KEY"GET/portalpay/api/users/liveTry It: Users Live
List currently live/public users.
Default is the APIM custom domain. For AFD, enter only the AFD endpoint host (e.g., https://afd-endpoint-pay-...) without any path; the /portalpay prefix is added automatically for /api/* and /healthz.
The key is kept only in memory while this page is open. Do not paste secrets on shared machines.
For public reads (GET /api/inventory, GET /api/shop/config), include the merchant wallet (0x-prefixed 40-hex). Non-GET requests should use JWT and will ignore this header.
Using server-side proxy to avoid CORS. Requests go through /api/tryit-proxy to AFD/APIM.cURLcurl -X GET "https://api.pay.ledger1.ai/portalpay/api/users/live"Response Status—Response Headers—Response Body—
Success (200 OK):
json{ "live": [ { "wallet": "0x1234...abcd", "displayName": "Alice", "pfpUrl": "https://cdn.example/pfp/alice.png", "spaceUrl": "https://portalpay.com/alice", "liveSince": 1698789000000, "lastHeartbeat": 1698790100000, "languages": ["en"], "domains": ["gaming"], "platform": "farcaster" } ] }
Degraded (Cosmos unavailable):
json{ "live": [], "degraded": true, "reason": "cosmos_unavailable" }
Possible responses: 200 (OK), 429 (rate limited)
Rate Limiting and Gateway Posture#
- APIM custom domain is primary; if AFD is enabled it injects markupwhich APIM validates.
x-edge-secret - Responses may include markup,
X-RateLimit-Limitmarkup,X-RateLimit-Remainingmarkup.X-RateLimit-Reset - On markup, implement exponential backoff.
429 Too Many Requests
Scopes#
Typical APIM scopes for Users endpoints:
- markup
users:read
403 ForbiddenNotes on Auth Models#
- Developer reads must use markup. Wallet identity is resolved automatically at the gateway based on your subscription.
Ocp-Apim-Subscription-Key - Admin/UI write operations related to users (e.g., profile updates, presence tracking writes, follow/unfollow mutations) are performed within the PortalPay app and require JWT cookies (markup) with CSRF protections and role checks; these are not available via APIM developer subscriptions.
cb_auth_token - Do not send wallet identity headers; APIM strips wallet headers and stamps the resolved identity.
