For developers
RootBound Tree API
Show a family’s published tree on another website. Paste one tag, or read the tree as JSON.
What it is
A family’s Recordkeeper can publish the family tree. They do it in RootBound, under Settings, then Publishing. They can publish the whole family. Or they can publish one person’s branch, with a chosen number of generations above and below.
Other websites can then show that tree. A memorial page is a common example. The tree stays up to date. Changes appear within about a minute.
What gets published
These rules are enforced in the database. No key or setting gets around them.
- Only people visible to the whole family are published.
- People hidden in the family are never published.
- Contact details are never published.
- People who have died show their name, dates with their certainty status, a portrait and a short bio.
- Living people show their name, a portrait, their birth year and a short bio. Never the full birth date.
- A living person can choose “limited”. Then only a first or preferred name and a portrait are shown.
- Under-18s are “limited” until someone chooses otherwise.
- A person who has claimed their profile makes this choice for themselves.
Keys
Keys are made in Settings, then Publishing. Each key is shown once, so copy it somewhere safe.
rb_pk_...
A website key. It works only on the websites listed for it. It is safe to put in a page.
rb_sk_...
A server key. It must stay on a server. Never put it in a page or an app.
Quick start: embed
Paste this where the tree should appear. Use your publication id and a website key.
<script src="https://rootbound.aristhegf.workers.dev/embed.js" async></script> <rootbound-tree publication="YOUR_PUBLICATION_ID" key="rb_pk_YOUR_WEBSITE_KEY" theme="auto" height="560"></rootbound-tree>
The <rootbound-tree> tag takes these attributes.
- publication
- The publication id. Required.
- key
- Your website key. Required.
- theme
- light, dark or auto. The default is auto.
- accent
- A hex colour without the #, for example 7a1f1f.
- focus
- A person id to open on. Useful when the tree is large.
- height
- The height in pixels. The default is 560.
- title
- A title for the tree.
The tree checks for changes once a minute while the page is visible. When the family changes something, it reloads. It lives in Shadow DOM, so your page’s styles don’t touch it, and its styles don’t touch your page.
Site builders
Some site builders strip scripts. Wix and Squarespace are two. On those, use a frame instead.
<iframe src="https://rootbound.aristhegf.workers.dev/embed/YOUR_PUBLICATION_ID?key=rb_pk_YOUR_WEBSITE_KEY&theme=auto" width="100%" height="560" style="border:0" referrerpolicy="strict-origin" loading="lazy" title="Family tree"></iframe>
Keep referrerpolicy="strict-origin". The tree uses it to check which website it is on.
Add the exact address the frame runs on to the key’s list of websites. Some builders host custom HTML on their own domain. If yours does, list that domain.
JSON API
Every path below starts from https://rootbound.aristhegf.workers.dev/api/v1.
GET/trees/{publicationId}
GET/trees/{publicationId}/version
{ version, changed_at }. The cheap way to poll.GET/trees/{publicationId}/people/{personId}
GET/media/{publicationId}/{personId}
photo URLs point here.The tree comes back in this shape.
{
"publication": {
"id", "title", "scope", "root_person_id",
"version", "changed_at"
},
"people": [ ... ],
"parent_child": [
{ "parent_id", "child_id", "type", "certainty" }
],
"partnerships": [
{ "partner_a", "partner_b", "type", "status", "certainty" }
]
}One person comes back in this shape.
{ "publication", "person", "parents", "partners", "children", "siblings" }People and links
A person takes one of three shapes.
Someone who has died
{
"id", "name", "preferred_name", "gender",
"living": false,
"profile": "full",
"birth": { "date", "precision", "status" } | null,
"death": { "date", "precision", "status" },
"bio"?,
"photo"
}A living person, full profile
{
"id", "name", "preferred_name", "gender",
"living": true,
"profile": "full",
"birth": { "year", "status" } | null,
"bio"?,
"photo"
}A living person, limited profile
{
"id", "name",
"living": true,
"profile": "limited",
"photo"
}photo is a URL or null.
Uncertainty is part of the data. Every certainty and status is one of confirmed, unconfirmed, estimated, disputed, family_tradition or unknown. Please show it. Don’t present an unconfirmed date as fact.
Authentication
From a server. Send the server key as a bearer token.
Authorization: Bearer rb_sk_YOUR_SERVER_KEY
From a browser. Add the website key to the URL as ?key=rb_pk_.... The request must come from a listed website. We check the Origin header, and answer with CORS for that website only.
Caching and freshness
- The
ETagis the tree’s version. Send it back asIf-None-Match. If nothing changed, you get304 Not Modified. - Answers to a website key can be cached publicly for 60 seconds.
- Answers to a server key are private.
curl -i https://rootbound.aristhegf.workers.dev/api/v1/trees/YOUR_PUBLICATION_ID \ -H "Authorization: Bearer rb_sk_YOUR_SERVER_KEY" \ -H 'If-None-Match: "THE_ETAG_YOU_HAVE"'
There are no webhooks yet. To keep a copy fresh, poll /version once a minute. Fetch the tree again only when the version changes.
Errors
Every error has the same shape.
{ "error": { "code": "invalid_key", "message": "..." } }| Code | Status | Meaning |
|---|---|---|
| bad_request | 400 | The request was not well formed. |
| missing_key | 401 | No key was sent. |
| invalid_key | 401 | The key is wrong, revoked, or for another tree. |
| origin_not_allowed | 403 | This website is not on the key’s list. |
| not_published | 404 | The tree is not published. |
| not_found | 404 | No such person or path. |
| quota_exceeded | 429 | The family’s monthly request allowance is used up. |
| server_error | 500 | Something failed on our side. |
| media_unavailable | 503 | The portrait could not be served right now. |
Limits
The free plan is the only plan today. It allows:
- 3 publications per family
- 100,000 requests a month
- 5 websites per key
Every request counts, including 304 answers.
Examples
Fetch the tree with curl
curl https://rootbound.aristhegf.workers.dev/api/v1/trees/YOUR_PUBLICATION_ID \ -H "Authorization: Bearer rb_sk_YOUR_SERVER_KEY"
Keep a copy fresh in Node
This checks /version once a minute. It fetches the whole tree only when something changed.
// Node 18 or later. Keep the server key on the server.
const BASE = 'https://rootbound.aristhegf.workers.dev/api/v1'
const PUB = 'YOUR_PUBLICATION_ID'
const headers = { Authorization: 'Bearer ' + process.env.ROOTBOUND_SERVER_KEY }
let version = null
let tree = null
async function refresh() {
const res = await fetch(`${BASE}/trees/${PUB}/version`, { headers })
if (!res.ok) {
const { error } = await res.json()
console.error(error.code, error.message)
return
}
const latest = await res.json()
if (latest.version === version) return
const treeRes = await fetch(`${BASE}/trees/${PUB}`, { headers })
if (!treeRes.ok) return
tree = await treeRes.json()
version = tree.publication.version
console.log('Tree updated', latest.changed_at, tree.people.length, 'people')
}
refresh()
setInterval(refresh, 60_000)