Authentication
Every request sends one credential as a bearer token:
Authorization: Bearer <credential>Grouperly decides what each caller may see from the group’s own permissions. The API never shows more than the person or key behind it could see in Grouperly itself.
Group keys
Section titled “Group keys”A group key (gk_…) belongs to one group. A group owner makes it in Settings → Developers, and it acts as that leader. If they stop being a leader, it stops working (key_owner_not_leader).
Each key has the scopes chosen when it was made:
| Scope | Allows |
|---|---|
read |
The group, its events, members, positions, photos, and the adults on the roster. Youth appear with names, roles and tags only |
contacts:write |
Adding and changing roster entries, and circle members |
events:write |
Creating and changing events |
rsvps:write |
Answering RSVPs on someone’s behalf |
messages:announce |
Sending announcements to the group |
documents:read |
The group’s documents |
payments:read |
Payments for the group’s events |
webhooks:manage |
Registering webhooks |
youth:read |
Youth members’ birthdates and contact details |
Each endpoint’s key scope is its x-scope in the OpenAPI document, and the API reference shows it. A key without it gets 403 insufficient_scope.
Apps’ access tokens
Section titled “Apps’ access tokens”An app that people sign in to with Sign in with Grouperly calls the API with the signed-in person’s access token. It gets the token from auth.grouperly.com with resource=https://api.grouperly.com, asking for the API scopes it needs: https://api.grouperly.com/events.read and so on. Each endpoint lists its scope as x-app-scope. @grouperly/next does all of this for a Next.js app.
What the app may do in a group is what all three of these allow:
- The token’s scopes. If one is missing, the API answers
insufficient_scope. - The group’s install of the app. A leader allows the app in the group and chooses its scopes. Without that, the answer is
app_not_installedorscope_not_allowed, with a link to send a leader to. - The person’s own permission in the group. If they don’t have it, the answer is
forbidden.
The token acts as the person, so the app sees what they’d see. A parent’s app gets the roster as a parent sees it.
- Endpoints about the person (
/me…) take only an app’s token, with theme.readscope. The person grants it on a consent page the first time. - Writes, such as changing a group’s profile or positions, are for apps’ tokens only, for now.
Apps that other groups install are open to invited partners for now. Email support@grouperly.com to build one.
App secrets
Section titled “App secrets”An app calling as itself, never for a group’s data, uses its app secret (gapp_…), issued by Grouperly. Only the endpoints that say so take one. Today that’s publishing a vertical’s descriptor.
Grouperly is careful with children’s information:
- An app sees youth members only with
roster.youth.read. Without it, lists leave youth out, and counts still include them (youthCount,memberCount). Photos come without captions or tags, because those name the people in them. - A group key sees youth names, roles and tags. Their birthdates and contact details need
youth:read. Without it, those fields arenull. - Fields about youth are marked
x-sensitive: youthin the OpenAPI document. - Responses that name youth are logged.
Rate limits
Section titled “Rate limits”| Caller | Limit |
|---|---|
| A group key | 120 requests a minute, per key |
| A partner app | 120 requests a minute, per person |
| An app secret | 120 requests a minute, per app |
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit, the answer is 429 rate_limited with Retry-After.