Read one page of an organization's analytics roster: one row per current member, with
what that member contributed over a period.
The roster is computed off the request path, like the metrics it is drawn from. A
roster that is not in the cache answers 202 Accepted with Retry-After, an empty
data array and users under meta.pending. Re-issue the identical request after
that many seconds. An empty page on a 202 means "not ready yet", never "no members".
Rows describe the organization's current roster. A member who has since left is absent,
even from a range that predates their departure. Owners are reported as admin — this
view has no separate owner role.
The endpoint is opt-in while in pilot: it answers only for organizations Padlet has
enrolled, and enrollment is granted on the organization's owner. Ask Padlet support to
enroll an organization.
Requires an API key belonging to an admin of the organization (a teacher, for a classroom).
Organization not enrolled, unknown id, or no access — every denial answers the same 404.
Opt-in while the endpoint is in pilotThis endpoint only answers for organizations Padlet has enrolled. Enrollment is granted on the organization's owner. Being an admin is not enough. Email [email protected] to ask for enrollment. Until then every call answers
404, the same response an unknown organization gets.
API keyYou will need to include your API key found here.
Please include the key in your header.
{"X-API-KEY": <api_key>}The key must belong to an admin of the organization, or a teacher for a classroom.
A 202 means poll, not failThe roster is computed off the request path. When it is not cached, the response is
202 Acceptedwith aRetry-Afterheader. Thedataarray is empty.usersappears undermeta.pending. Re-issue the identical request after that many seconds.An empty page on a
202means the roster is not ready. It never means the organization has no members.
Reads one page of an organization's analytics roster. Each row is one current member, with what that member contributed over a period.
It is not a breakdown of memberCount. That metric counts members who joined on or before to, while this roster lists every current member whenever they joined, so meta.totalCount and memberCount can disagree.
Query parameters
| Parameter | Notes |
|---|---|
from, to | YYYY-MM, inclusive. The range counts both endpoints and may span at most 24 of them, so to can be no more than 23 months after from. Send both or neither. Omitting both reads the organization's current billing term, or all time if it has none |
status[] | active or inactive. Repeatable. Listing both is the same as omitting it |
userType[] | admin, maker, teacher, student, contributor, guest. Repeatable |
q | Case-insensitive substring match on name or email |
sort | name (default), email, userType, signupDate, lastActivityDate, padlets, posts, comments, reactions |
order | asc (default) or desc |
page | 1-based, default 1 |
perPage | Default 25, maximum 100 |
Repeatable parameters take PHP-style brackets: status[]=active&status[]=inactive. A single value can be sent without them.
from cannot precede January of five years ago, and to cannot be later than the current month. A range inside the 24-month cap but outside that window is still a 400.
Nothing is clamped. A perPage above 100, a zero or negative page, and an unknown sort, order, status or userType value are all a 400. (page - 1) * perPage may not exceed 1,000,000.
Any role in the list is accepted for any organization. Asking a classroom for maker returns no rows rather than an error.
Rows with no value for the sort column sort to the start of an ascending page and the end of a descending one. A sort=lastActivityDate scan therefore reaches members who never contributed either first or last, depending on order.
Row attributes
| Attribute | Notes |
|---|---|
name | Display name, falling back to the username when it is blank |
username | Padlet username. Can be null |
email | Can be null |
userType | The member's role. Owners are reported as admin |
active | Whether the member contributed anything in the range |
signupDate | UTC date the member signed up for Padlet, not the date they joined this organization |
lastActivityDate | Their most recent activity in this organization, all time. Not scoped to the range. See below |
padlets | Padlets created in the range |
posts | Posts written in the range |
comments | Comments written in the range |
reactions | Reactions given in the range |
The id of each row is the member's user hashid.
What the roster covers
Rows are the organization's current roster. A member who has since left is absent, even from a range that ends before they left.
The four counts and active are scoped to the range. lastActivityDate is not. It is the member's most recent activity in this organization, whenever it happened. That means it can fall outside the range in either direction.
lastActivityDate also counts time spent on a padlet. The four counts do not. A member who is inactive for the range can therefore still carry a date.
lastActivityDate is null only when the member has no recorded activity in the organization at all.
There is no owner value for userType. The roster reports owners as admin. Filtering userType[]=admin therefore returns admins and the owner together. There is no way to ask for the owner alone.
active means the member created a padlet, post, comment or reaction in the range. Reading or viewing does not count, so a member who only opened padlets is inactive.
Meta
| Field | Notes |
|---|---|
status | ready, pending while the roster is being computed, or failed |
dateRange | The range the counts cover, to the day |
page | The page served |
perPage | Rows per page |
totalCount | Rows matching the filters across all pages, not the size of this page |
totalPages | ceil(totalCount / perPage) |
pending | ["users"] on a 202, alongside retryAfter |
errors | ["users"] when the roster failed. data is empty. Read it as an error, never as no members |
A failed roster answers 200, not a 5xx. Check meta.status before reading data.
Errors
| Code | Meaning |
|---|---|
400 | An unknown sort, order, status or userType value, a non-positive page or perPage, a perPage above 100, an offset past 1,000,000 rows, or a malformed or too-wide range |
401 | Missing or revoked API key |
404 | The organization does not exist, is not enrolled, or your key has no analytics access to it. All three get the same response |
406 | The Accept header named something else. Send application/vnd.api+json, or omit it |
429 | More than 60 requests in an hour for this API key and organization. This endpoint has its own allowance, separate from the metrics endpoint. Retry-After gives the wait in seconds |
Example
curl "https://api.padlet.dev/v1/organizations/$ORG_ID/analytics/users?from=2026-01&to=2026-03&status[]=active&sort=posts&order=desc&perPage=2" \
-H "X-API-KEY: $PADLET_API_KEY"{
"data": [
{
"id": "user_abcd1234efgh5678",
"type": "organizationAnalyticsUser",
"attributes": {
"name": "Ada Lovelace",
"username": "ada",
"email": "[email protected]",
"userType": "teacher",
"active": true,
"signupDate": "2025-09-14",
"lastActivityDate": "2026-03-02",
"padlets": 4,
"posts": 37,
"comments": 12,
"reactions": 58
}
},
{
"id": "user_wxyz9876stuv5432",
"type": "organizationAnalyticsUser",
"attributes": {
"name": "Alan Turing",
"username": "alan",
"email": "[email protected]",
"userType": "student",
"active": true,
"signupDate": "2025-08-21",
"lastActivityDate": "2026-03-01",
"padlets": 2,
"posts": 19,
"comments": 5,
"reactions": 23
}
}
],
"meta": {
"status": "ready",
"dateRange": { "from": "2026-01-01", "to": "2026-03-31" },
"page": 1,
"perPage": 2,
"totalCount": 348,
"totalPages": 174
}
}To export a whole roster, walk page until it passes meta.totalPages. Keep from, to and the filters identical across the walk. totalCount is computed per request, and changing a filter mid-walk repaginates the results underneath you.
