API reference

Matches

Suggested duplicate people: review them, then accept (merge) or reject. A group of duplicates can be merged in one request.

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

get/workspaces/{workspace_id}/matches

List pending match suggestions

A page can be shorter than limit when matches with a trashed person are dropped. Keep following next_cursor.

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

Responses

  • 200 A page of pending matches. (MatchList)
  • 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 or cursor. (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",
            "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)$"
          },
          "person_a_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)$"
          },
          "person_b_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)$"
          },
          "confidence": {
            "type": "string"
          },
          "score": {
            "type": [
              "number",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "const": "pending"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "person_a_id",
          "person_b_id",
          "confidence",
          "score",
          "status",
          "created_at"
        ]
      }
    },
    "next_cursor": {
      "description": "Pass as ?cursor to get the next page. Null on the last page.",
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "next_cursor"
  ]
}
post/workspaces/{workspace_id}/matches/{match_id}/reject

Reject a match

The pair is not suggested again. Replays of an Idempotency-Key return the original body and request_id; headers are not replayed.

NameInRequiredDescription
workspace_idpathyesThe workspace (project) id.
match_idpathyesThe match id.
Idempotency-KeyheadernoMakes the write safe to retry (1-255 characters, kept 24 hours). Same key and same request replays the original response; a different request with the same key is a 409.
Request body (application/json)
{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}

Responses

  • 200 Rejected. (Ok)
  • 401 Missing, malformed, unknown or revoked API key. (ErrorResponse)
  • 403 The account has no paid plan, or the key is read-only (a read_write key is required). (ErrorResponse)
  • 404 The workspace does not exist or is not visible to this key's owner. Also: The match does not exist or is not visible. (ErrorResponse)
  • 409 The workspace is archived (writes are refused). Also: Idempotency-Key was reused with a different request, or a request with it is still in progress. Also: The match is already resolved. (ErrorResponse)
  • 422 Validation failed. A bad Idempotency-Key (1-255 characters) is also a 422. (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": {
    "ok": {
      "type": "boolean",
      "const": true
    }
  },
  "required": [
    "ok"
  ]
}
post/workspaces/{workspace_id}/matches/{match_id}/accept

Accept a match (merge)

Merges the match's two people. The body is optional; survivor_id defaults to person_a_id. To undo it, send the returned match_id to POST .../people/{person_id}/unmerge with the survivor in the path. Replays of an Idempotency-Key return the original body and request_id; headers are not replayed.

NameInRequiredDescription
workspace_idpathyesThe workspace (project) id.
match_idpathyesThe match id.
Idempotency-KeyheadernoMakes the write safe to retry (1-255 characters, kept 24 hours). Same key and same request replays the original response; a different request with the same key is a 409.
Request body (application/json)
{
  "type": "object",
  "properties": {
    "survivor_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)$"
    },
    "field_choices": {
      "type": "object",
      "propertyNames": {
        "type": "string",
        "enum": [
          "given_name",
          "surname",
          "birth_date",
          "birth_place",
          "death_date",
          "death_place",
          "gender",
          "maiden_name",
          "occupation",
          "religion",
          "burial_date",
          "burial_place",
          "christening_date",
          "christening_place",
          "death_cause",
          "name_prefix",
          "name_suffix",
          "surname_prefix",
          "nickname"
        ]
      },
      "additionalProperties": {
        "type": "string",
        "enum": [
          "survivor",
          "absorbed"
        ]
      }
    }
  },
  "additionalProperties": false
}

Responses

  • 200 Merged. Returns the surviving person. (MatchAccepted)
  • 401 Missing, malformed, unknown or revoked API key. (ErrorResponse)
  • 403 The account has no paid plan, or the key is read-only (a read_write key is required). (ErrorResponse)
  • 404 The workspace does not exist or is not visible to this key's owner. Also: The match does not exist or is not visible. (ErrorResponse)
  • 409 The workspace is archived (writes are refused). Also: Idempotency-Key was reused with a different request, or a request with it is still in progress. Also: The match is already resolved, or one of its people is gone. (ErrorResponse)
  • 422 Validation failed. A bad Idempotency-Key (1-255 characters) is also a 422. Also: survivor_id is not one of the match's two people, or a man and a woman. (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": {
    "ok": {
      "type": "boolean",
      "const": true
    },
    "match_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)$"
    },
    "survivor": {
      "type": "object",
      "properties": {
        "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)$"
        },
        "workspace_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)$"
        },
        "given_name": {
          "type": [
            "string",
            "null"
          ]
        },
        "surname": {
          "type": [
            "string",
            "null"
          ]
        },
        "maiden_name": {
          "type": [
            "string",
            "null"
          ]
        },
        "name_prefix": {
          "type": [
            "string",
            "null"
          ]
        },
        "name_suffix": {
          "type": [
            "string",
            "null"
          ]
        },
        "surname_prefix": {
          "type": [
            "string",
            "null"
          ]
        },
        "title": {
          "type": [
            "string",
            "null"
          ]
        },
        "nickname": {
          "type": [
            "string",
            "null"
          ]
        },
        "display_name": {
          "type": "string"
        },
        "gender": {
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "M",
                "F",
                "X",
                "U"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "birth": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place"
          ]
        },
        "christening": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place"
          ]
        },
        "death": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            },
            "cause": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place",
            "cause"
          ]
        },
        "burial": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place"
          ]
        },
        "occupation": {
          "type": [
            "string",
            "null"
          ]
        },
        "religion": {
          "type": [
            "string",
            "null"
          ]
        },
        "living_status": {
          "type": [
            "string",
            "null"
          ]
        },
        "notes": {
          "type": [
            "string",
            "null"
          ]
        },
        "created_at": {
          "type": "string"
        },
        "folder_id": {
          "description": "The folder the person is in (null: none). Returned by GET .../people.",
          "anyOf": [
            {
              "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)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "tag_ids": {
          "description": "Ids of the person's tags. Returned by GET .../people.",
          "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)$"
          }
        }
      },
      "required": [
        "id",
        "workspace_id",
        "given_name",
        "surname",
        "maiden_name",
        "name_prefix",
        "name_suffix",
        "surname_prefix",
        "title",
        "nickname",
        "display_name",
        "gender",
        "birth",
        "christening",
        "death",
        "burial",
        "occupation",
        "religion",
        "living_status",
        "notes",
        "created_at"
      ]
    }
  },
  "required": [
    "ok",
    "match_id",
    "survivor"
  ]
}
post/workspaces/{workspace_id}/matches/merge-group

Merge a group of duplicates

Merge every other person in person_ids into survivor_id, as one undoable group: unmerging any of the returned match_ids restores the whole group. If a later person cannot be merged, the earlier merges stand and that person is listed in failed. Replays of an Idempotency-Key return the original body and request_id; headers are not replayed.

NameInRequiredDescription
workspace_idpathyesThe workspace (project) id.
Idempotency-KeyheadernoMakes the write safe to retry (1-255 characters, kept 24 hours). Same key and same request replays the original response; a different request with the same key is a 409.
Request body (application/json, required)
{
  "type": "object",
  "properties": {
    "person_ids": {
      "minItems": 2,
      "maxItems": 20,
      "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)$"
      },
      "description": "Everyone in the group, survivor included: 2 to 20 distinct people."
    },
    "survivor_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)$",
      "description": "The person the others are merged into. Must be in person_ids."
    }
  },
  "required": [
    "person_ids",
    "survivor_id"
  ],
  "additionalProperties": false
}

Responses

  • 200 Merged. (MergeGroupResult)
  • 401 Missing, malformed, unknown or revoked API key. (ErrorResponse)
  • 403 The account has no paid plan, or the key is read-only (a read_write key is required). (ErrorResponse)
  • 404 The workspace does not exist or is not visible to this key's owner. Also: A person does not exist or is not visible. (ErrorResponse)
  • 409 The workspace is archived (writes are refused). Also: Idempotency-Key was reused with a different request, or a request with it is still in progress. (ErrorResponse)
  • 422 Validation failed. A bad Idempotency-Key (1-255 characters) is also a 422. Also: Fewer than 2 or more than 20 people, survivor_id not in person_ids, or a man and a woman. (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": {
    "ok": {
      "type": "boolean",
      "const": true
    },
    "survivor": {
      "type": "object",
      "properties": {
        "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)$"
        },
        "workspace_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)$"
        },
        "given_name": {
          "type": [
            "string",
            "null"
          ]
        },
        "surname": {
          "type": [
            "string",
            "null"
          ]
        },
        "maiden_name": {
          "type": [
            "string",
            "null"
          ]
        },
        "name_prefix": {
          "type": [
            "string",
            "null"
          ]
        },
        "name_suffix": {
          "type": [
            "string",
            "null"
          ]
        },
        "surname_prefix": {
          "type": [
            "string",
            "null"
          ]
        },
        "title": {
          "type": [
            "string",
            "null"
          ]
        },
        "nickname": {
          "type": [
            "string",
            "null"
          ]
        },
        "display_name": {
          "type": "string"
        },
        "gender": {
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "M",
                "F",
                "X",
                "U"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "birth": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place"
          ]
        },
        "christening": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place"
          ]
        },
        "death": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            },
            "cause": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place",
            "cause"
          ]
        },
        "burial": {
          "type": "object",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "year": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                {
                  "type": "null"
                }
              ]
            },
            "place": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "date",
            "year",
            "place"
          ]
        },
        "occupation": {
          "type": [
            "string",
            "null"
          ]
        },
        "religion": {
          "type": [
            "string",
            "null"
          ]
        },
        "living_status": {
          "type": [
            "string",
            "null"
          ]
        },
        "notes": {
          "type": [
            "string",
            "null"
          ]
        },
        "created_at": {
          "type": "string"
        },
        "folder_id": {
          "description": "The folder the person is in (null: none). Returned by GET .../people.",
          "anyOf": [
            {
              "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)$"
            },
            {
              "type": "null"
            }
          ]
        },
        "tag_ids": {
          "description": "Ids of the person's tags. Returned by GET .../people.",
          "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)$"
          }
        }
      },
      "required": [
        "id",
        "workspace_id",
        "given_name",
        "surname",
        "maiden_name",
        "name_prefix",
        "name_suffix",
        "surname_prefix",
        "title",
        "nickname",
        "display_name",
        "gender",
        "birth",
        "christening",
        "death",
        "burial",
        "occupation",
        "religion",
        "living_status",
        "notes",
        "created_at"
      ]
    },
    "merged_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)$"
      }
    },
    "match_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)$"
      },
      "description": "One per merged person. Unmerging any one of them undoes the whole group."
    },
    "failed": {
      "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)$"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "person_id",
          "reason"
        ]
      },
      "description": "People that could not be merged after at least one merge succeeded. Usually empty."
    }
  },
  "required": [
    "ok",
    "survivor",
    "merged_person_ids",
    "match_ids",
    "failed"
  ]
}

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.