Returns engagement, membership and content-safety figures for one organization over a date range.
It uses POST because the query is a list of metric objects. It is still a read, so sending it again changes nothing.
Padlet computes analytics in the background. If a metric is not ready, the response is 202 Accepted, the metric is listed in meta.pending, and Retry-After says how many seconds to wait. Send the same request again until the response is 200 and meta.pending is empty. A query can take several minutes. A pending metric is missing from data; do not treat it as zero.
Pilot: works only for organizations Padlet has enrolled. To enroll, contact Padlet support.
The API key must belong to an admin of the organization, or a teacher for a classroom. An unknown organization, one that is not enrolled, and a key without access all return the same 404.
Pilot: enrollment requiredThis endpoint works only for organizations Padlet has enrolled. To enroll, email [email protected]. Until then, every call returns
404.
Before you start
- API key. Get one from your developer settings and send it as the
X-API-KEYheader. The key must belong to an admin of the organization, or a teacher for a classroom.org_id. CallGET /me?include=organizations. It lists everywksp_organization your key belongs to.org_organizations on padlet.org are not supported yet.
A202means "not ready yet"Padlet computes analytics in the background. If a metric is not ready, the response is
202 Accepted, the metric is listed inmeta.pending, and theRetry-Afterheader says how many seconds to wait.Wait, then send the same request again. Repeat until the response is
200andmeta.pendingis empty. A query can take several minutes.A pending metric is missing from
data. Do not treat it as zero.
Returns engagement, membership and content-safety figures for one organization over a date range.
The endpoint uses POST because the query is a list of metric objects. It is still a read: sending it again changes nothing. Each retry does count toward the limit of 60 requests an hour, so wait for Retry-After between polls.
Request body
| Field | Type | Notes |
|---|---|---|
metrics | array | Required. 1 to 25 metrics. See Query limit |
metrics[].name | string | A metric from the catalog |
metrics[].<property> | string or array | See the catalog. An array splits the result by each value. userType is the exception, see below |
dimensions | array | Send ["month"] for a monthly series. Every metric in the request must support it |
from, to | string | Start and end days, inclusive, as YYYY-MM-DD. Send both or neither. Default: the past 365 days |
Date range rules:
- The range can be at most 24 months long.
fromcannot be earlier than January, five years ago.tocannot be later than the current month.
Breaking any of these returns 400.
Query limit
Padlet runs one query per metric, and one per value when a property is an array (except userType). A request can run at most 50 queries. Split larger requests into several calls.
Metric catalog
| Metric | Properties | Monthly |
|---|---|---|
memberCount | status: active, inactive, invited, joined, all · userType: roles | yes |
newMemberCount | — | yes |
padletCount | userType: roles, monthly only | yes |
postCount | userType: roles, monthly only | yes |
commentCount | userType: roles, monthly only | yes |
reactionCount | userType: roles, monthly only | yes |
visitorCount | — | yes |
peerInteractionCount | userType: roles — required | yes |
wallEngagementMinutes | userType: roles, plus anonymous | no |
attachmentCountByCategory | userType: roles — required | no |
scannedItemCount | — | no |
scannedItemCountByType | — | no |
avgScanTimeMs | — | no |
flaggedItemCount | — | no |
flaggedItemCountByCategory | — | no |
moderationCatchRatePercent | — | no |
topPadlets | sortBy: posts, visitors — required | no |
topUsers | sortBy: posts, padlets — required · userType: roles | no |
topMedia | mediaType: video, audio — required | no |
subscription | — | no |
How to read the table:
- required: you must send this property. The metric has no all-members total.
- monthly only: you can send
userTypeonly together withdimensions: ["month"]. Otherwise the request returns400. Leaving out both is fine:{"name": "postCount"}returns one number.
Not every property value has a monthly form. For example, memberCount with status: ["active", "inactive"] and dimensions: ["month"] returns a 400 that names the unsupported combination.
userType
userTypeuserType takes a single role or a list of roles. A list is one combined group, not a split by role. For example, ["teacher", "admin"] returns one figure for teachers and admins together.
Roles depend on the organization type:
| Organization | Roles |
|---|---|
| School | owner, admin, teacher, student, guest |
| Classroom | owner, teacher, student |
| Team | owner, admin, maker, contributor, guest |
The endpoint accepts every role name for every organization type. A role the organization cannot have returns 0, not an error. For example, admin in a classroom returns 0.
all must be sent alone. ["all", "teacher"] returns 400.
Metric notes
memberCount:statusinvitedandjoinedalso needuserType.wallEngagementMinutes: with nouserType, or withall, the figure includes anonymous visitors. To count members only, list their roles.- Content-safety metrics (
scannedItemCountthroughmoderationCatchRatePercent): available for schools and classrooms only. A team organization gets a400.
What the figures cover
Membership counts use the organization's current members. A member who has left is not counted, even for a date range before they left.
memberCount status | Counts |
|---|---|
all, joined | Current members who joined on or before to |
active | Current members who contributed anything in the range |
inactive | Current members minus active |
invited | Invitations open right now. Ignores from and to |
All other metrics (padlets, posts, comments, reactions, visitors, engagement minutes) count only activity inside the range.
Response
Each metric in attributes.metrics has a name, its properties and its data.
properties shows what Padlet used, not a copy of your request:
- A property you left out comes back as
all. - A single
userTypecomes back as a one-item list. - Duplicate values are removed.
To match an entry in meta.pending or meta.errors to your request, compare the name and these properties.
Shape of data
data| You asked for | data is |
|---|---|
| A plain count | A number, like 42 |
dimensions: ["month"] | A list of monthly rows. See Monthly row keys |
| A property as an array | An object with one key per value, like { "active": 12, "inactive": 3 }. Each value has the shape it would have on its own, for example a list of monthly rows |
topPadlets, topUsers, topMedia | A list of up to 10 items, each with a hashid, a name or title, and its figures. The limit of 10 is fixed. There is no pagination |
attachmentCountByCategory | A list of { category, count } |
scannedItemCountByType, flaggedItemCountByCategory | An object of numbers, keyed by item type or flag category |
subscription | An object with billing dates, status and seat count. See below |
Monthly row keys
Each row has a month and one figure. The figure's key depends on the metric:
| Key | Metrics |
|---|---|
value | memberCount, padletCount, postCount, commentCount, peerInteractionCount |
count | newMemberCount, reactionCount |
visitors | visitorCount |
subscription
subscription- Dates and status show the current billing state, whatever the range.
- Seat count is as of the last day of the range, or today if the range ends in the future.
- Seat count is
nullif the range covers more than one billing term, or goes back further than the billing history.
Meta
| Field | Notes |
|---|---|
status | ready: every metric was returned. pending: at least one is still being computed. partial: nothing is pending, but at least one metric failed |
dateRange | The date range used. The default range does not start on the first of a month |
pending | Metrics still being computed, on a 202 |
retryAfter | Seconds to wait before sending the request again. Same as the Retry-After header |
errors | Metrics that failed. They are missing from data, not returned as zero |
A partial response returns 200, not a 5xx. If every metric failed, metrics is empty. Always check meta.status before reading data.
Errors
| Code | Meaning |
|---|---|
400 | Unknown metric, invalid property value, bad or too-long date range, duplicate metric, more than 50 queries, or malformed JSON (BAD_JSON) |
401 | API key missing or revoked |
404 | Organization not found, not enrolled, or your key has no analytics access to it. All three look the same |
406 | Unsupported Accept header. Send application/vnd.api+json or leave it out |
415 | Unsupported Content-Type. Send application/json. Some clients send form encoding by default |
429 | More than 60 requests in an hour for this API key and organization. Polls count too. Retry-After says how many seconds to wait |
Example
curl -X POST https://api.padlet.dev/v1/organizations/$ORG_ID/analytics \
-H "X-API-KEY: $PADLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"metrics": [
{ "name": "padletCount" },
{ "name": "memberCount", "status": "active", "userType": ["teacher", "admin", "owner"] }
],
"dimensions": ["month"]
}'{
"data": {
"id": "wksp_1oRLGeKoGK9DPvOw",
"type": "organizationAnalytics",
"attributes": {
"metrics": [
{ "name": "padletCount", "properties": { "userType": "all" }, "data": [{ "month": "2026-08", "value": 1 }] },
{
"name": "memberCount",
"properties": { "status": "active", "userType": ["teacher", "admin", "owner"] },
"data": [{ "month": "2026-08", "value": 1 }]
}
]
}
},
"meta": { "status": "ready", "dateRange": { "from": "2026-08-03", "to": "2027-08-03" } }
}