Overview
Organization routes pull data from the normalized users, organizations, and organization_memberships tables. Every route requires authentication via getRequestSession().
GET /api/organizations
File: app/api/organizations/route.ts
Lists all organizations the authenticated user belongs to, enriched with installation status.
Response
{
"organizations": [
{
"id": 67890,
"login": "my-org",
"name": "My Organization",
"avatarUrl": "https://avatars.githubusercontent.com/u/67890",
"viewerCanAdminister": true,
"hasAppInstalled": true,
"installationId": 12345,
"repositoryCount": null,
"repositorySelection": null,
"suspendedAt": null
}
]
}Fields
| Field | Type | Description |
|---|---|---|
id | number | GitHub organization ID |
login | string | Organization slug |
name | string | null | Display name |
avatarUrl | string | null | Avatar URL |
viewerCanAdminister | boolean | True if you’re an admin |
hasAppInstalled | boolean | Whether the GitHub App is installed |
installationId | number | null | Installation ID if installed |
repositoryCount | number | null | Cached repo count (null if not fetched) |
repositorySelection | "all" | "selected" | null | Repository access scope |
suspendedAt | string | null | ISO timestamp if suspended |
Error responses
| Status | Condition |
|---|---|
401 | Not authenticated |
Frontend hook
import { useOrganizationsQuery } from '@/hooks/queries';
const { data: organizations, isLoading } = useOrganizationsQuery();GET /api/organizations/[login]
File: app/api/organizations/[login]/route.ts
Get detailed information about a specific organization, including installation metadata.
Parameters
| Param | Type | Description |
|---|---|---|
login | string | Organization slug (URL param) |
Response
{
"organization": {
"id": 67890,
"login": "my-org",
"name": "My Organization",
"avatarUrl": "https://avatars.githubusercontent.com/u/67890",
"viewerCanAdminister": true,
"hasAppInstalled": true,
"installationId": 12345,
"repositoryCount": 42,
"repositorySelection": "all",
"suspendedAt": null
}
}If the organization has an installation, the route queries InstallationService.getInstallationForOrg() to fetch cached repository count, selection, and suspension status from github_installations.
Error responses
| Status | Condition |
|---|---|
400 | Missing organization login |
401 | Not authenticated |
404 | Organization not found or user is not a member |
Frontend hook
import { useOrganizationDetailQuery } from '@/hooks/queries';
const { data: org, isLoading } = useOrganizationDetailQuery('my-org');POST /api/organizations/[login]/mass-invite
File: app/api/organizations/[login]/mass-invite/route.ts
Bulk-invite GitHub users to an organization. Requires admin access.
Request body
{
"userLogins": ["alice", "bob", "charlie"]
}| Field | Type | Constraints |
|---|---|---|
userLogins | string[] | 1–50 usernames. Duplicates are deduplicated. |
Response
{
"succeeded": ["alice", "bob"],
"failed": [{ "login": "charlie", "error": "Not Found" }]
}Authorization
You must be an admin (viewerCanAdminister = true in organization_memberships).
Implementation
- Validates you’re an admin of the target org
- Resolves each username to a GitHub user ID via
users.getByUsername - Sends organization invitations via
orgs.createInvitation - Returns per-user results
Error responses
| Status | Condition |
|---|---|
400 | Missing/invalid request body |
401 | Not authenticated |
403 | Not an organization admin |
413 | More than 50 users requested |
500 | GitHub API error |
For a deep dive into the mass-invite pipeline (concurrency, GraphQL + REST, per-user error handling), see Mass Invite API.
Related
- Mass Invite API — validation pipeline, edge cases, rate limiting
- Auth Routes — session authentication
- Database Schema —
organizations,organization_membershipstables