> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gumnut.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Merge people

> Merges one or more source people into the primary person identified by the URL. All faces from source people are reassigned to the primary person. Source people are permanently deleted (this cannot be undone). The primary person's centroid embedding is recalculated.

In the degenerate case where the primary and all sources are unnamed and have zero faces, the primary is auto-deleted by the post-merge centroid recompute (GUM-681) and the response is `204 No Content`.



## OpenAPI

````yaml https://api.gumnut.ai/openapi.json post /api/people/{person_id}/merge
openapi: 3.1.0
info:
  title: Gumnut API
  description: API for using Gumnut to manage photos and videos
  version: 0.1.0
servers: []
security: []
paths:
  /api/people/{person_id}/merge:
    post:
      tags:
        - people
      summary: Merge people
      description: >-
        Merges one or more source people into the primary person identified by
        the URL. All faces from source people are reassigned to the primary
        person. Source people are permanently deleted (this cannot be undone).
        The primary person's centroid embedding is recalculated.


        In the degenerate case where the primary and all sources are unnamed and
        have zero faces, the primary is auto-deleted by the post-merge centroid
        recompute (GUM-681) and the response is `204 No Content`.
      operationId: merge_people
      parameters:
        - name: person_id
          in: path
          required: true
          schema:
            type: string
            title: Person Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PersonMerge'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PersonResponse'
        '204':
          description: >-
            Primary person was auto-deleted by the post-merge centroid recompute
            (degenerate empty-empty merge — primary and all sources unnamed with
            zero faces). No body returned.
        '404':
          description: Not found
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    PersonMerge:
      properties:
        source_person_ids:
          items:
            type: string
          type: array
          maxItems: 50
          minItems: 1
          title: Source Person Ids
          description: >-
            IDs of the people to merge into the primary person. These people
            will be deleted after their faces are moved.
      type: object
      required:
        - source_person_ids
      title: PersonMerge
    PersonResponse:
      properties:
        id:
          type: string
          title: Id
          description: Unique person identifier with 'person_' prefix
        name:
          anyOf:
            - type: string
            - type: 'null'
          title: Name
          description: Optional name assigned to this person
        birth_date:
          anyOf:
            - type: string
              format: date
            - type: 'null'
          title: Birth Date
          description: Optional birth date of this person
        is_hidden:
          type: boolean
          title: Is Hidden
          description: Whether this person should be hidden from the UI
        is_favorite:
          type: boolean
          title: Is Favorite
          description: Whether this person is marked as a favorite
        asset_count:
          anyOf:
            - type: integer
            - type: 'null'
          title: Asset Count
          description: >-
            Number of unique photos this person appears in, or null if not
            computed
        thumbnail_face_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Thumbnail Face Id
          description: ID of the face resource used as this person's thumbnail
        asset_urls:
          anyOf:
            - additionalProperties:
                $ref: '#/components/schemas/AssetVariant'
              type: object
            - type: 'null'
          title: Asset Urls
          description: >-
            Asset variants from this person's thumbnail face. May be null when
            embedded in an AssetResponse; use /api/people endpoints for full
            person data.
        cluster_metrics:
          anyOf:
            - $ref: '#/components/schemas/ClusterMetricsResponse'
            - type: 'null'
          description: >-
            Cohesion metrics for this person's face cluster. Populated only when
            `include=cluster_metrics` is requested on the people endpoint, and
            only for persons with a populated centroid (newly-created empty
            Persons will have null). See `ClusterMetricsResponse` for the shape.
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When this person record was created
        updated_at:
          type: string
          format: date-time
          title: Updated At
          description: When this person record was last updated
      type: object
      required:
        - id
        - is_hidden
        - is_favorite
        - created_at
        - updated_at
      title: PersonResponse
      description: Represents a person identified through face clustering and recognition.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    AssetVariant:
      properties:
        url:
          type: string
          title: Url
          description: URL to fetch this image variant
        mimetype:
          type: string
          title: Mimetype
          description: MIME type of the served image
        width:
          anyOf:
            - type: integer
            - type: 'null'
          title: Width
          description: Target width in pixels (null if unknown)
      type: object
      required:
        - url
        - mimetype
      title: AssetVariant
      description: A single image variant with its URL, MIME type, and target width.
    ClusterMetricsResponse:
      properties:
        pairwise_p90:
          type: number
          title: Pairwise P90
          description: >-
            90th-percentile pairwise cosine distance between faces in this
            person's cluster. Lower = more cohesive cluster; loose clusters
            (higher pairwise_p90) are gated out of the face-assignment path to
            prevent further drift.
        pairwise_mean:
          type: number
          title: Pairwise Mean
          description: >-
            Mean pairwise cosine distance between faces in this person's
            cluster.
        face_count:
          type: integer
          title: Face Count
          description: >-
            Number of faces that fed into the centroid and pairwise metrics.
            This is the cluster-membership count, **not** the same as
            `asset_count` — `face_count` counts every face row, while
            `asset_count` counts distinct assets (one asset can contribute
            multiple faces of the same person).
      type: object
      required:
        - pairwise_p90
        - pairwise_mean
        - face_count
      title: ClusterMetricsResponse
      description: |-
        Cohesion metrics for a Person's face cluster — surfaced via
        ``include=cluster_metrics`` on the people endpoints. These describe how
        tight the cluster is in embedding space (lower = more cohesive) and
        drive both the production face-assignment cohesion gate and the
        operator-facing face cleanup dashboard.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError

````