Docs
Leaderboards, away and inbox
Three read-only views of who sent what: a ranking, a summary of what arrived since the user last looked, and a 24-hour list of received gifts. None of them moves coins.
Each view has a server endpoint (secret key) and a client endpoint (client token, for the signed-in user). The SDKs draw all three; the pages below are for when you build your own screen or want the numbers on your server. Reads are not counted towards your plan. The numbers are display counters, never balances: a receiver never gets spendable coins.
| View | Server (secret key) | Client (client token) |
|---|---|---|
| Leaderboard | GET /v1/leaderboards/{board} | GET /v1/client/leaderboards/{board} |
| Hide a user | PUT /v1/users/{external_id}/leaderboard-visibility | (your server only) |
| While you were away | GET /v1/users/{external_id}/awayPUT /v1/users/{external_id}/away/cursor | GET /v1/client/me/awayPUT /v1/client/me/away/cursor |
| Inbox | GET /v1/users/{external_id}/inbox | GET /v1/client/me/inbox |
Leaderboards
{board} is senders (who sent gifts) or receivers (who
received them), ranked by the value of the gifts or by their number. Reversed gifts never count;
deleted users and users who opted out never appear.
| Query | Meaning |
|---|---|
period | day, week (Monday to Sunday), month or all, in UTC. Default week. Kept: today and 7 days back, this week and 4 before, this month and 12 before. |
metric | units (value of the gifts in your own coin units) or gifts (their number). Default units. |
at | Any day inside the wanted period, YYYY-MM-DD. Default today. Ignored for all. Outside the kept range: 400 period_out_of_range. |
limit | Rows, 1 to 100. Default 10. The board is the top 100: there is no page 2. |
user (server) / include_me (client) | The server adds a me block for that user. The client call includes one for the token user unless include_me=false. |
GET /v1/leaderboards/senders?period=week&metric=units&limit=3&user=ava
{
"board": "senders", "period": "week", "metric": "units",
"label": "2026-W44",
"starts_at": "2026-10-26T00:00:00Z", "ends_at": "2026-11-02T00:00:00Z",
"as_of": "2026-10-29T10:15:02Z",
"data": [
{ "rank": 1, "user": "ben", "gifts": 14, "units": 5200 },
{ "rank": 2, "user": "cem", "gifts": 9, "units": 3100 },
{ "rank": 2, "user": "dilan", "gifts": 4, "units": 3100 }
],
"has_more": true,
"me": { "user": "ava", "rank": 41, "gifts": 2, "units": 300, "hidden": false }
}
rank: competition rank. Equal scores share a rank (1, 2, 2, 4).label:2026-10-26,2026-W44,2026-10orall.starts_atandends_at(exclusive) arenullforall.as_of: when the ranking was computed. At most 30 seconds old for day and all time, 2 minutes for week and month, 10 minutes for finished periods.me.rank: the exact rank when the user is in the top 1,000, otherwisenull(show "1,000+"). Alsonullwithout a score in the period or when hidden.me.hiddensays the user opted out.- The first read after the feature starts counting older gifts can answer
503 leaderboard_building. Retry after theRetry-Afterheader (30 seconds).
Hiding a user
For users who asked not to be ranked. PUT /v1/users/{external_id}/leaderboard-visibility
with { "hidden": true } removes the user from every board at once and keeps their
counters; { "hidden": false } shows them again. It needs an
Idempotency-Key, creates the user if it does not exist yet, and is not counted
towards your plan.
While you were away
The gifts a user received since they last looked, at most the last 7 days, grouped by gift: for a
card on the home screen and a short replay of the effects. Reading changes nothing. After the
person has seen the summary, send its cursor to the cursor endpoint so the next read
starts from there. Nothing here is real time. A user who does not exist yet gets an empty summary.
GET /v1/users/ava/away?max_groups=5
{
"user": "ava",
"since": "2026-10-27T08:00:00Z", "until": "2026-10-29T10:15:02Z",
"cursor": "aw1.MTcyODYzMTgwMjUxMS40MjE3",
"truncated": false,
"total_gifts": 7, "total_units": 1900, "sender_count": 3,
"groups": [
{ "gift": { "id": "rose", "name": "Rose", "price": 100, "icon_url": "…", "animation_url": null },
"count": 5, "units": 500, "sender_count": 2,
"senders": [ { "user": "ben", "count": 3 }, { "user": "cem", "count": 2 } ] }
],
"top_senders": [ { "user": "ben", "count": 4, "units": 1200 } ]
}
PUT /v1/users/ava/away/cursor
{ "cursor": "aw1.MTcyODYzMTgwMjUxMS40MjE3" }
max_groups: gift groups to return, 1 to 10. Default 5. Groups are biggest first byunits; each lists at most 3 senders.top_sendershas at most 5, by gift count.since(query): an earliercursorto read from, for this read only. It does not change the stored cursor.cursor: send it toPUT .../away/cursorafter showing the summary. It is unchanged when nothing is new.truncated: more than 2,000 gifts arrived in the window, so the totals are lower bounds.priceis today's catalog price, so effects match the gift tray. Auserofnullis a deleted sender; all of them are merged into one entry.- The cursor only moves forward. An older or equal cursor changes nothing, so repeating the call is safe. It needs no
Idempotency-Keyand is not counted towards your plan.
Inbox
The gifts a user received in the last 24 hours, one row per gift, newest first: who sent which gift and when, for an inbox or activity list. Messages, metadata and references are never included. The server keeps no read state: keep the time of the newest row you showed and compare on your side to draw a badge.
GET /v1/users/ava/inbox?limit=20
{
"user": "ava",
"since": "2026-10-28T10:15:02Z", "until": "2026-10-29T10:15:02Z",
"data": [
{ "id": "gtx_01JA0Q8X2M4N6P8R0T2V4W6Y8Z", "created_at": "2026-10-29T09:58:11Z",
"sender": "ben",
"gift": { "id": "rose", "name": "Rose", "price": 100, "icon_url": "…", "animation_url": null },
"quantity": 3, "units": 300, "status": "completed" }
],
"has_more": false,
"next_cursor": null
}
limit: rows per page, 1 to 100. Default 20.cursor: thenext_cursorof the previous page (Pagination).senderisnullfor a deleted sender.unitsis the value when the gift was sent (price times quantity).status: a reversed gift stays in the list asreversed. The SDK components hide it.- A user who does not exist yet gets an empty list; a deleted user is
422 user_deleted.
Errors
400 invalid_request: a bad query value.400 period_out_of_range:atoutside the kept leaderboard history or in the future.503 leaderboard_building: the first leaderboard count is still running. Retry afterRetry-After.- The client endpoints can also answer
401 invalid_client_token(mint a new token) and503 temporarily_unavailable.
Every error type is listed under Errors. The SDK components that draw these views are in Customize the SDK.
Questions or something unclear? support@giftingstack.com.