Skip to main content

pyclann

Python client library for the Clann family-tree API.

Installation

pip install pyclann

Quick start

from pyclann import ClannClient

client = ClannClient(
    api_url="http://localhost:8090",
    auth_url="http://localhost:8081",   # ullav-user-management service
)
client.login(email="user@example.com", password="secret")

# Family trees
trees = client.trees.list(owner="alice")
tree = client.trees.create("walsh-family", "Walsh Family", owner="alice")

# Persons
father = client.persons.create(
    "Walsh", "Patrick", "Male",
    trees=["walsh-family"],
    date_of_birth="1820-06-01",
    created_by="alice",
)
son = client.persons.create(
    "Walsh", "Michael", "Male",
    trees=["walsh-family"],
    created_by="alice",
)

# Relationships
client.relationships.add(son.id, "Father", father.id)
rels = client.relationships.get(son.id)       # RelationshipsResponse

# Life events
client.life_events.create(
    father.id, "Born in Galway", "Birth",
    date="1820-06-01",
    created_by="alice",
)

# Research notes
note = client.notes.create(
    "Walsh Family Research",
    trees=["walsh-family"],
    body="Found records at Galway archives.",
    is_shared=True,
    created_by="alice",
)
client.notes.create_reply(note.id, "Also check Dublin records.", created_by="alice")

# Profile picture
with open("patrick.jpg", "rb") as f:
    client.persons.upload_image(father.id, f.read(), "image/jpeg")

image_bytes = client.persons.get_image(father.id)   # public endpoint, no auth needed

Authentication

ClannClient authenticates against the ullav-user-management service, which issues the JWT accepted by the Clann server.

  • api_url — Clann server base URL (e.g. http://clann-server:8090)
  • auth_url — auth service base URL (e.g. http://ullav-user-management:8081); omit if both services are behind the same proxy

Call client.login(email, password) before any other method. Tokens expire according to the server's configuration; call login() again to refresh.

Resource clients

Attribute Resource
client.trees Family tree CRUD, primary flag, team assignment, avatar image
client.persons Person CRUD, tree membership, profile/life-story media
client.relationships Add/remove father/mother/sibling/spouse edges, family-tree view
client.life_events Life event CRUD per person
client.notes Research note CRUD, folder assignment, replies
client.folders Research folder CRUD
client.chat AI chat session and message management
client.ai_settings Per-user AI provider settings (encrypted BYOK)

Error handling

from pyclann import ClannAuthError, ClannNotFoundError, ClannValidationError

try:
    tree = client.trees.get("non-existent-tree")
except ClannNotFoundError:
    print("tree not found")
except ClannAuthError:
    client.login(email, password)   # token expired — re-authenticate
except ClannValidationError as e:
    print("bad request:", e)
Exception HTTP status
ClannAuthError 401 / 403, or login() not called
ClannNotFoundError 404
ClannValidationError 400
ClannServerError 5xx
ClannError base class

Record IDs

The Clann API uses SurrealDB record IDs of the form "table:ulid", e.g. "person:01jd4a8xyz". All client methods that take an *_id parameter accept either the full form or the bare ULID — the library strips the table prefix when building URL paths.

person = client.persons.get("person:01jd4a8xyz")   # full ID
person = client.persons.get("01jd4a8xyz")           # bare ULID — both work

Note: when specifying a related_id in relationship calls, always pass the full record ID ("person:01jd4a8xyz"), since the server uses it verbatim in URL paths.

Relationship types

from pyclann import RelationshipType, SiblingType

# Add a father
client.relationships.add(child.id, RelationshipType.FATHER, father.id)

# Add a sibling — sibling_type is required
client.relationships.add(
    person.id,
    RelationshipType.SIBLING,
    sibling.id,
    sibling_type=SiblingType.BROTHER,
)

# Add a spouse with dates
client.relationships.add(
    person.id,
    RelationshipType.SPOUSE,
    spouse.id,
    spouse_from="1845-09-14",
)

# Remove a relationship
client.relationships.remove(child.id, RelationshipType.FATHER, father.id)

Image uploads

Profile pictures accept JPEG or PNG only (max 2 MB). Life-story media accepts the same image formats on Individual/Family plans; Professional/Enterprise plans also allow video (MP4, MOV, WebM), audio (MP3, WAV, OGG), and PDF.

# Upload
with open("profile.jpg", "rb") as f:
    client.persons.upload_image(person.id, f.read(), "image/jpeg")

# Download — no login() required
data = client.persons.get_image(person.id)
with open("downloaded.jpg", "wb") as f:
    f.write(data)

Licence

MIT

Metadata

Release files for pyclann 26.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyclann 26.7.0
File Size Uploaded Provenance
pyclann-26.7.0.tar.gz 37.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pyclann 26.7.0
File Interpreter ABI Platform
pyclann-26.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 67.7 kB

Release files / pyclann-26.7.0.tar.gz

Download URL pyclann-26.7.0.tar.gz
Size 37.9 kB
Tags Source
SHA-256 checksum
How to use checksums
54cd27832e5ffe12e5bbf6ac5432d9bbe67248083e6a04a5176322fbd9546c1f
BLAKE2b-256 checksum
How to use checksums
55dd300924c5910b01bdce15c31a8dac32115d50ea3d56c879fbb706b264de72
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / pyclann-26.7.0-py3-none-any.whl

Download URL pyclann-26.7.0-py3-none-any.whl
Size 29.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fce36b5b7421a0efc475ef223f5b6d2fb4a321a127b11ca53e83e17e09ee49f7
BLAKE2b-256 checksum
How to use checksums
52296215283312af17bd35c92bbf5344e3fff1165c6737b9cfa1588c8be19911
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for pyclann 26.7.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page