API reference
Every endpoint, request schema, response schema, and parameter — auto-generated from the running Django backend via drf-spectacular.
The sidebar on the left organizes endpoints by tag (which usually maps to a Django app — compliance, elections, members, etc.).
Try it out
The endpoint pages include an interactive try-it-out panel. To use it:
- Sign into your GreekManage instance in another tab to obtain an
access_tokencookie - Open the endpoint page here
- Fill in path / query parameters
- Click Send API Request
Responses, headers, and timing show inline.
Authentication
All endpoints (except a small set listed under auth and public) require a JWT.
Web (cookie)
Cookie: access_token=<jwt>
The cookie is set automatically by POST /api/auth/login/. It's HttpOnly, Secure, SameSite=Lax.
Mobile / scripts (header)
Authorization: Bearer <jwt>
Use this when calling from outside a browser or from the iOS / Android app.
Tenant scoping
Every authenticated request is automatically scoped to the user's organization via OrganizationContextMiddleware. You don't need to pass the org ID on most endpoints — it's derived from your token.
Exceptions:
- Platform admins acting on behalf of a tenant: pass
X-Organization-Id: <uuid> - Public endpoints (PNM apply, public donate): explicitly take an org slug or campaign slug in the URL
Error format
{
"detail": "Human-readable error",
"code": "machine_readable_code",
"errors": {
"field_name": ["Field-specific error"]
}
}
| Status | Meaning |
|---|---|
400 | Validation error — see errors for field-specific messages |
401 | Not authenticated |
403 | Authenticated but not authorized (wrong role / out of scope) |
404 | Not found — sometimes returned instead of 403 to avoid revealing existence |
409 | Conflict (duplicate, optimistic lock fail) |
422 | Unprocessable entity — request was valid JSON but semantically wrong |
429 | Throttled — see Retry-After header |
500 | Server error — please report |
Pagination
Most list endpoints use page-number pagination:
GET /api/chapters/?page=2&page_size=50
{
"count": 142,
"next": "...?page=3",
"previous": "...?page=1",
"results": [ ... ]
}
Default page_size: 25. Maximum: 100.
Filtering + ordering
Where supported, filter and order via query params:
GET /api/members/?status=undergraduate&ordering=-joined_at
The endpoint detail pages list which params each endpoint accepts.
Versioning
The API version is exposed in the OpenAPI schema (info.version). Breaking changes bump the major version with at least 90 days of notice and an overlap period when both versions run.
Today the schema shows 0.27.0 (lagging the platform version 0.57.0) — info.version tracks the API contract version, not the platform release version.
Throttling
| Scope | Anonymous | Authenticated |
|---|---|---|
| Default | 200/day | 2000/day |
auth (login, refresh) | 10/minute | – |
sso | 20/minute | – |
account_request | 3/hour | – |
password_reset | 5/hour | – |
pnm_submit_ip | 5/hour | – |
Hit 429 and back off per Retry-After.
Webhook events (out of scope today)
Outbound webhooks for events (member added, dues paid, election closed, etc.) are on the roadmap. For now, integrations poll relevant endpoints.
Generating the schema yourself
docker compose exec backend python manage.py spectacular \
--file ../docs-site/openapi/greekmanage.yaml \
--format openapi
Then regenerate the API MDX in this site:
cd docs-site
npm run docusaurus gen-api-docs all
The new endpoints appear in the sidebar after a rebuild.
Reading the endpoint pages
Each endpoint page in the sidebar has:
- Path + method at the top
- Description pulled from the docstring on the view
- Path / query parameters with type, required flag, description
- Request body schema with example
- Response schemas by status code
- Try it out panel
- Code samples in curl, Python, Node.js, TypeScript
Tags
Endpoints are grouped by tag in the sidebar. Click a tag to expand the list. Tags map roughly to Django apps:
accounts— user, password, profileauth— login, logout, SSOorganizations,chapters,regions,membershipscompliance— requirements, submissions, alertselections— elections, ballots, resultsfinances— invoices, payments, dues settingsforums— engage / communitylearning— courses, enrollments, certificatesfoundation— campaigns, donations, donorsalumni— directory, mentors, career boardmembers— profiles, skills, recognitionsmessaging— conversations, messagesnotifications— list, prefsai-services— chat, config, embeddingsplatform— tenant management (platform admins only)backups— full DB / org export
Help
- Endpoint missing? Most likely an authentication / permission issue — check the request comes with a valid JWT and the user has scope for the resource.
- Field looks wrong? The schema is generated from serializers; if a field renders with the wrong type, it's a serializer issue — open an issue.
- Want a new endpoint? Open a feature request issue in the repo.