--- title: Settings API description: Manage user, organization, and repository settings icon: settings --- # Settings API Manage settings for users, organizations, and repositories including profiles, avatars, and LFS configuration. ## User Settings ### Get Current User Info Get authenticated user information in HuggingFace-compatible format. **Endpoint:** `GET /api/whoami-v2` **Authentication:** Required **Response:** ```json { "type": "user", "id": "123", "name": "alice", "fullname": "alice", "email": "alice@example.com", "emailVerified": true, "canPay": false, "isPro": false, "orgs": [ { "name": "myorg", "fullname": "myorg", "roleInOrg": "admin" } ], "auth": { "type": "access_token", "accessToken": { "displayName": "Auto-generated token", "role": "write" } }, "site": { "name": "KohakuHub", "api": "kohakuhub", "version": "0.0.1" } } ``` **Example:** ```python import requests response = requests.get( "http://localhost:28080/api/whoami-v2", headers={"Authorization": "Bearer YOUR_TOKEN"} ) user_info = response.json() print(f"Logged in as: {user_info['name']}") ``` --- ### Get Namespace Type Determine if a namespace is a user or organization. **Endpoint:** `GET /api/users/{username}/type` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `username` | string | path | Yes | Username or organization name | | `fallback` | boolean | query | No | Enable fallback to external sources (default: `true`) | **Authentication:** Optional **Response:** ```json { "type": "user", "_source": "local" } ``` Or: ```json { "type": "org", "_source": "local" } ``` **Example:** ```python response = requests.get("http://localhost:28080/api/users/myorg/type") data = response.json() if data["type"] == "org": print("This is an organization") ``` --- ### Get User Profile Get public user profile information. **Endpoint:** `GET /api/users/{username}/profile` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `username` | string | path | Yes | Username to query | | `fallback` | boolean | query | No | Enable fallback to external sources (default: `true`) | **Authentication:** Optional **Response:** ```json { "username": "alice", "full_name": "Alice Smith", "bio": "ML Engineer", "website": "https://example.com", "social_media": { "twitter_x": "alice_ml", "github": "alice", "huggingface": "alice" }, "created_at": "2025-01-01T00:00:00Z", "_source": "local" } ``` **Example:** ```python response = requests.get("http://localhost:28080/api/users/alice/profile") profile = response.json() ``` --- ### Update User Settings Update authenticated user's settings. **Endpoint:** `PUT /api/users/{username}/settings` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `username` | string | path | Yes | Username (must match authenticated user) | **Request Body:** ```json { "email": "newemail@example.com", "full_name": "Alice Smith", "bio": "ML Engineer and researcher", "website": "https://example.com", "social_media": { "twitter_x": "alice_ml", "threads": "alice", "github": "alice", "huggingface": "alice" } } ``` **All fields are optional:** | Field | Type | Description | |-------|------|-------------| | `email` | string | Email address (triggers re-verification) | | `full_name` | string | Full display name | | `bio` | string | User biography | | `website` | string | Personal website URL | | `social_media` | object | Social media handles | **Authentication:** Required (can only update own settings) **Response:** ```json { "success": true, "message": "User settings updated successfully" } ``` **Example:** ```python response = requests.put( "http://localhost:28080/api/users/alice/settings", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "bio": "ML Engineer and researcher", "website": "https://alice.example.com" } ) ``` --- ### Manage User Avatar #### Upload Avatar **Endpoint:** `POST /api/users/{username}/avatar` **Authentication:** Required (can only upload own avatar) **Request:** Multipart form data with image file Supported formats: JPEG, PNG, WebP, GIF Maximum size: 10 MB **Processing:** - Images are resized to max 1024x1024 (maintains aspect ratio) - Center-cropped to square - Converted to JPEG (quality: 95) **Response:** ```json { "success": true, "message": "Avatar uploaded successfully", "size_bytes": 245678 } ``` #### Get Avatar **Endpoint:** `GET /api/users/{username}/avatar` **Authentication:** Optional **Response:** JPEG image with cache headers **Cache-Control:** `public, max-age=86400` (24 hours) #### Delete Avatar **Endpoint:** `DELETE /api/users/{username}/avatar` **Authentication:** Required (can only delete own avatar) **Response:** ```json { "success": true, "message": "Avatar deleted successfully" } ``` **Example:** ```python # Upload avatar with open("avatar.png", "rb") as f: response = requests.post( "http://localhost:28080/api/users/alice/avatar", headers={"Authorization": "Bearer YOUR_TOKEN"}, files={"file": f} ) # Get avatar URL avatar_url = "http://localhost:28080/api/users/alice/avatar" # Delete avatar response = requests.delete( "http://localhost:28080/api/users/alice/avatar", headers={"Authorization": "Bearer YOUR_TOKEN"} ) ``` --- ## Organization Settings ### Get Organization Profile Get public organization profile information. **Endpoint:** `GET /api/organizations/{org_name}/profile` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `org_name` | string | path | Yes | Organization name | **Authentication:** Optional **Response:** ```json { "name": "myorg", "description": "Machine Learning Research", "bio": "We build open-source ML models", "website": "https://myorg.example.com", "social_media": { "twitter_x": "myorg_ml", "github": "myorg" }, "member_count": 5, "created_at": "2025-01-01T00:00:00Z" } ``` --- ### Update Organization Settings Update organization settings (admin only). **Endpoint:** `PUT /api/organizations/{org_name}/settings` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `org_name` | string | path | Yes | Organization name | **Request Body:** ```json { "description": "Machine Learning Research", "bio": "We build open-source ML models", "website": "https://myorg.example.com", "social_media": { "twitter_x": "myorg_ml", "threads": "myorg", "github": "myorg", "huggingface": "myorg" } } ``` **All fields are optional:** | Field | Type | Description | |-------|------|-------------| | `description` | string | Organization description | | `bio` | string | Organization biography | | `website` | string | Organization website URL | | `social_media` | object | Social media handles | **Authentication:** Required (admin or super-admin role) **Response:** ```json { "success": true, "message": "Organization settings updated successfully" } ``` **Example:** ```python response = requests.put( "http://localhost:28080/api/organizations/myorg/settings", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "description": "Machine Learning Research", "website": "https://myorg.example.com" } ) ``` --- ### Manage Organization Avatar #### Upload Avatar **Endpoint:** `POST /api/organizations/{org_name}/avatar` **Authentication:** Required (admin or super-admin) **Request:** Multipart form data with image file Same processing as user avatars (1024x1024, center-cropped, JPEG). **Response:** ```json { "success": true, "message": "Avatar uploaded successfully", "size_bytes": 245678 } ``` #### Get Avatar **Endpoint:** `GET /api/organizations/{org_name}/avatar` **Authentication:** Optional **Response:** JPEG image with cache headers #### Delete Avatar **Endpoint:** `DELETE /api/organizations/{org_name}/avatar` **Authentication:** Required (admin or super-admin) **Response:** ```json { "success": true, "message": "Avatar deleted successfully" } ``` **Example:** ```python # Upload organization avatar with open("org-logo.png", "rb") as f: response = requests.post( "http://localhost:28080/api/organizations/myorg/avatar", headers={"Authorization": "Bearer YOUR_TOKEN"}, files={"file": f} ) ``` --- ## Repository Settings ### Update Repository Settings Update repository configuration including visibility and LFS settings. **Endpoint:** `PUT /api/{repo_type}s/{namespace}/{name}/settings` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `repo_type` | string | path | Yes | Repository type: `model`, `dataset`, or `space` | | `namespace` | string | path | Yes | Repository namespace | | `name` | string | path | Yes | Repository name | **Request Body:** ```json { "private": false, "lfs_threshold_bytes": 10000000, "lfs_keep_versions": 10, "lfs_suffix_rules": [".safetensors", ".bin", ".gguf"] } ``` **All fields are optional:** | Field | Type | Description | Constraints | |-------|------|-------------|-------------| | `private` | boolean | Repository visibility | Checks quota before changing | | `lfs_threshold_bytes` | integer | Size threshold for LFS (bytes) | Min: 1,000,000 (1 MB), null = server default | | `lfs_keep_versions` | integer | Number of LFS versions to keep | Min: 2, null = server default | | `lfs_suffix_rules` | array[string] | File extensions to always use LFS | Must start with '.', null = no custom rules | **Note:** All size values use **decimal units** (1 MB = 1,000,000 bytes, not 1,048,576). **Authentication:** Required (write permission) **Response:** ```json { "success": true, "message": "Repository settings updated successfully" } ``` **Error Responses:** | Status | Description | |--------|-------------| | 400 | Invalid settings or quota exceeded | | 403 | Not authorized | | 404 | Repository not found | **Example:** ```python # Update repository visibility and LFS settings response = requests.put( "http://localhost:28080/api/models/myorg/mymodel/settings", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={ "private": False, "lfs_threshold_bytes": 10000000, # 10 MB "lfs_keep_versions": 10, "lfs_suffix_rules": [".safetensors", ".bin", ".gguf"] } ) # Make repository private response = requests.put( "http://localhost:28080/api/models/myorg/mymodel/settings", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"private": True} ) # Reset LFS threshold to server default response = requests.put( "http://localhost:28080/api/models/myorg/mymodel/settings", headers={"Authorization": "Bearer YOUR_TOKEN"}, json={"lfs_threshold_bytes": None} ) ``` --- ### Get Repository LFS Settings Get repository LFS configuration with both configured and effective values. **Endpoint:** `GET /api/{repo_type}s/{namespace}/{name}/settings/lfs` **Parameters:** | Parameter | Type | Location | Required | Description | |-----------|------|----------|----------|-------------| | `repo_type` | string | path | Yes | Repository type: `model`, `dataset`, or `space` | | `namespace` | string | path | Yes | Repository namespace | | `name` | string | path | Yes | Repository name | **Authentication:** Required (write permission) **Response:** ```json { "lfs_threshold_bytes": 10000000, "lfs_keep_versions": 10, "lfs_suffix_rules": [".safetensors", ".bin"], "lfs_threshold_bytes_effective": 10000000, "lfs_threshold_bytes_source": "repository", "lfs_keep_versions_effective": 10, "lfs_keep_versions_source": "repository", "lfs_suffix_rules_effective": [ ".safetensors", ".bin", ".pt", ".pth", ".ckpt", ".onnx", ".pb", ".h5", ".tflite", ".gguf", ".ggml", ".msgpack", ".zip", ".tar", ".gz", ".bz2", ".xz", ".7z", ".rar", ".npy", ".npz", ".arrow", ".parquet", ".mp4", ".avi", ".mkv", ".mov", ".wav", ".mp3", ".flac", ".tiff", ".tif" ], "lfs_suffix_rules_source": "merged", "server_defaults": { "lfs_threshold_bytes": 5000000, "lfs_keep_versions": 5, "lfs_suffix_rules_default": [ ".safetensors", ".bin", ".pt", ".pth", ".ckpt", ".onnx", ".pb", ".h5", ".tflite", ".gguf", ".ggml", ".msgpack", ".zip", ".tar", ".gz", ".bz2", ".xz", ".7z", ".rar", ".npy", ".npz", ".arrow", ".parquet", ".mp4", ".avi", ".mkv", ".mov", ".wav", ".mp3", ".flac", ".tiff", ".tif" ] } } ``` **Field Descriptions:** - **Configured values** (null = using server default): - `lfs_threshold_bytes`: Repository-specific threshold - `lfs_keep_versions`: Repository-specific keep versions - `lfs_suffix_rules`: Repository-specific custom suffix rules - **Effective values** (resolved with server defaults): - `*_effective`: Actual values being used - `*_source`: Where the value comes from (`repository` or `server_default` or `merged`) - **Server defaults** (for reference): - Global default values from configuration - 32 built-in suffix rules for ML models, archives, and media files **Important Notes:** 1. **Suffix rule merging**: Repository suffix rules are **ADDED TO** (not replacing) server defaults 2. **Server default suffixes**: Files with these extensions ALWAYS use LFS, even if size < threshold 3. **Size units**: All sizes use decimal units (1 MB = 1,000,000 bytes) **Example:** ```python response = requests.get( "http://localhost:28080/api/models/myorg/mymodel/settings/lfs", headers={"Authorization": "Bearer YOUR_TOKEN"} ) lfs_settings = response.json() print(f"Threshold: {lfs_settings['lfs_threshold_bytes_effective']} bytes") print(f"Keep versions: {lfs_settings['lfs_keep_versions_effective']}") print(f"Custom suffixes: {lfs_settings['lfs_suffix_rules']}") print(f"Total suffixes (with defaults): {len(lfs_settings['lfs_suffix_rules_effective'])}") ``` --- ## Server Default LFS Suffix Rules KohakuHub includes **32 server-wide default suffix rules** that always use LFS: **ML Model Formats (12):** `.safetensors`, `.bin`, `.pt`, `.pth`, `.ckpt`, `.onnx`, `.pb`, `.h5`, `.tflite`, `.gguf`, `.ggml`, `.msgpack` **Compressed Archives (9):** `.zip`, `.tar`, `.gz`, `.bz2`, `.xz`, `.7z`, `.rar` **Data Files (4):** `.npy`, `.npz`, `.arrow`, `.parquet` **Media Files (5):** `.mp4`, `.avi`, `.mkv`, `.mov`, `.wav`, `.mp3`, `.flac` **Large Images (2):** `.tiff`, `.tif` These rules apply to ALL repositories automatically. Repository-specific suffix rules ADD to these defaults. --- ## Usage Examples ### Complete User Profile Update ```python import requests BASE_URL = "http://localhost:28080" TOKEN = "YOUR_TOKEN" headers = {"Authorization": f"Bearer {TOKEN}"} # Update profile requests.put( f"{BASE_URL}/api/users/alice/settings", headers=headers, json={ "full_name": "Alice Smith", "bio": "ML Engineer specializing in NLP", "website": "https://alice.example.com", "social_media": { "twitter_x": "alice_ml", "github": "alice", "huggingface": "alice" } } ) # Upload avatar with open("avatar.jpg", "rb") as f: requests.post( f"{BASE_URL}/api/users/alice/avatar", headers=headers, files={"file": f} ) ``` ### Repository LFS Configuration ```python # Configure repository to always use LFS for GGUF files requests.put( f"{BASE_URL}/api/models/myorg/mymodel/settings", headers=headers, json={ "lfs_threshold_bytes": 10000000, # 10 MB "lfs_suffix_rules": [".gguf", ".ggml"] # Added to 32 server defaults } ) # Check effective settings response = requests.get( f"{BASE_URL}/api/models/myorg/mymodel/settings/lfs", headers=headers ) settings = response.json() # All .safetensors files will use LFS (server default) # All .gguf files will use LFS (custom rule) # Files > 10 MB will use LFS (threshold) ``` --- ## Next Steps - [Organization Management API](./organizations.md) - Create and manage organizations - [Quota Management API](./quota.md) - Manage storage quotas - [Repository API](../API.md#repositories) - Create and manage repositories - [CLI Settings Commands](../CLI.md#settings) - Manage settings via CLI