Files
KohakuHub/docs/api/settings.md
2025-10-24 18:45:55 +08:00

16 KiB

title, description, icon
title description icon
Settings API Manage user, organization, and repository settings 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:

{
  "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:

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:

{
  "type": "user",
  "_source": "local"
}

Or:

{
  "type": "org",
  "_source": "local"
}

Example:

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:

{
  "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:

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:

{
  "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:

{
  "success": true,
  "message": "User settings updated successfully"
}

Example:

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:

{
  "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:

{
  "success": true,
  "message": "Avatar deleted successfully"
}

Example:

# 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:

{
  "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:

{
  "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:

{
  "success": true,
  "message": "Organization settings updated successfully"
}

Example:

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:

{
  "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:

{
  "success": true,
  "message": "Avatar deleted successfully"
}

Example:

# 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:

{
  "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:

{
  "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:

# 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:

{
  "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:

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

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

# 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