3DKenji

Self-hosted knowledge keeper for 3D printing projects

View the Project on GitHub bodybybuddha/3DKenji

API Reference

Complete documentation of all 3DKenji REST API endpoints.

Contents

Base URL

http://localhost:8000/api/v1

Authentication

All protected endpoints require Authorization header with JWT bearer token:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Tokens are obtained from the authentication endpoints and expire after 24 hours.

Response Format

All responses are JSON with consistent structure:

Success (2xx):

{
  "id": 1,
  "title": "Project Name",
  ...
}

Error (4xx/5xx):

{
  "detail": "Error message describing what went wrong"
}

Authentication Endpoints

Register User

Create a new user account and receive JWT token.

Request:

POST /auth/register
Content-Type: application/json

Body:

{
  "username": "alice",
  "nickname": "alice-prints",
  "email": "alice@example.com",
  "password": "SecurePassword123!",
  "display_name": "Alice Smith"
}

Parameters:

Response (201):

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Errors:


Login

Authenticate with username and password.

Request:

POST /auth/login
Content-Type: application/json

Body:

{
  "username": "alice",
  "password": "SecurePassword123!"
}

Response (200):

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Errors:


Change Password

Update user password (requires authentication).

Request:

POST /auth/password-change
Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "old_password": "SecurePassword123!",
  "new_password": "NewSecurePassword456!"
}

Response (200):

{
  "message": "Password changed successfully"
}

Errors:

OAuth / OIDC Endpoints

These endpoints enable external OIDC authentication and account linking. Replace {provider} with your configured provider slug (default: oidc). OAuth configuration is now stored in the database through the admin settings screen. See docs/oauth-setup.md for operator setup and examples.

Admin OAuth Configuration


Projects Endpoints

Access Model

Create Project

Create a new project (requires authentication).

Request:

POST /projects
Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "title": "Benchy Calibration",
  "description": "Printer calibration prints",
  "visibility": "private"
}

Parameters:

Response (201):

{
  "id": "a5e4420a-3e22-41c3-a219-0bd9d8b7ab07",
  "title": "Benchy Calibration",
  "slug": "benchy-calibration",
  "category": "Uncategorized",
  "visibility": "private",
  "directory_path": "Projects/alice-prints/benchy-calibration",
  "owner_id": "user_123",
  "created_at": "2026-02-21T10:30:45Z",
  "updated_at": "2026-02-21T10:30:45Z"
}

Errors:


List Projects

Get all projects accessible to the authenticated user (owned + collaborator + public).

Request:

GET /projects?skip=0&limit=10
Authorization: Bearer <token>

Query Parameters:

Response (200):

{
  "items": [
    {
      "id": "project_123",
      "title": "Benchy Calibration",
      "owner_id": "user_123",
      "slug": "benchy-calibration",
      "category": "Calibration",
      "visibility": "private",
      "directory_path": "/data/storage/Projects/alice/benchy-calibration",
      "disk_size_bytes": 24576,
      "is_archived": false,
      "created_at": "2026-02-21T10:30:45Z",
      "updated_at": "2026-02-21T10:30:45Z"
    }
  ],
  "total": 1,
  "skip": 0,
  "limit": 10
}

Errors:


Get Project

Get details of a specific project.

Request:

GET /projects/{id}
Authorization: Bearer <token>

Parameters:

Response (200):

{
  "id": 1,
  "title": "Benchy Calibration",
  "description": "Printer calibration prints",
  "owner_id": "user_123",
  "created_at": "2026-02-21T10:30:45Z",
  "updated_at": "2026-02-21T10:30:45Z"
}

Errors:


Update Project

Update project title/category/visibility.

Request:

PATCH /projects/{id}
Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "title": "Updated Project Name",
  "custom_metadata": {
    "category": "Calibration",
    "visibility": "public"
  }
}

Parameters:

Response (200):

{
  "id": 1,
  "title": "Updated Project Name",
  "description": "Updated description",
  "owner_id": "user_123",
  "created_at": "2026-02-21T10:30:45Z",
  "updated_at": "2026-02-21T10:30:46Z"
}

Errors:


List Public Projects

List publicly visible projects without authentication.

Request:

GET /projects/public?skip=0&limit=100

Response (200):

{
  "items": [
    {
      "id": "a5e4420a-3e22-41c3-a219-0bd9d8b7ab07",
      "title": "Benchy Calibration",
      "slug": "benchy-calibration",
      "visibility": "public"
    }
  ],
  "total": 1,
  "skip": 0,
  "limit": 100
}

Get Public Project

Read one publicly visible project without authentication.

Request:

GET /projects/public/{project_id}

Errors:


Collaboration Endpoints

All collaboration management endpoints below require owner permissions on the target project.

List Collaborators

GET /projects/{project_id}/collaborators
Authorization: Bearer <token>

Add or Update Collaborator

POST /projects/{project_id}/collaborators
Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "user_id": "b84a2750-c27f-43e4-a735-a09f8f4c5c5f",
  "role": "editor"
}

Remove Collaborator

DELETE /projects/{project_id}/collaborators/{user_id}
Authorization: Bearer <token>

Invitation Endpoints

Create Invitation

POST /projects/{project_id}/invitations
Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "email": "collaborator@example.com",
  "role": "viewer",
  "expires_in_days": 7
}

Returns a one-time invitation token and invitation metadata.

List Project Invitations

GET /projects/{project_id}/invitations?include_inactive=false
Authorization: Bearer <token>

Update Invitation Role

PATCH /projects/{project_id}/invitations/{invitation_id}
Authorization: Bearer <token>
Content-Type: application/json

Revoke Invitation

DELETE /projects/{project_id}/invitations/{invitation_id}
Authorization: Bearer <token>

Accept Invitation by Token

POST /projects/invitations/{token}/accept
Authorization: Bearer <token>

Accept Invitation by ID

POST /projects/invitations/id/{invitation_id}/accept
Authorization: Bearer <token>

List My Pending Invitations

GET /projects/invitations/mine
Authorization: Bearer <token>

Pending invitations are matched by authenticated user email. Acceptance fails if invitation email does not match the current user.


Delete Project

Delete a project and its associated metadata.

Request:

DELETE /projects/{id}
Authorization: Bearer <token>

Parameters:

Response (204): No content

Errors:


Project Files Endpoints

List Project Files

List files in a project directory. This powers the Project Files browser in the web UI.

Request:

GET /projects/{project_id}/files?path=models
Authorization: Bearer <token>

Parameters:

Response (200):

{
  "project_id": 1,
  "path": "models",
  "parent_path": "",
  "items": [
    {
      "name": "benchy.stl",
      "relative_path": "models/benchy.stl",
      "is_dir": false,
      "size_bytes": 1048576,
      "size": "1.0 MB",
      "extension": "stl",
      "is_editable": false,
      "viewer": {
        "viewer_id": "stl-viewer",
        "name": "STL Basic Preview",
        "plugin_id": "stl-viewer-plugin",
        "has_js": true
      }
    }
  ]
}

Errors:


Upload Project File

Upload a file into the selected project directory.

Request:

POST /projects/{project_id}/files/upload
Authorization: Bearer <token>
Content-Type: multipart/form-data

Parameters:

Response (201):

{
  "project_id": 1,
  "path": "models",
  "relative_path": "models/benchy.stl",
  "name": "benchy.stl",
  "size_bytes": 1048576,
  "size": "1.0 MB"
}

Errors:


Preview Project File

Preview a file in JSON or HTML form. Text formats return inline preview text, and viewer-enabled formats can render through plugin-provided preview code.

Request:

GET /projects/{project_id}/files/preview?path=models/benchy.stl
Authorization: Bearer <token>

Parameters:

Response (200):

{
  "path": "models/benchy.stl",
  "extension": "stl",
  "size_bytes": 1048576,
  "viewer": {
    "viewer_id": "stl-viewer",
    "name": "STL Basic Preview",
    "plugin_id": "stl-viewer-plugin",
    "has_js": true
  },
  "preview_mode": "binary",
  "preview_text": null
}

Errors:


Download Project File

Download a file from a project.

Request:

GET /projects/{project_id}/files/download?path=models/benchy.stl
Authorization: Bearer <token>

Parameters:

Response (200): Binary file download

Errors:


API Keys Endpoints

Create API Key

Generate a new API key for programmatic access.

Request:

POST /keys
Authorization: Bearer <token>
Content-Type: application/json

Body:

{
  "name": "CI/CD Pipeline"
}

Parameters:

Response (201):

{
  "id": "key_abc123",
  "name": "CI/CD Pipeline",
  "created_at": "2026-02-21T10:30:45Z",
  "secret": "sk_live_abc123def456ghi789jkl..."
}

Important: The secret is only shown once. Store it securely.

Errors:


List API Keys

Get all API keys for authenticated user (secrets not shown).

Request:

GET /keys
Authorization: Bearer <token>

Response (200):

{
  "items": [
    {
      "id": "key_abc123",
      "name": "CI/CD Pipeline",
      "created_at": "2026-02-21T10:30:45Z"
    }
  ],
  "total": 1
}

Errors:


Revoke API Key

Delete and disable an API key immediately.

Request:

DELETE /keys/{id}
Authorization: Bearer <token>

Parameters:

Response (204): No content

Errors:


Health & Status Endpoints

Full System Health

Get complete health status of all components.

Request:

GET /health

Response (200):

{
  "status": "ok",
  "timestamp": "2026-02-21T10:30:45.123Z",
  "components": [
    {
      "name": "storage_backend",
      "status": "ok",
      "timestamp": "2026-02-21T10:30:45.123Z"
    },
    {
      "name": "database",
      "status": "ok",
      "timestamp": "2026-02-21T10:30:45.123Z"
    }
  ]
}

Readiness Probe

Check if service is ready to accept requests (Kubernetes).

Request:

GET /health/ready

Response:


Liveness Probe

Check if service process is alive (Kubernetes).

Request:

GET /health/live

Response:


Status Codes Reference

Code Meaning
200 OK – Request succeeded
201 Created – Resource created successfully
204 No Content – Successful, no response body
400 Bad Request – Invalid parameters
401 Unauthorized – Missing or invalid token
403 Forbidden – Permission denied
404 Not Found – Resource not found
500 Internal Server Error – Server error
503 Service Unavailable – Service not ready

Rate Limiting

Currently no rate limiting is implemented. Production deployments should add rate limiting via reverse proxy (nginx, CloudFlare, etc.).

Examples

cURL Examples

See getting-started.md for common cURL examples.

Python Example

import requests

BASE_URL = "http://localhost:8000/api/v1"
TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# List projects
response = requests.get(
    f"{BASE_URL}/projects",
    headers={"Authorization": f"Bearer {TOKEN}"}
)
projects = response.json()

JavaScript/Fetch Example

const BASE_URL = "http://localhost:8000/api/v1";
const TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";

// List projects
const response = await fetch(`${BASE_URL}/projects`, {
  headers: {
    "Authorization": `Bearer ${TOKEN}`
  }
});
const projects = await response.json();