--- title: Organizations API description: Create and manage organizations and their members icon: users --- # Organizations API Manage organizations, members, and roles for collaborative repository management. ## Overview Organizations allow multiple users to collaborate on repositories. Members can have different roles: - **visitor**: Read-only access - **member**: Can create repositories, read all org repos - **admin**: Can manage members and settings - **super-admin**: Full control (creator role) --- ## Endpoints ### Create Organization Create a new organization with default quotas. **Endpoint:** `POST /api/organizations/create` **Request Body:** ```json { "name": "myorg", "description": "Machine Learning Research" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `name` | string | Yes | Organization name (alphanumeric, hyphens, underscores) | | `description` | string | No | Organization description | **Authentication:** Required **Response:** ```json { "success": true, "name": "myorg" } ``` **Notes:** - Creator is automatically added as `super-admin` - Default quotas are applied from server configuration - Organization name must not be reserved (e.g., `admin`, `api`, `models`, etc.) - Name is validated and normalized **Error Responses:** | Status | Description | |--------|-------------| | 400 | Organization name already exists or is reserved | | 401 | Authentication required | | 422 | Invalid request body | **Example:** ```python import requests response = requests.post( "http://localhost:28080/api/organizations/create", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "name": "myorg", "description": "Machine Learning Research" } ) result = response.json() print(f"Organization created: {result['name']}") ``` --- ### Get Organization Info Get basic organization information. **Endpoint:** `GET /api/organizations/{org_name}` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `org_name` | string | path | Yes | Organization name | | `fallback` | boolean | query | No | Enable fallback to external sources (default: `true`) | **Authentication:** Optional **Response:** ```json { "name": "myorg", "description": "Machine Learning Research", "created_at": "2025-01-01T00:00:00Z", "_source": "local" } ``` **Example:** ```python response = requests.get("http://localhost:28080/api/organizations/myorg") org = response.json() ``` --- ### Add Member Add a member to an organization (admin only). **Endpoint:** `POST /api/organizations/{org_name}/members` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `org_name` | string | path | Yes | Organization name | **Request Body:** ```json { "username": "alice", "role": "member" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `username` | string | Yes | Username to add | | `role` | string | Yes | Member role: `visitor`, `member`, `admin` | **Authentication:** Required (admin or super-admin) **Response:** ```json { "success": true, "message": "Member added successfully" } ``` **Error Responses:** | Status | Description | |--------|-------------| | 400 | User is already a member | | 403 | Not authorized to add members | | 404 | Organization or user not found | **Example:** ```python response = requests.post( "http://localhost:28080/api/organizations/myorg/members", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "username": "alice", "role": "member" } ) ``` --- ### Remove Member Remove a member from an organization (admin only). **Endpoint:** `DELETE /api/organizations/{org_name}/members/{username}` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `org_name` | string | path | Yes | Organization name | | `username` | string | path | Yes | Username to remove | **Authentication:** Required (admin or super-admin) **Response:** ```json { "success": true, "message": "Member removed successfully" } ``` **Error Responses:** | Status | Description | |--------|-------------| | 403 | Not authorized to remove members | | 404 | Organization, user, or membership not found | **Example:** ```python response = requests.delete( "http://localhost:28080/api/organizations/myorg/members/alice", headers={"Authorization": "Bearer YOUR_TOKEN"} ) ``` --- ### Update Member Role Change a member's role in an organization (admin only). **Endpoint:** `PUT /api/organizations/{org_name}/members/{username}` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `org_name` | string | path | Yes | Organization name | | `username` | string | path | Yes | Username to update | **Request Body:** ```json { "role": "admin" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `role` | string | Yes | New role: `visitor`, `member`, or `admin` | **Authentication:** Required (admin or super-admin) **Response:** ```json { "success": true, "message": "Member role updated successfully" } ``` **Error Responses:** | Status | Description | |--------|-------------| | 403 | Not authorized to update member roles | | 404 | Organization, user, or membership not found | **Example:** ```python # Promote member to admin response = requests.put( "http://localhost:28080/api/organizations/myorg/members/alice", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"role": "admin"} ) # Demote admin to member response = requests.put( "http://localhost:28080/api/organizations/myorg/members/bob", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"role": "member"} ) ``` --- ### List Organization Members Get list of all organization members. **Endpoint:** `GET /api/organizations/{org_name}/members` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `org_name` | string | path | Yes | Organization name | **Authentication:** Optional (public information) **Response:** ```json { "members": [ { "user": "alice", "role": "super-admin" }, { "user": "bob", "role": "admin" }, { "user": "charlie", "role": "member" } ] } ``` **Example:** ```python response = requests.get( "http://localhost:28080/api/organizations/myorg/members" ) members = response.json()["members"] for member in members: print(f"{member['user']}: {member['role']}") ``` --- ### List User Organizations Get organizations a user belongs to. **Endpoint:** `GET /api/users/{username}/orgs` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `username` | string | path | Yes | Username to query | **Authentication:** Optional (public information) **Response:** ```json { "organizations": [ { "name": "myorg", "description": "Machine Learning Research", "role": "admin" }, { "name": "anotherorg", "description": "Data Science Projects", "role": "member" } ] } ``` **Example:** ```python response = requests.get( "http://localhost:28080/api/users/alice/orgs" ) orgs = response.json()["organizations"] for org in orgs: print(f"{org['name']} ({org['role']})") ``` --- ## Role Permissions ### Visitor - View public repositories - View organization profile - No write access ### Member - All visitor permissions - Create repositories under organization - Write to organization repositories they created - View all organization repositories (public and private) ### Admin - All member permissions - Manage organization members (add, remove, update roles) - Update organization settings and avatar - Manage organization quotas - Delete organization repositories ### Super-Admin - All admin permissions - Cannot be removed by other admins - Transfer ownership capabilities - Full organization control **Note:** Only the organization creator gets `super-admin` role automatically. Admins cannot promote members to `super-admin`. --- ## Usage Examples ### Create and Set Up Organization ```python import requests BASE_URL = "http://localhost:28080" TOKEN = "YOUR_TOKEN" headers = {"Authorization": f"Bearer {TOKEN}"} # 1. Create organization response = requests.post( f"{BASE_URL}/api/organizations/create", headers=headers, json={ "name": "ml-research", "description": "Machine Learning Research Lab" } ) print(f"Created: {response.json()['name']}") # 2. Update organization settings requests.put( f"{BASE_URL}/api/organizations/ml-research/settings", headers=headers, json={ "bio": "Advancing AI through open research", "website": "https://ml-research.example.com", "social_media": { "twitter_x": "ml_research", "github": "ml-research" } } ) # 3. Upload organization logo with open("logo.png", "rb") as f: requests.post( f"{BASE_URL}/api/organizations/ml-research/avatar", headers=headers, files={"file": f} ) # 4. Add team members members = [ ("alice", "admin"), ("bob", "member"), ("charlie", "member") ] for username, role in members: requests.post( f"{BASE_URL}/api/organizations/ml-research/members", headers=headers, json={"username": username, "role": role} ) print(f"Added {username} as {role}") ``` ### Manage Organization Members ```python # List all members response = requests.get( f"{BASE_URL}/api/organizations/ml-research/members" ) members = response.json()["members"] # Find members by role admins = [m for m in members if m["role"] in ["admin", "super-admin"]] regular_members = [m for m in members if m["role"] == "member"] print(f"Admins: {len(admins)}") print(f"Members: {len(regular_members)}") # Promote member to admin requests.put( f"{BASE_URL}/api/organizations/ml-research/members/alice", headers=headers, json={"role": "admin"} ) # Remove inactive member requests.delete( f"{BASE_URL}/api/organizations/ml-research/members/bob", headers=headers ) ``` ### Check User's Organizations ```python # Get all organizations for a user response = requests.get( f"{BASE_URL}/api/users/alice/orgs" ) orgs = response.json()["organizations"] # Filter by role admin_orgs = [o for o in orgs if o["role"] in ["admin", "super-admin"]] member_orgs = [o for o in orgs if o["role"] == "member"] print(f"Alice is admin of: {[o['name'] for o in admin_orgs]}") print(f"Alice is member of: {[o['name'] for o in member_orgs]}") ``` ### Python Helper Class ```python class OrganizationManager: def __init__(self, base_url: str, token: str): self.base_url = base_url self.headers = {"Authorization": f"Bearer {token}"} def create_org(self, name: str, description: str = None): response = requests.post( f"{self.base_url}/api/organizations/create", headers=self.headers, json={"name": name, "description": description} ) response.raise_for_status() return response.json() def add_member(self, org_name: str, username: str, role: str = "member"): response = requests.post( f"{self.base_url}/api/organizations/{org_name}/members", headers=self.headers, json={"username": username, "role": role} ) response.raise_for_status() return response.json() def list_members(self, org_name: str): response = requests.get( f"{self.base_url}/api/organizations/{org_name}/members" ) response.raise_for_status() return response.json()["members"] def update_role(self, org_name: str, username: str, new_role: str): response = requests.put( f"{self.base_url}/api/organizations/{org_name}/members/{username}", headers=self.headers, json={"role": new_role} ) response.raise_for_status() return response.json() def remove_member(self, org_name: str, username: str): response = requests.delete( f"{self.base_url}/api/organizations/{org_name}/members/{username}", headers=self.headers ) response.raise_for_status() return response.json() # Usage org_mgr = OrganizationManager("http://localhost:28080", "YOUR_TOKEN") # Create and setup org_mgr.create_org("ml-team", "ML Research Team") org_mgr.add_member("ml-team", "alice", "admin") org_mgr.add_member("ml-team", "bob", "member") # List and manage members = org_mgr.list_members("ml-team") org_mgr.update_role("ml-team", "bob", "admin") org_mgr.remove_member("ml-team", "charlie") ``` --- ## JavaScript/TypeScript Example ```javascript class OrganizationAPI { constructor(baseURL, token) { this.baseURL = baseURL; this.headers = { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }; } async createOrg(name, description) { const response = await fetch(`${this.baseURL}/api/organizations/create`, { method: 'POST', headers: this.headers, body: JSON.stringify({ name, description }) }); return await response.json(); } async addMember(orgName, username, role = 'member') { const response = await fetch( `${this.baseURL}/api/organizations/${orgName}/members`, { method: 'POST', headers: this.headers, body: JSON.stringify({ username, role }) } ); return await response.json(); } async listMembers(orgName) { const response = await fetch( `${this.baseURL}/api/organizations/${orgName}/members` ); const data = await response.json(); return data.members; } async updateRole(orgName, username, newRole) { const response = await fetch( `${this.baseURL}/api/organizations/${orgName}/members/${username}`, { method: 'PUT', headers: this.headers, body: JSON.stringify({ role: newRole }) } ); return await response.json(); } async removeMember(orgName, username) { const response = await fetch( `${this.baseURL}/api/organizations/${orgName}/members/${username}`, { method: 'DELETE', headers: this.headers } ); return await response.json(); } } // Usage const orgAPI = new OrganizationAPI('http://localhost:28080', 'YOUR_TOKEN'); await orgAPI.createOrg('ml-team', 'ML Research Team'); await orgAPI.addMember('ml-team', 'alice', 'admin'); const members = await orgAPI.listMembers('ml-team'); ``` --- ## CLI Usage See [CLI Documentation](../CLI.md#organizations) for command-line interface: ```bash # Create organization kohub-cli org create myorg --description "ML Research" # Add member kohub-cli org add-member myorg alice --role member # List members kohub-cli org list-members myorg # Update role kohub-cli org update-role myorg alice --role admin # Remove member kohub-cli org remove-member myorg bob ``` --- ## Next Steps - [Invitation API](./invitations.md) - Invite users to organizations - [Quota Management API](./quota.md) - Manage organization storage quotas - [Settings API](./settings.md) - Update organization profile and avatar - [Repository API](../API.md#repositories) - Create repositories under organizations