Skip to content

Notebook Sharing

The sharing system allows admins to create invite links for notebooks. Users who redeem an invite receive chat_only access to the notebook. Admins can manage invites and revoke access.

Base paths: /api/notebooks/{notebook_id} and /api/invite


POST /api/notebooks/{notebook_id}/invites

Create a new invite link for a notebook. The invite code is auto-generated and returned in the response.

Auth: Admin

Headers:

Header Value
Authorization Bearer <token>
Content-Type application/json

Body:

{
  "expires_at": "2026-03-25T00:00:00Z"
}
Field Type Required Default Description
expires_at string (ISO 8601) No null Expiration date (null = never expires)

Status: 201 Created

{
  "success": true,
  "data": {
    "invite_code": "abc123def456",
    "notebook_id": "a1b2c3d4-...",
    "created_by": "user_abc",
    "expires_at": "2026-03-25T00:00:00Z",
    "invite_url": "http://localhost:8000/invite/abc123def456",
    "created_at": "2026-02-25T15:00:00Z"
  }
}
Code Cause
401 Invalid or missing token
403 Non-admin user
curl -X POST http://localhost:8000/api/notebooks/$NOTEBOOK_ID/invites \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expires_at": "2026-03-25T00:00:00Z"}'
import httpx

notebook_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
response = httpx.post(
    f"http://localhost:8000/api/notebooks/{notebook_id}/invites",
    headers={"Authorization": f"Bearer {token}"},
    json={"expires_at": "2026-03-25T00:00:00Z"},
)
invite = response.json()["data"]
print(f"Invite URL: {invite['invite_url']}")

GET /api/notebooks/{notebook_id}/invites

List all invites for a notebook.

Auth: Admin

Headers:

Header Value
Authorization Bearer <token>

Status: 200 OK

{
  "success": true,
  "data": [
    {
      "invite_code": "abc123def456",
      "notebook_id": "a1b2c3d4-...",
      "created_by": "user_abc",
      "expires_at": "2026-03-25T00:00:00Z",
      "created_at": "2026-02-25T15:00:00Z",
      "redeemed_count": 3
    }
  ]
}
Code Cause
401 Invalid or missing token
403 Non-admin user
curl http://localhost:8000/api/notebooks/$NOTEBOOK_ID/invites \
  -H "Authorization: Bearer $TOKEN"
import httpx

notebook_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
response = httpx.get(
    f"http://localhost:8000/api/notebooks/{notebook_id}/invites",
    headers={"Authorization": f"Bearer {token}"},
)
invites = response.json()["data"]
for inv in invites:
    print(f"  {inv['invite_code']}: redeemed {inv.get('redeemed_count', 0)} times")

DELETE /api/notebooks/{notebook_id}/invites/{invite_code}

Revoke an invite link. Existing access granted by this invite is NOT affected.

Auth: Admin

Headers:

Header Value
Authorization Bearer <token>

Status: 200 OK

{
  "success": true,
  "data": {
    "revoked": true
  }
}
Code Cause
401 Invalid or missing token
403 Non-admin user
404 Invite not found
curl -X DELETE http://localhost:8000/api/notebooks/$NOTEBOOK_ID/invites/abc123def456 \
  -H "Authorization: Bearer $TOKEN"
import httpx

response = httpx.delete(
    f"http://localhost:8000/api/notebooks/{notebook_id}/invites/{invite_code}",
    headers={"Authorization": f"Bearer {token}"},
)
print(response.json()["data"])

GET /api/notebooks/{notebook_id}/access

List all users with access to a notebook (both admins and invited users).

Auth: Admin

Headers:

Header Value
Authorization Bearer <token>

Status: 200 OK

{
  "success": true,
  "data": [
    {
      "user_id": "user_def456",
      "notebook_id": "a1b2c3d4-...",
      "access_level": "chat_only",
      "granted_by": "user_abc",
      "invite_code": "abc123def456",
      "granted_at": "2026-02-25T16:00:00Z"
    }
  ]
}
Code Cause
401 Invalid or missing token
403 Non-admin user
curl http://localhost:8000/api/notebooks/$NOTEBOOK_ID/access \
  -H "Authorization: Bearer $TOKEN"
import httpx

response = httpx.get(
    f"http://localhost:8000/api/notebooks/{notebook_id}/access",
    headers={"Authorization": f"Bearer {token}"},
)
records = response.json()["data"]
for r in records:
    print(f"  {r['user_id']}: {r['access_level']}")

DELETE /api/notebooks/{notebook_id}/access/{user_id}

Revoke a user's access to a notebook.

Auth: Admin

Headers:

Header Value
Authorization Bearer <token>

Status: 200 OK

{
  "success": true,
  "data": {
    "revoked": true
  }
}
Code Cause
401 Invalid or missing token
403 Non-admin user
404 Access record not found
curl -X DELETE http://localhost:8000/api/notebooks/$NOTEBOOK_ID/access/user_def456 \
  -H "Authorization: Bearer $TOKEN"
import httpx

response = httpx.delete(
    f"http://localhost:8000/api/notebooks/{notebook_id}/access/{target_user_id}",
    headers={"Authorization": f"Bearer {token}"},
)
print(response.json()["data"])

POST /api/invite/{invite_code}/redeem

Redeem an invite code. Grants chat_only access to the associated notebook. The system searches across all configured databases (cloud and local) to find the invite.

Auth: User

Headers:

Header Value
Authorization Bearer <token>

Status: 200 OK

{
  "success": true,
  "data": {
    "notebook_id": "a1b2c3d4-...",
    "notebook_title": "Customer Support KB",
    "access_level": "chat_only"
  }
}
Code Cause
401 Invalid or missing token
404 Invite not found or already revoked
410 Invite has expired
curl -X POST http://localhost:8000/api/invite/abc123def456/redeem \
  -H "Authorization: Bearer $TOKEN"
import httpx

invite_code = "abc123def456"
response = httpx.post(
    f"http://localhost:8000/api/invite/{invite_code}/redeem",
    headers={"Authorization": f"Bearer {token}"},
)
result = response.json()["data"]
print(f"Access granted to: {result['notebook_title']}")

GET /api/invite/{invite_code}

Get public information about an invite link. Used by the frontend to display invite details before the user redeems it.

Auth: User

Headers:

Header Value
Authorization Bearer <token>

Status: 200 OK

{
  "success": true,
  "data": {
    "notebook_title": "Customer Support KB",
    "notebook_icon": "\ud83d\udcca",
    "is_valid": true,
    "reason": null
  }
}

When the invite is invalid:

{
  "success": true,
  "data": {
    "notebook_title": "",
    "notebook_icon": null,
    "is_valid": false,
    "reason": "not_found"
  }
}
Reason Description
null Invite is valid
"not_found" Invite does not exist
"expired" Invite has expired
"revoked" Invite was revoked by admin
Code Cause
401 Invalid or missing token
curl http://localhost:8000/api/invite/abc123def456 \
  -H "Authorization: Bearer $TOKEN"
import httpx

invite_code = "abc123def456"
response = httpx.get(
    f"http://localhost:8000/api/invite/{invite_code}",
    headers={"Authorization": f"Bearer {token}"},
)
info = response.json()["data"]
if info["is_valid"]:
    print(f"Invite for: {info['notebook_title']}")
else:
    print(f"Invalid: {info['reason']}")