API reference

Places

Places derived from a workspace's people and confirmed records: list them, read one with its people and events, and get place-name suggestions.

Paths are relative to https://kleiobase.com/api/v1.

get/workspaces/{workspace_id}/places

List places

Derived from people and confirmed records. Ordered by name. A place's id is stable and opaque. coordinates come from the geocode cache only: a list never geocodes, so a place not geocoded yet has null coordinates.

NameInRequiredDescription
workspace_idpathyesThe workspace (project) id.
limitquerynoPage size. Default 25, max 100.
cursorquerynoThe next_cursor of the previous page. Opaque.
qquerynoPlace name filter (max 200 characters).

Responses

  • 200 A page of places. (PlaceList)
  • 401 Missing, malformed, unknown or revoked API key. (ErrorResponse)
  • 403 The account has no paid plan. (ErrorResponse)
  • 404 The workspace does not exist or is not visible to this key's owner. (ErrorResponse)
  • 422 Invalid limit, cursor or q. (ErrorResponse)
  • 429 Rate limit exceeded. Wait the number of seconds in Retry-After. (ErrorResponse)
  • 500 Unexpected error. Retry later and quote request_id if it persists. (ErrorResponse)
200 response schema
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable, opaque id of the place. Use it with GET .../places/{place_id}."
          },
          "name": {
            "type": "string"
          },
          "coordinates": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "lat": {
                    "type": "number"
                  },
                  "lng": {
                    "type": "number"
                  }
                },
                "required": [
                  "lat",
                  "lng"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "From the geocode cache. Null when the place has not been geocoded yet or could not be found."
          },
          "people": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "person_id": {
                  "type": "string",
                  "format": "uuid",
                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                },
                "context": {
                  "type": "string"
                }
              },
              "required": [
                "person_id",
                "context"
              ]
            }
          }
        },
        "required": [
          "id",
          "name",
          "coordinates",
          "people"
        ]
      }
    },
    "next_cursor": {
      "description": "Pass as ?cursor to get the next page. Null on the last page.",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ]
}
get/workspaces/{workspace_id}/places/{place_id}

Get a place

The place, who is connected to it and the events there. When the place is not in the geocode cache yet it is geocoded once now, which also counts against the app's geocoding rate limit (429 with Retry-After when it is reached). coordinates is null when the place cannot be found on the map.

NameInRequiredDescription
workspace_idpathyesThe workspace (project) id.
place_idpathyesThe place id, as returned by GET .../places or GET .../search. Opaque.

Responses

  • 200 The place. (PlaceDetail)
  • 401 Missing, malformed, unknown or revoked API key. (ErrorResponse)
  • 403 The account has no paid plan. (ErrorResponse)
  • 404 The workspace does not exist or is not visible to this key's owner. Also: The place id is invalid or the place is not in this workspace. (ErrorResponse)
  • 429 Rate limit exceeded. Wait the number of seconds in Retry-After. (ErrorResponse)
  • 500 Unexpected error. Retry later and quote request_id if it persists. (ErrorResponse)
200 response schema
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "coordinates": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "lat": {
              "type": "number"
            },
            "lng": {
              "type": "number"
            }
          },
          "required": [
            "lat",
            "lng"
          ]
        },
        {
          "type": "null"
        }
      ],
      "description": "From the geocode cache. Null when the place has not been geocoded yet or could not be found."
    },
    "people": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "person_id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
          },
          "role": {
            "type": "string",
            "enum": [
              "birth",
              "death",
              "event"
            ]
          }
        },
        "required": [
          "person_id",
          "role"
        ]
      },
      "description": "Who is connected to the place: born there, died there, or part of an event there."
    },
    "events": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string"
          },
          "date": {
            "description": "Always null in v1; use year.",
            "type": [
              "string",
              "null"
            ]
          },
          "year": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "place": {
            "type": [
              "string",
              "null"
            ]
          },
          "person_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          "record_id": {
            "description": "Always null in v1.",
            "type": [
              "string",
              "null"
            ]
          },
          "label": {
            "type": "string"
          }
        },
        "required": [
          "kind",
          "date",
          "year",
          "place",
          "person_ids",
          "record_id",
          "label"
        ]
      },
      "description": "Dated events at this place, ordered by year."
    }
  },
  "required": [
    "id",
    "name",
    "coordinates",
    "people",
    "events"
  ]
}
get/workspaces/{workspace_id}/places/suggestions

Suggest place names

Place names already used in the workspace that match q, as the app's place field suggests them: matches at the start of a word first. At most 20. Not paginated: next_cursor is always null.

NameInRequiredDescription
workspace_idpathyesThe workspace (project) id.
qquerynoWhat was typed so far (1 to 100 characters). Matching ignores case and accents.

Responses

  • 200 Suggestions. (PlaceSuggestionList)
  • 401 Missing, malformed, unknown or revoked API key. (ErrorResponse)
  • 403 The account has no paid plan. (ErrorResponse)
  • 404 The workspace does not exist or is not visible to this key's owner. (ErrorResponse)
  • 422 q is missing or longer than 100 characters. (ErrorResponse)
  • 429 Rate limit exceeded. Wait the number of seconds in Retry-After. (ErrorResponse)
  • 500 Unexpected error. Retry later and quote request_id if it persists. (ErrorResponse)
200 response schema
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        },
        "required": [
          "name"
        ]
      }
    },
    "next_cursor": {
      "description": "Pass as ?cursor to get the next page. Null on the last page.",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ]
}

We use cookies and similar technologies. Essential cookies keep the site working and secure. We only load analytics (PostHog, including masked session replays) and marketing (Meta Pixel and TikTok Pixel) with your consent. See our Privacy Policy.