Attendance API
Last updated: August 2026
Your bots already know who joined the voice channels during your content. This API lets your own script read that list, so you can hand out DKP (or check who showed up) without copying names by hand.
Before you start
- Turn on Attendance for your server: open your server in the dashboard, go to the Activity tab and press Turn on. Nothing is recorded until you do.
- In the same place, open API access and create a token. You will see it once — copy it right away. If you lose it, revoke it and make a new one.
A token belongs to one server. You never send the server ID: it comes from the token.
Calling the API
Send the token in the Authorization header:
curl -H "Authorization: Bearer txrc_your_token_here" \
"https://app.example.com/app/api/v1/attendance?from=2026-08-16T20:00:00Z&to=2026-08-16T23:00:00Z"
Replace app.example.com with the address you use for your dashboard.
Dates (from and to) can be ISO 8601 with a time zone, or milliseconds since the epoch.
to defaults to now.
Limits: 60 requests per minute per token. The reply includes RateLimit-* headers, so
your script can see how many calls it has left.
Endpoints
GET /api/v1/token
Checks that a token works. Useful while you set up your script.
{ "guild_id": "123456789", "scopes": ["attendance:read"], "expires_at": null }
GET /api/v1/attendance
One row per member, with the time each one spent in voice inside the window.
| Query | Meaning |
|---|---|
from | Start of the window. Required. |
to | End of the window. Defaults to now. |
min_minutes | How long counts as attending. Sets the attended flag; nobody is hidden. |
channel_id | Only count one channel. |
{
"guild_id": "123456789",
"from": "2026-08-16T20:00:00.000Z",
"to": "2026-08-16T23:00:00.000Z",
"sample_interval_seconds": 30,
"min_minutes": 60,
"totals": { "members": 24, "attended": 21, "total_minutes": 2870 },
"channels": [
{ "channel_id": "222", "name": "party-1", "members": 6, "total_minutes": 700 }
],
"members": [
{
"user_id": "245244453630115840",
"username": "thexreth",
"display_name": "TheXReth",
"minutes": 170,
"first_seen": "2026-08-16T20:02:00.000Z",
"last_seen": "2026-08-16T22:52:00.000Z",
"attended": true,
"channels": [{ "channel_id": "111", "name": "callers", "minutes": 170 }]
}
]
}
GET /api/v1/attendance/sessions
The raw stretches of time, if you would rather do the maths yourself. One row each time a member joined a channel and left it.
| Query | Meaning |
|---|---|
from, to | Same as above. |
limit | Rows per page (up to 500, 100 by default). |
cursor | Pass the next_cursor from the last reply to get the next page. |
next_cursor is null when there is nothing left to read. left is null for someone who
is still in the channel.
Errors
| Status | error | What happened |
|---|---|---|
| 401 | missing_token | No Authorization header. |
| 401 | invalid_token | The token is wrong, revoked or expired. |
| 403 | insufficient_scope | The token cannot read attendance. |
| 403 | attendance_disabled | Attendance is turned off for that server. |
| 400 | invalid_range | from/to missing or the wrong way round. |
| 429 | rate_limited | More than 60 calls in a minute. |
Good to know
- Times are close, not exact. Presence is checked every 30 seconds, so the start and end of each stretch can be off by a few seconds. Totals over an evening are fine; do not use this to time anything to the second.
- Only channels your bots use are counted. Someone sitting in a voice channel without a bot does not appear.
- History is kept for 90 days, then deleted. Pull what you need before that, or export a CSV from the dashboard.
- This is version 1. Fields that exist today will keep their name and meaning. If we ever need to change them, it will be under a new version.
- Treat the token like a password. Anyone holding it can read your members’ names, IDs and times. Keep it out of public repos, and revoke it from the dashboard if it leaks.