A key carries two independent kinds of permission, and a request must clear both.
These are the ones in use across the API today:
attendance:readattendance:writeevents:readevents:writelodging:readmembers:readmembers:writeorg:readregistrations:readregistrations:writesync:readsync:writeunits:readunits:writeAll three are off by default. Without them a key sees names, roles, and clubs — the roster shape, and nothing personal.
| Class | Unlocks |
|---|---|
data:pii | email, phone, date of birth, gender, username |
data:health | dietary needs (which carry allergies) |
data:safeguarding | background-check status |
Some fields are never exposed at any class: password hashes, authentication ids, and session validity.
A field outside your classes is left out of the object entirely, and the class is listed in redacted_classes. In CSV the column itself is missing. An empty dietary_needs would say “this child has no allergies”; an absent one says “you may not see allergies”. Those are very different claims.
Sending a field outside your classes is a 403 that names the field. We never accept a write and silently drop part of it — an integration that believes it recorded a birthdate and didn’t is worse than one that got an error.
data:safeguarding with members:read can read background-check status but not change it. members:write without the class can edit a member but not that field.