💚

Health Check

Is the API running? Hit one of these.

Environment Local
Auth Not logged in
SignalR Disconnected
Response will appear here.
📡

SignalR (Video Hub)

Connect to the real-time Video hub. You’ll see events when videos are uploaded, location groups updated, or videos deleted. Login required.

Hub URL: /hubs/videos. Connect with your current token, then upload or delete a video in the Videos section to see events here.

Disconnected
—
🔧 Azure SignalR REST — Test POST /api/v1/hubs/:hubName//:send

Paste the Azure SignalR connection string. The JWT is built in-browser (same logic as the Worker). This tests whether the Azure SignalR endpoint accepts the publish call.

—
🧭

Infra trace (SignalR · Redis · Service Bus)

Hub events in a sortable log. Development API only: inspect live-stream Redis keys and recent Service Bus publishes from this app (see Redis / Service Bus tabs).

Uses the same hub connection as Realtime. Connect once (either tab), then delete or upload a video to see VideoDeleted vs other events.

Disconnected
Time Kind Event / line Summary Payload

Last health summary

Run Refresh health on Redis or Service Bus tab.
📹

Live Stream Testing

Host and audience tokens, go-live, RTC preview, event-linked streams, request live, and report testing.

Normal user — What happens with Live & Report? (tap to collapse)

Without Report: Host Go Live → followers notify. Request live → receiver gets SignalR RequestLive (+ bell). Receiver Start = accept → requesters get “is now live”.

Report (live): 1 report → stream auto-stops for moderation, then admin can Approve or Reject.

Admin is not in normal go-live — only after reports (see Admin tab).

Login required. Flow: Event (optional) → Host token → Start → Join/End. Two accounts for request live: target must Connect hub (Realtime tab) for RequestLive.

Active live streams

All currently live sessions from GET /api/videos/my-videos/grouped-by-location. Connect Realtime → SignalR for instant viewer join/leave updates.

0 active 0 you joined SignalR: —
Log in and click Refresh list to load active streams.
Live activity log (join / leave / SignalR)
No events yet.
Dashboard actions appear here.

Follow & go-live requests

Two users required: log in as User A here and paste User B’s Guid below → Follow. When B starts a live stream (other session), A should receive a follower notification (if Firebase + devices are set up). Request go live → POST /api/livestreams/requests (201). Target gets SignalR RequestLive if hub connected (+ in-app bell). Accept = POST /start (no separate accept API). Requesters get FCM when target goes live.

Sent as JSON source on go-live request.
(Pending requests JSON appears here.)
Follow / request responses appear here.
Response will appear here.

1) Token

Response will appear here.

2) Start stream

Response will appear here.

2.5) RTC publish/playback (Laptop cam)

Response will appear here.

3) Live Studio

Sequential flow after Start + RTC: Join stream → Open chat room → Chat & moderate. Backend creates chatRoomId on start — no PATCH. Use another browser/user to join as viewer.

Room — Comments — Chat off

Live chat

Open chat room to start messaging

No messages yet. Join the stream, then Open chat room.

Comments must be ON for viewers to send.

Studio responses appear here.

3c) Report live stream (viewer)

Join as viewer (another account), paste Live stream ID above (ls_…). Reports via unified POST /api/videos/{id}/report (same reasons as videos). 1st distinct report: reporter-only banner; 2nd distinct report (default threshold): stream auto-stops for moderation.

Report response appears here.

4) Feed check

(Grouped feed result will appear here.)
Response will appear here.
Response will appear here.
📱

Live Playground

Mobile-style live + circle + chat. Click only — no stream-id paste. Use 2 browsers to test SignalR LiveStreamChatRoomReady.

Live SignalR: —

Tap a host to join. Login first. Connects SignalR + Chat automatically.

No live hosts yet. Go Live here or refresh.
📡

Sentry Test

Trigger a test exception to verify Sentry is capturing errors.

This calls GET /api/SentryTest/throw which throws an exception. You should see a 500 response here and the error in your Sentry dashboard.

Response will appear here.

Apple IAP config diagnostics (Admin only). Calls GET /api/Credits/debug/apple-config.

Response will appear here.
📄

Day-wise Logs

List backend rolling logs, view latest lines, and download by day.

Reads all files from backend Logs folder. View opens full file content and download saves full file.

(Click "Load logs" to fetch day-wise files.)
(Select a log file to view.)
Response will appear here.
🔐

Welcome

Sign in to access the tester dashboard.

New here?

Step 1 sends OTP to email. Enter it in Step 2, then set password in Step 3.

Step 1
Step 2
Step 3
Already have an account?
Step 1
Step 2
Step 3
Remembered your password?
Google

Or paste a Google ID token:

Apple

Paste Firebase ID token after Apple sign-in via Firebase Auth.

Firebase

Paste a Firebase ID token from your app (e.g. user.getIdToken()).

Prefer email/password?
📚

Docs

Module-wise documentation viewer (Markdown).

Select a module and document to view it here.
👤

Profile

Get or update your profile: name, email (read-only), gender, dashcam type, profile picture. Login required.




My Circle

Search or browse users and tap + to add them to your circle. Uses GET /api/users/search and /api/circles.


Or add/remove by user ID manually:

🔒

Change password

Set a new password (requires current password). Login required.

🎬

Videos

Test video upload modes: Direct-to-Azure (recommended) and Legacy API modes. Login required.

Uses Google Places – type to see top 10 suggestions, then click to select.
You can also paste lat/long and click “Reverse geocode” to fill location.
Recommended: use Direct-to-Azure upload. Legacy modes are kept for backward compatibility testing.

Chunked upload: use Direct-to-Azure (recommended) or Legacy API-proxied chunks (older POC). Thumbnail is optional on complete for these chunked flows.


Load my videos = everyone's videos. My Feed = only your videos (with views, shares, average rating). Use Play (MP4) to play immediately; Play (HLS) appears after background encoding (refresh after 1–2 min). Validation uses 1/2/5 tiers, and in rating-batch mode you send 4 previous IDs while current URL video is the 5th.

Current tile video ID in URL is treated as 5th video for /validate batch settle to 30.
After preset, click "Validate video" on any tile in My Feed / Unrated list.
Progress: —/5 | Lifetime ratings: — | Credit balance: —

Home map search

Calls GET /api/map/search?query=.... It returns both metadata search matches and Google location-based matches, including isGoogleLocationResult and fallback lat/lng when no nearby video is found.

(Map search results will appear here.)

ML manual bearer token (optional)

If provided, this token is used for GET /api/videos/nearby and POST /api/webhooks/video-analysis. If empty, UI uses your login token.

Nearby analysis lookup

Calls GET /api/videos/nearby with latitude, longitude, timestamp, radius and time_range to verify ML analysis records.

(Nearby analysis results will appear here.)

AI/ML callback webhook tester

Calls POST /api/webhooks/video-analysis with required Authorization: Bearer and X-Job-ID header.

⭐

Rate Testing

Rate-focused testing for milestone progress, owner visibility, and full validation payloads.

Use this tab to test rating flow quickly without scrolling the full Videos section.

Progress: —/5 | Pending for milestone: — | Lifetime ratings: — | Credit balance: —

Selecting a candidate auto-fills Video ID.
(Candidate list with owner details will appear here.)
Response will appear here.
✅

Valid Videos Rate

Only valid videos (not expired, not deleted) that you can rate. Rate directly from tile and verify confidence score update.

This uses GET /api/videos/videos-left-to-rate and shows confidence score, average rating, and per-user rating entries for each tile.

Response will appear here.
🔔

Notifications (v1)

Register device token, list notifications, unread count, mark read, and send admin test push.

1) Register Device

Calls POST /api/v1/devices. Login required.


2) List Notifications

Calls GET /api/v1/notifications. Use filters as needed.

(Notifications list will appear here.)

3) Mark as Read


4) Test Push (Admin)

Calls POST /api/v1/notifications/test-push. Admin JWT required.


5) Admin Simulation Helpers

Admin-only helper actions to quickly test the 2 enabled admin auto-notification flows.


6) Request Live — test bench (all results on this page)

Single window: log in as target → Use my user ID → Connect hub → Run full test. Two windows: target connects hub in window A; sender uses target Guid in window B.

Hub: — Presence: — RequestLive: waiting

Logged-in user: —

Ready — follow steps above or click Run full test.
(Presence and send responses appear here.)
(Connect hub as the target user; events show here when delivery works.)
🧠

AI/ML Reprocess

Select videos and submit to AI/ML through backend so ML job id is persisted on video.

Loads your videos from backend and calls backend endpoint POST /api/videos/{id}/ml/submit for selected videos.

(Load videos to start selection.)
💳

Credits & Buy Credits

View balance, packages, and create a Stripe payment intent to buy credits. Login required for overview and purchase.


Select a package and create a payment intent. Use the returned clientSecret with Stripe.js (or test with Stripe test card 4242 4242 4242 4242). After payment, webhook adds credits.

Select Option
Click "Get packages" to load bundles.
If a saved card is selected, payment will use it without entering card details again.

Verify IAP purchase (Apple / Google)

Login required. This calls POST /api/credits/verify-purchase.


Transaction history (last 30 days).

💎

Subscriptions

Browse plans, activate via IAP, cancel, and re-subscribe after cancel. Admin: full plan management. Login required.

Applies to GET /api/subscriptions/plans?platform=..., activate, and change plan. iOS/Android filters plans by matching SKU and sets the store SKU in the response.

1) Browse Plans

Calls GET /api/subscriptions/plans with the platform selected above. Select a card to auto-fill the activation form below.

Click "Load Plans" to see available plans.
Response will appear here.

2) Activate / Re-subscribe (IAP)

Calls POST /api/subscriptions. Paste the receipt / purchase token from the device store. Plan ID and platform auto-fill when you select a plan card above.

After cancel: complete a new store purchase — do not reuse the old token. The backend expires the cancelled subscription when the new one activates.

iOS — synced from Store platform above

Response will appear here.
Re-subscribe response (when using the button above) appears here.

3) My Active Subscription

Calls GET /api/subscriptions/me. Returns active, past-due, or cancelled-pending-expiry subscription. 404 if none.

Response will appear here.

4) Cancel Subscription

Calls DELETE /api/subscriptions/{id}. Stops auto-renewal — status becomes cancelled and access stays until expiryDate. Tokens are NOT removed. You can re-subscribe immediately with a new IAP token (section 2).

Response will appear here.

5) Change Plan (Upgrade / Downgrade)

Calls PATCH /api/subscriptions/{id}. Upgrade = immediate, requires new IAP token. Downgrade = deferred to period end, no token needed. Click a plan card above to auto-fill New Plan ID.

Response will appear here.

6) Payment History

Calls GET /api/subscriptions/payments?limit=&offset=. Returns paginated list of all payments. Click a row to auto-fill the Receipt ID below.

(Click "Load Payment History" to fetch.)
Response will appear here.

7) Payment Receipt

Calls GET /api/subscriptions/payments/{id}. Returns receipt details for a single payment. Auto-fills from the first result in Payment History above.

Response will appear here.

8) Subscription History

Calls GET /api/subscriptions/me/history. Returns all past and current subscription records for the logged-in user.

(Click "Load Subscription History" to fetch.)
Response will appear here.
🛠️

Admin – Credits

For Admin users only. Manage base price per credit and credit packages.

You must be logged in as an Admin (UserRole.Admin) for these calls to succeed.

Base price per credit


Packages

(Packages will appear here.)

Create or update a package below, then click the corresponding button.

Choose a package to load its Id and fields for update. Leave empty to create a new package.

Admin — What can report review do? (tap to expand)

Video: Allow = content OK. Remove = take down (+ optional block user).

Live: 1 report auto-ends stream → admin reviews. Approve = short playback (~48h). Reject = remove. Force stop = end while still live.

List: GET /api/admin/reported-content (video + live).

Reported content (video + live)

Click any tile → POST /api/admin/video-reports/by-ids (uses session/video GUID; report id optional for live).

All: — | Pending: — | Allowed: — | Removed: —

(Reported video + live items appear here.)
Click a reported content tile to load full detail.
🛠️

Admin - Dev Users

Search a user, add them to the dev list, or remove them. Login and profile return isDevUser: true when the logged-in user's full name is in this list.

Admin only. Search uses GET /api/admin/users (includes you). Add uses POST /api/admin/dev-users. Delete uses DELETE /api/admin/dev-users/{id}. The match is the user's current first + last name, ignoring case.

Dev user list

(Dev users appear here.)
👥

Admin - Users

For Admin users only. List users sorted by active first and newest created.

Calls /api/admin/users with paging/search. Use checkboxes for bulk activate/deactivate via PATCH /api/admin/users/status.

Select users from the list below for bulk action.
(Users will appear here.)
📊

Admin – Report Schedules

For Admin users only. Test and configure the system performance report email.

You must be logged in as an Admin (UserRole.Admin) for these calls to succeed.

⚡ Quick test send

Sends (or previews) a real report right now — no schedule needs to be created first. Use this to just check what the email looks like.

Adds the Azure Monitor infra-health section — only valid when Frequency above is Daily.

⚙️ Advanced: manage recurring schedules (tap to expand)

Only needed to set up the real automated recurring email (e.g. every day at 9am). For just testing the report, use Quick test send above instead. Multiple schedules can be active at once (e.g. Daily + Weekly + Monthly), each with its own time/day/recipients.

Schedules

(Schedules will appear here.)

Create or update a schedule below, then click the corresponding button.

Choose a schedule to load its fields for update. Leave empty to create a new one.

No schedule selected — fields below will create a new schedule.

Email

No recipients yet — add one below.

Only valid when Frequency above is Daily.

Send now: immediately sends the selected saved schedule's report email for its current window — ignores day/time due-check.

🔄

Refresh Token

Get new tokens (uses saved refresh token).

👋

Logout

Sign out (uses current token).

📍

Scan Mode

Test POST /api/v1/heartbeat and GET /api/scanmode/online-users. Login required. Presence TTL is 6 minutes — send heartbeat every 5 min to stay online.

Two-device test: open this tab on two browsers with different users, same coordinates. Always await heartbeat before Get online users (or use the combined button).

Presence: — Last heartbeat: — Expires in: —

1) Heartbeat

Type latitude, longitude, and altitude manually below, then send. Browser GPS is optional — it only fills these fields (you can edit before send).

Manual coordinates


2) Online users (500 m)

Calls GET /api/scanmode/online-users. Returns nearby online users except you. Empty [] is valid when nobody else is within 500 m.

(Nearby online users will appear here.)
🗺️

Quests — Treasure Hunt

Create, activate, find, and manage treasure-hunt quests. Login required for all endpoints.

Auto-filled after Create. Paste any quest Guid to target it.
💰 Balance: — tokens

1) Create Quest — Free & Premium

POST /api/v1/quests · sent as multipart/form-data — Server derives tier, reward tokens and premium cost from the chosen icon. FREE Standard icons cost nothing. PREMIUM icons deduct PremiumCostTokens from your balance when the quest goes Active (drain order: Daily → Earned → QuestEarned → Purchased). Click Load Icons from API first.

Select an icon to see its tier, reward tokens and premium cost.
Sent as the questImage multipart file part.
AR / positioning fields (optional)
Response will appear here.

2) Quest Actions (uses Quest ID above)

All three use the Quest ID field at the top of this section. Activate a Premium quest deducts its PremiumCostTokens from your balance (drain order: Daily → Earned → QuestEarned → Purchased); returns 402 if you can't afford it. Cancel fails with 409 once any finder has collected. Create Share Link calls POST /api/v1/quests/{id}/share-score — same (quest, sharer) combo returns the previously-minted link for 30 days instead of a fresh one.

(Quest detail will appear here.)
Response will appear here.

3) Find (Collect) Quest

POST /api/v1/quests/{id}/find — Server haversine proximity check. Your coordinates must be within CollectionRadiusMeters of the quest. Rewards tokens to finder and writes a QuestFinding + UserTreasure record.

Tip: set your coords very close to the quest coords above to pass the proximity check in testing.

Response will appear here.

4) Participant Management

Track an active play session for the quest in the Quest ID field above. A user can only be active in one quest at a time. Start is rejected if you are outside quest_participant_radius_meters (default 2 km). Send Heartbeat calls the unified POST /api/v1/heartbeat with questId — the separate participant heartbeat endpoint has been removed.

(Participants list will appear here.)
Response will appear here.

5) Discovery — Live Map

Map auto-fetches GET /api/v1/quests/viewport on every pan/zoom (debounced 600 ms). Click a marker to select it — fills the Quest ID above and shows details. Color: ● Standard   ● Premium   ● Inactive.

0 quests 0 Standard 0 Premium —
Response will appear here.

Random quest in viewport

Calls GET /api/v1/quests/viewport/random using the four bounding-box coordinates above. Returns a list containing 0 or 1 quest, excluding quests you created. Prefers a quest at least ~2 km from the viewport center (offset left/right / ahead/behind), not dead-center.

Response will appear here.

Nearby quests (radius search)

Response will appear here.

My quests & treasures

(My quests / treasures will appear here.)
Response will appear here.

Quests at an event

Response will appear here.

6) Puzzle State (v2 — not yet active)

GET /api/v1/quests/me/puzzle — Returns your current treasure-icon puzzle slots and completion status.

Response will appear here.

7) Generate Quest Near Me (UC-7)

POST /api/v1/quests/generate — System creates a Standard quest near your coordinates using AI-selected icon. Only 1 active generated quest per user at a time (409 if one already exists).

Response will appear here.

8) Admin — Batch Create Quests

POST /api/admin/quests/batch — Admin role required. Scatters quests randomly inside a venue / event geofence polygon and activates them immediately (system-funded).

Ctrl/Cmd+click to pick multiple. Leave all unselected for random distribution.
(Batch create result will appear here.)
Response will appear here.

9) Admin — Auto-Generate Quests from City Place

POST /api/admin/quests/auto-generate-from-city-place — Admin role required. Uses Google Places API to find top POIs in a city and auto-generates quests at walkable street coordinates near each place.

(Auto-generate result will appear here.)
Response will appear here.
📣

Promotions — Wallet, Create & Discover

Fund the Promotion Wallet, walk a Draft through the Create wizard (Boost / Offer / Repeat), publish it (with a deferred card payment if the wallet is short), discover & claim offers, and redeem vouchers as a merchant. Login required.

💰 Balance: — tokens ✨ Spotlight: 100 tokens
Stripe billing details (used for every card payment below)

This Stripe account requires a cardholder name + billing address on every payment (India cross-border export rule) — otherwise you'll see "export transactions require a customer name and address". Defaults are pre-filled; edit if you like.

Promotion Wallet

GET /api/v1/promotion-wallet — cash funds Boost Visibility & deferred publish/boost charges; vouchers fund Offers.

—
Available Balance
—
Voucher Balance
Response will appear here.

Add Funds

POST /promotion-wallet/cash-top-up-intent, then confirm the card — same Stripe Elements pattern as Credits.

Response will appear here.

Buy Vouchers

GET /promotion-wallet/voucher-packages (no login needed to browse), then POST .../purchase-intent.

Click "Load voucher packages" to see options.
Response will appear here.

My Saved Voucher Packages

Click "Load saved voucher packages" to see your bookmarks.
Response will appear here.

Buy Cash Package (Native In-App Purchase)

Alongside Stripe "Add Funds" above, not a replacement. GET /promotion-wallet/cash-packages?platform=ios|android (no login needed to browse), then POST /promotion-wallet/cash-topup/verify-purchase with a receipt/transaction token from the store — no card entry, no webhook wait, credits cashBalance synchronously in the same response.

Click "Load cash packages" to see options.
Response will appear here.

Recent Activity

GET /promotion-wallet/transactions — newest first.

(Click "Load transactions" to list recent wallet activity.)
Response will appear here.

Create Promotion

Step 1 of 3. POST /api/v1/promotions {name, imageUrl} creates a Draft. Image uploads via POST /api/v1/promotions/image-upload first (done automatically here if you pick a file and click Create Draft).

Required — uploaded automatically when you click "Create Draft".
Response will appear here.

Promotion Detail

Note: Record View never counts while you're logged in as this promotion's creator — log in as a different user to test it, or it won't increment (this is expected, not a bug).

(Promotion detail JSON will appear here.)
Response will appear here.

My Promotions

GET /api/v1/promotions/mine — Profile → My Promotions list with status badges, view counts, and end dates.

(Click "Load My Promotions" to list yours.)
Response will appear here.

Merchant — Scan Voucher Code

Stand-in for scanning a customer's redemption QR with a camera — this is a browser test tool, so just paste/type the code. Uses the merchant's own token (must be the promotion's creator). POST /api/v1/promotion-redemptions/scan

Response will appear here.

Saved Promotions

GET /api/v1/promotions/saved

(Click "Load saved" to list your saved promotions.)
Response will appear here.
🛍️

Promotions — Discover & Claim (Consumer)

The "normal user" side, separate from the Promoter tab: browse what's nearby, open a promotion, and claim its Offer for a redemption code — no promotion creation involved. Log in as a different account than the promoter to test this end-to-end. Login required.

Discover Nearby Promotions

Calls GET /promotions/nearby directly.

📍 Pin = your search location (click map or drag pin). 📣 Markers = the promoter's nearby promotions. Click a marker (or its "View detail" popup button) to open it below.

0 nearby
(Click "Find Nearby Promotions" to list what's around this point. Click any card below to open it.)
Response will appear here.

Promotion Detail

Response will appear here.

My Saved Promotions

(Click "Load Saved" to list your bookmarked promotions.)
Response will appear here.

My Valid Vouchers

Vouchers you've claimed that are still usable — excludes anything already redeemed in-store, and anything whose promotion has expired/been cancelled.

(Click "Load My Valid Vouchers" to list vouchers you can still use.)
Response will appear here.
📡

Quest V1 Live Stream

Follow steps in order: location → viewport quests → participant → hub → live/join. Or use Run all steps.

Role: Host Hub: disconnected Stream: — 🔴 Live joins 0 · peak 0 You: not logged in
① Location → ② Quest → ③ Start Play → ④ Hub → ⑤ Subscribe → ⑥ Go live → ⑦ Participants
1
Your location pending

Set lat/lng first — used for viewport quest search and Start Play radius check.

2
Select quest (viewport) pending

Calls GET /api/v1/quests/viewport using your Step 1 lat/lng + radius (not the Quests tab defaults). Click a card or dropdown.

API: —

Step 1 → set location → Step 2 → Load viewport quests
3
Become quest participant pending

POST …/participants/start — must be within 2km of the quest pin, not just your Step 1 location.

Select a quest — distance to quest pin will show here.

4
Connect SignalR hub pending

/hubs/quest-live-stream — real-time join/leave/end events.

5
Subscribe to quest pending

SubscribeToQuest — receive QuestLiveStreamStarted on this quest.

6
Go live pending

POST …/live-streams — starts stream; you become host participant in stream.

Stream appears here after Start stream.
Selected: —
7
Circle & Live Chat pending

After start/join: circle updates in the Participants monitor (right). Host taps Remove on a viewer to kick · SignalR QuestLiveStreamParticipantRemoved → viewer gets removedByHost: true (rejoin blocked). Backend creates chatRoomId on start (no PATCH).

Room — Comments —
Advanced kick (paste userId)
8
Agora RTC (optional) optional
Flow log
Complete steps 1→6 in order, or use Run all…
Circle 0
  • After join/start — click Refresh participants.
SignalR events
(Events appear after hub connect.)
API responses appear here.
Advanced — manual REST
🛣️

Street Locations

Preview real walkable street coordinates near any point. Calls GET /api/admin/quests/street-locations via Google Roads API and pins each result on the map.

Enter a centre coordinate, choose a search radius (up to 5 km) and how many points to return (1–50). Click Fetch Locations — markers appear on the map below. Click any marker for its coordinates and Place ID.

0 locations Idle
Response will appear here.
🌎

Events Map (App Viewport)

Load live map events from GET /api/events (viewport, ±12h). Search catalog via /api/events/search. Sources: Ticketmaster, ESPN, PredictHQ — multi-country via EventIngestion:SupportedCountryCodes.

Live event map

Viewport events first — pan/zoom to refresh

Uses GET /api/events?SouthWestLatitude=…&SouthWestLongitude=…&NorthEastLatitude=…&NorthEastLongitude=… (±12h window). Green = onGoing, blue = upcoming. PredictHQ events may have no ticket/image URL.

0events
0mapped
0venues

Country support (multi-market ingestion)

Dev config seeds Ticketmaster {CC} + PredictHQ {CC} per country. Prod/UAT typically US only. Click a country to jump the map, set filters, and load viewport events.

Event ingestion (Admin)

Manage Ticketmaster, ESPN, and PredictHQ sync via GET/POST /api/admin/event-sources. One row per country (e.g. PredictHQ IN, Ticketmaster GB) when SupportedCountryCodes includes that market. PredictHQ trial is global (no API country cap); SeeCircles limits ingest via config. Token: Key Vault PredictHQ--ApiToken.

Click “Load event sources” (Admin JWT required).
Ingestion responses appear here.
Smooth event map Pan map or click Load map events
Showing All available states

Event cards

No events loaded yet.

Raw response

Response will appear here.
🏬

Popup Stores

Share & save for Popup Stores and their curated Shop Products (StoreItem). Browse via GET /api/v1/popup-stores/nearby and GET /api/v1/popup-stores/{id} elsewhere; this panel focuses on the new share/save endpoints.

Popup Store

Response will appear here.

Shop Product (StoreItem)

A single curated product inside a Popup Store. Share only — there is no save/unsave for Shop Products.

Response will appear here.

My Saved Popup Stores

Response will appear here.
🔖

Saved Bookmarks

The "Saved" screen's tabbed bookmark list — aggregates Events / Shops / Offers / Vouchers / Videos in one call. Saving/unsaving itself lives on each resource's own module (Events Map, Popup Stores, Videos, Promotions) — this panel is read-only aggregation across all of them.

Bookmarks List

GET /api/v1/bookmarks?tab=&search=&sort=&latitude=&longitude=

Voucher rows (itemType: "voucher", in both this list and the history below) now also carry promotionId (the underlying Promotion, for detail navigation) and claimId (same value as the row's own id, named explicitly so it's unambiguous per-tab). Paste a promotionId into the box below to jump straight to its detail in Promotions (Consumer).

Click "Load Bookmarks" to see results.

Offer/Voucher cards are clickable — jumps straight to that promotion's detail in Promotions (Consumer), same as pasting its id below.

Response will appear here.

Ended Offers

GET /api/v1/bookmarks/offers/ended?search= — saved promotions that dropped out of the Offers tab above: past their own end date, or otherwise no longer Active (cancelled/draft). Unlike Vouchers, there's no Used/Expired split — just one flat "ended" list, most recently ended first.

Click "Load Ended Offers" to see results.
Response will appear here.

Used & Expired Vouchers

GET /api/v1/bookmarks/vouchers/history?search= — claimed vouchers that are no longer active, split into Used (redeemed in-store) and Expired (promotion ended, never redeemed). "Vouchers" here means a claimed PromotionOfferClaim (a QR code the user redeems in-store) — not the purchasable VoucherPackage from the Promotion Wallet module, which is a separate, unrelated bookmark type. Rows here also carry promotionId/claimId — paste a promotionId into the box above to open it.

Used

Click "Load Voucher History" to see results.

Expired

Click "Load Voucher History" to see results.
Response will appear here.
💬

Chat (Agora)

Interactive DM chat — conversations, send/receive, typing indicator. Auto-connects after login.

● Disconnected
💬
Connect to load conversations
💬
Select a conversation
Or click Browse all users on the left
⚙️ API Tools — Token, Raw Search, Peer Profile

Chat Tokens from Login

Populated automatically after login. Used by Connect above.


GET /api/chat/token

Returns a fresh Agora Chat token. Login required.

Response will appear here.

POST /api/chat/token/refresh

Issues a new token (SDK expiry callback path). Login required.

Response will appear here.

GET /api/users/search

Optional q (min 3 chars if set; blank = all users). Paginated via page / pageSize (max 50). Response data.users + totalCount, currentPage, totalPages. Use agoraChatUserId for Agora.


GET /api/users/{id}/chat-profile

Returns isActive — used to show the deactivated banner.

Response will appear here.