PhotoPrism Cluster API

The Cluster API from PhotoPrism — 7 operation(s) for cluster.

Operations 9

GET /api/v1/cluster cluster summary #
GET /api/v1/cluster/health cluster health #
GET /api/v1/cluster/metrics temporary cluster metrics (counts only) #
GET /api/v1/cluster/nodes lists registered nodes #
POST /api/v1/cluster/nodes/register registers a node, provisions DB credentials, and issues ClientSecret #
DELETE /api/v1/cluster/nodes/{uuid} delete node by uuid #
GET /api/v1/cluster/nodes/{uuid} get node by uuid #
PATCH /api/v1/cluster/nodes/{uuid} update node fields #
GET /api/v1/cluster/theme returns custom theme files as zip, if available #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/photoprism:photoprism-cluster-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

photoprism-cluster-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  contact: {}
  description: 'API request bodies and responses are usually JSON-encoded, except for binary data and some of the OAuth2 endpoints. Note that the `Content-Type` header must be set to `application/json` for this, as the request may otherwise fail with error 400.

    When clients have a valid access token, e.g. obtained through the `POST /api/v1/session` or `POST /api/v1/oauth/token` endpoint, they can use a standard Bearer Authorization header to authenticate their requests. Submitting the access token with a custom `X-Auth-Token` header is supported as well.'
  title: PhotoPrism Cluster API
  version: v1
servers:
- url: https://demo.photoprism.app
security:
- BearerAuth: []
tags:
- name: Cluster
paths:
  /api/v1/cluster:
    get:
      operationId: ClusterSummary
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cluster.SummaryResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: cluster summary
      tags:
      - Cluster
  /api/v1/cluster/health:
    get:
      operationId: ClusterHealth
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/api.HealthResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: cluster health
      tags:
      - Cluster
  /api/v1/cluster/metrics:
    get:
      operationId: ClusterMetrics
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cluster.MetricsResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: temporary cluster metrics (counts only)
      tags:
      - Cluster
  /api/v1/cluster/nodes:
    get:
      operationId: ClusterListNodes
      parameters:
      - description: maximum number of results (default 100, max 1000)
        in: query
        name: count
        schema:
          type: integer
          maximum: 1000
          minimum: 1
      - description: result offset
        in: query
        name: offset
        schema:
          type: integer
          minimum: 0
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                items:
                  $ref: '#/components/schemas/cluster.Node'
                type: array
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: lists registered nodes
      tags:
      - Cluster
  /api/v1/cluster/nodes/register:
    post:
      operationId: ClusterNodesRegister
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cluster.RegisterResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cluster.RegisterResponse'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '413':
          description: Request Entity Too Large
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '503':
          description: Service Unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: registers a node, provisions DB credentials, and issues ClientSecret
      tags:
      - Cluster
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: 'registration payload (NodeName required; optional: NodeRole, Labels, AdvertiseUrl, SiteUrl, AppName, AppVersion, Theme, NodeUUID, RotateDatabase, RotateSecret). New-node joins require the Bearer join token. Existing-node mutations require a Bearer OAuth access token that belongs to the same node client.'
        required: true
  /api/v1/cluster/nodes/{uuid}:
    delete:
      operationId: ClusterDeleteNode
      parameters:
      - description: node uuid
        in: path
        name: uuid
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cluster.StatusResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: delete node by uuid
      tags:
      - Cluster
    get:
      operationId: ClusterGetNode
      parameters:
      - description: node uuid
        in: path
        name: uuid
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cluster.Node'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: get node by uuid
      tags:
      - Cluster
    patch:
      operationId: ClusterUpdateNode
      parameters:
      - description: node uuid
        in: path
        name: uuid
        required: true
        schema:
          type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/cluster.StatusResponse'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '413':
          description: Request Entity Too Large
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: update node fields
      tags:
      - Cluster
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: properties to update (Role, DisplayName, Labels, AdvertiseUrl, SiteUrl, RedirectURIs, AllowGroups, AllowGroupRoles, GroupsFullView)
        required: true
  /api/v1/cluster/theme:
    get:
      operationId: ClusterGetTheme
      responses:
        '200':
          description: OK
          content:
            application/zip:
              schema:
                type: string
                format: binary
        '401':
          description: Unauthorized
          content:
            application/zip:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '403':
          description: Forbidden
          content:
            application/zip:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '404':
          description: Not Found
          content:
            application/zip:
              schema:
                $ref: '#/components/schemas/i18n.Response'
        '429':
          description: Too Many Requests
          content:
            application/zip:
              schema:
                $ref: '#/components/schemas/i18n.Response'
      summary: returns custom theme files as zip, if available
      tags:
      - Cluster
components:
  schemas:
    cluster.Node:
      properties:
        AdvertiseUrl:
          type: string
        AllowGroupRoles:
          additionalProperties:
            type: string
          type: object
        AllowGroups:
          description: 'Group-based admission config (redacted for non-admin sessions):

            AllowGroups admits matching login-time groups, AllowGroupRoles

            optionally overrides the default role per group, GroupsFullView opts the

            node into receiving the user''s full group set, and GroupsSrc is the

            AllowGroups provenance ("node" = instance-declared via env, "manual" =

            admin-pinned; empty = unmanaged).'
          items:
            type: string
          type: array
        AppName:
          type: string
        AppVersion:
          type: string
        ClientID:
          type: string
        CreatedAt:
          type: string
        Database:
          $ref: '#/components/schemas/cluster.NodeDatabase'
        DisplayName:
          type: string
        GroupsFullView:
          type: boolean
        GroupsSrc:
          type: string
        Labels:
          additionalProperties:
            type: string
          type: object
        Name:
          description: NodeName
          type: string
        RedirectURIs:
          items:
            type: string
          type: array
        Role:
          description: NodeRole
          type: string
        SiteUrl:
          type: string
        Theme:
          type: string
        UUID:
          description: NodeUUID
          type: string
        UpdatedAt:
          type: string
      type: object
    cluster.SummaryResponse:
      properties:
        ClusterCIDR:
          type: string
        Database:
          $ref: '#/components/schemas/cluster.DatabaseInfo'
        Nodes:
          type: integer
        Theme:
          type: string
        Time:
          type: string
        UUID:
          description: ClusterUUID
          type: string
      type: object
    cluster.RegisterDatabase:
      properties:
        DSN:
          type: string
        Driver:
          type: string
        Host:
          type: string
        Incomplete:
          description: Incomplete reports a database that exists but could not be fully provisioned yet; a later rotation completes it.
          type: boolean
        Name:
          type: string
        Password:
          type: string
        Port:
          type: integer
        RotatedAt:
          type: string
        User:
          type: string
      type: object
    cluster.RegisterResponse:
      properties:
        AlreadyProvisioned:
          type: boolean
        AlreadyRegistered:
          type: boolean
        ClusterCIDR:
          type: string
        Database:
          $ref: '#/components/schemas/cluster.RegisterDatabase'
        JWKSUrl:
          type: string
        Node:
          $ref: '#/components/schemas/cluster.Node'
        PortalLoginUrl:
          type: string
        Secrets:
          $ref: '#/components/schemas/cluster.RegisterSecrets'
        Theme:
          type: string
        UUID:
          description: ClusterUUID
          type: string
      type: object
    cluster.RegisterSecrets:
      properties:
        ClientSecret:
          type: string
        RotatedAt:
          type: string
      type: object
    i18n.Response:
      properties:
        code:
          type: integer
        details:
          type: string
        error:
          type: string
        message:
          type: string
        messageId:
          type: string
        messageParams:
          items: {}
          type: array
      type: object
    cluster.DatabaseInfo:
      properties:
        Driver:
          type: string
        Host:
          type: string
        Port:
          type: integer
      type: object
    cluster.MetricsResponse:
      properties:
        ClusterCIDR:
          type: string
        Nodes:
          additionalProperties:
            type: integer
          type: object
        Time:
          type: string
        UUID:
          type: string
      type: object
    cluster.NodeDatabase:
      properties:
        Driver:
          type: string
        Name:
          type: string
        RotatedAt:
          type: string
        User:
          type: string
      type: object
    api.HealthResponse:
      properties:
        status:
          type: string
        time:
          type: string
      type: object
    cluster.StatusResponse:
      properties:
        Status:
          type: string
      type: object
  securitySchemes:
    BearerAuth:
      in: header
      name: Authorization
      type: apiKey
externalDocs:
  description: Learn more ›
  url: https://docs.photoprism.app/developer-guide/api/