Skip to main content

Gramps Web API Client

A simple Python client based on requests for interacting with a Gramps Web API server.

Warning

This is an experimental project for advanced users. The goal is to allow powerful batch operations on Gramps objects via the API. But only use it if you know what you are doing – you can easily break your Gramps database with this tool!

Install

pip install gramps-web-api-client

Quick start

First, instantiate the API instance:

from gramps_web_api_client import API

api = API(
    host="https://my-gramps-web-instance.com",
    basic_auth=("my_user", "my_password")
)

The client reuses a single HTTP session. It can also be used as a context manager, which closes the session when done:

with API(host="https://my-gramps-web-instance.com", basic_auth=("my_user", "my_password")) as api:
    print(api.get_metadata())

Optional arguments are timeout (seconds per request, default 30) and session (a preconfigured requests.Session). Access tokens are fetched on first use and renewed automatically when they expire.

Python 3.10 or newer is required.

Methods

For each object type, the client has methods to iterate over, get, create, update and delete objects:

Object type Iterate Get by handle / Gramps ID Create Update Delete
Citation iter_citations() get_citation(handle), get_citation_by_gramps_id(gramps_id) create_citation(data) update_citation(handle, data) delete_citation(handle)
Event iter_events() get_event(handle), get_event_by_gramps_id(gramps_id) create_event(data) update_event(handle, data) delete_event(handle)
Family iter_families() get_family(handle), get_family_by_gramps_id(gramps_id) create_family(data) update_family(handle, data) delete_family(handle)
Media object iter_media() get_media(handle), get_media_by_gramps_id(gramps_id) – update_media(handle, data) delete_media(handle)
Note iter_notes() get_note(handle), get_note_by_gramps_id(gramps_id) create_note(data) update_note(handle, data) delete_note(handle)
Person iter_people() get_person(handle), get_person_by_gramps_id(gramps_id) create_person(data) update_person(handle, data) delete_person(handle)
Place iter_places() get_place(handle), get_place_by_gramps_id(gramps_id) create_place(data) update_place(handle, data) delete_place(handle)
Repository iter_repositories() get_repository(handle), get_repository_by_gramps_id(gramps_id) create_repository(data) update_repository(handle, data) delete_repository(handle)
Source iter_sources() get_source(handle), get_source_by_gramps_id(gramps_id) create_source(data) update_source(handle, data) delete_source(handle)
Tag iter_tags() get_tag(handle) create_tag(data) update_tag(handle, data) delete_tag(handle)

In addition:

Method Description
search(query) Iterate over full-text search results
get_metadata(include_surnames) Get metadata about the current instance

Uploading and downloading media files is not supported yet, which is why there is no create_media.

Getting objects

get_* methods return a single object as a dictionary and raise a GrampsWebAPIError (status 404) if the handle does not exist. get_*_by_gramps_id methods return None if no object has that Gramps ID.

iter_* methods are generators that fetch results page by page. Their keyword arguments are passed as query parameters to the API; see the API documentation for all options. Commonly used ones are:

  • gramps_id: only return the object with this Gramps ID
  • rules: a filter as a dictionary, using Gramps filter rule names
  • extend: include referenced objects, e.g. ["event_ref_list", "citation_list"] or "all"
  • profile: include a human-readable summary, e.g. "self" or "all"
  • keys / skipkeys: only return or leave out the given keys
  • strip: leave out empty values

Lists are sent comma-separated, dictionaries as JSON and booleans as true/false:

for person in api.iter_people(rules={"rules": [{"name": "IsMale"}]}, keys=["handle", "gramps_id"]):
    ...

search(query) iterates over full-text search results. Each result is a dictionary with the keys handle, object_type and object. It accepts the same kind of keyword arguments, e.g. type=["person", "note"] to limit the object types.

Creating, updating and deleting objects

data is always a dictionary following the Gramps Web API JSON conventions.

update_* methods fetch the object, merge data into it and save the result. The merge only works on top-level keys: a key you pass replaces the whole existing value. For example, passing {"primary_name": {"first_name": "John"}} replaces the entire primary name, deleting the surname and all other name fields. To change a nested value, fetch the object, modify it and pass the complete top-level value:

person = api.get_person("somehandle")
name = person["primary_name"]
name["first_name"] = "John"
api.update_person("somehandle", {"primary_name": name})

create_*, update_* and delete_* methods return the database transaction: a list of changes, each a dictionary with the keys type ("add", "update" or "delete"), _class, handle, old and new. To get the handle of a newly created object:

transaction = api.create_note({"text": {"_class": "StyledText", "string": "Hello"}})
handle = transaction[0]["handle"]

Errors

If the server returns an error, a GrampsWebAPIError is raised. It is a subclass of requests.HTTPError, with the HTTP status in status_code and the decoded JSON error body (if any) in data:

from gramps_web_api_client import GrampsWebAPIError

try:
    api.get_person("nonexistent")
except GrampsWebAPIError as e:
    print(e.status_code, e.data)

Examples

Removing all citations from an existing person:

api.update_person("somehandle", {"citation_list": []})

In this example, all other properties of the person (except citations) will remain the same.

Creating a new place:

api.create_place({
    "name": {
        "_class": "PlaceName",
        "value": "Gotham City"
    }
})

Iterating over people and adding a citation if a condition is satisfied:

for person in api.iter_people():
    try:
        surname = person["primary_name"]["surname_list"][0]["surname"]
    except (KeyError, IndexError):
        continue
    if surname == "Garner":
        api.update_person(
            person["handle"],
            {"citation_list": person["citation_list"] + ["some_citation_handle"]}
        )    

Development

This project uses uv:

uv sync                    # install the package and dev dependencies
uv run pytest              # run the tests
uv run ruff check src tests
uv run ruff format src tests
uv run mypy

Metadata

Release files for gramps-web-api-client 0.2

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

Source distribution (sdist)

Source distribution for gramps-web-api-client 0.2
File Size Uploaded
gramps_web_api_client-0.2.tar.gz 14.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gramps-web-api-client 0.2
File Interpreter ABI Platform
gramps_web_api_client-0.2-py3-none-any.whl Python 3 none any Details

Total release size: 23.7 kB

Release files / gramps_web_api_client-0.2.tar.gz

Download URL gramps_web_api_client-0.2.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5b50f6d014d5f51763351c751a1a8b4f470c20b6beb7ccd0a8110ac317a71b21
BLAKE2b-256 checksum
How to use checksums
f2d314fd46341800cd174b1c8259e7a3751151565a7198952a600ccc1e540e5f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.

Transparency log

Release files / gramps_web_api_client-0.2-py3-none-any.whl

Download URL gramps_web_api_client-0.2-py3-none-any.whl
Size 9.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bd8b22df806c5b17d56f99c3917411ed942e876436c33939393b3a7551802279
BLAKE2b-256 checksum
How to use checksums
0e8d2ab99ca4809297b9b2af4b3148f9a161cb63c912e423d45e5547ff572563
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2 This release

2 release files

0.1

2 release files

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