{
  "openapi": "3.1.0",
  "info": {
    "title": "ALMa API",
    "description": "\n    REST API for ALMa \u2014 Another Library Manager.\n\n    This API provides endpoints for:\n    - **Authors**: Manage monitored authors\n    - **Papers**: Query and filter papers\n    - **Plugins**: Configure messaging platform plugins\n    - **System**: Health checks and statistics\n\n    ## Authentication\n\n    The API supports optional authentication via API key:\n    - Set the `API_KEY` environment variable to enable authentication\n    - Provide the key via `X-API-Key` header or `Bearer` token\n    - If no `API_KEY` is set, all requests are allowed (development mode)\n\n    ## Rate Limiting\n\n    Rate limiting will be implemented in a future version.\n\n    ## Examples\n\n    ### List all authors\n    ```bash\n    curl http://localhost:8000/api/v1/authors\n    ```\n\n    ### Add a new author\n    ```bash\n    curl -X POST http://localhost:8000/api/v1/authors \\\n         -H \"Content-Type: application/json\" \\\n         -d '{\"scholar_id\": \"abc123xyz\"}'\n    ```\n\n    ### Query papers\n    ```bash\n    curl \"http://localhost:8000/api/v1/papers?min_year=2023&min_citations=10\"\n    ```\n\n    ### Configure a plugin\n    ```bash\n    curl -X PUT http://localhost:8000/api/v1/plugins/slack/config \\\n         -H \"Content-Type: application/json\" \\\n         -d '{\"config\": {\"api_token\": \"replace-with-real-slack-token\", \"channel\": \"#general\"}}'\n    ```\n    ",
    "contact": {
      "name": "ALMa",
      "url": "https://github.com/costantinoai/alma-library-manager"
    },
    "license": {
      "name": "CC BY-NC 4.0",
      "url": "https://creativecommons.org/licenses/by-nc/4.0/"
    },
    "version": "1.0.0"
  },
  "paths": {
    "/api": {
      "get": {
        "summary": "Api Root",
        "description": "API root endpoint.",
        "operationId": "api_root_api_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Health check",
        "description": "Check the health status of the API and its dependencies.",
        "operationId": "health_check_api_v1_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/version": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Version information",
        "description": "Get version information for the API and application.",
        "operationId": "version_info_api_v1_version_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/stats": {
      "get": {
        "tags": [
          "system"
        ],
        "summary": "Overall statistics",
        "description": "Get aggregate statistics about the system.",
        "operationId": "get_statistics_api_v1_stats_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatisticsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "List all authors",
        "description": "Retrieve a list of all monitored authors with their metadata.",
        "operationId": "list_authors_api_v1_authors_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuthorResponse"
                  },
                  "title": "Response List Authors Api V1 Authors Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Add a new author",
        "description": "Add a new author to monitor by their Google Scholar ID.",
        "operationId": "create_author_api_v1_authors_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthorCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/lookup": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Look up an author by display name",
        "description": "Return a compact author record matched by normalized display name. Intended for lightweight UI previews (hover cards on paper bylines). Returns 404 when no corpus row matches the name.",
        "operationId": "lookup_author_api_v1_authors_lookup_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Author display name",
              "title": "Name"
            },
            "description": "Author display name"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/suggestions": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "List collaborator and adjacent author suggestions",
        "operationId": "list_author_suggestions_api_v1_authors_suggestions_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 30,
              "minimum": 1,
              "default": 5,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AuthorSuggestionResponse"
                  },
                  "title": "Response List Author Suggestions Api V1 Authors Suggestions Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/suggestions/merge-into": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Import a duplicate suggestion into the followed author it matches",
        "description": "For a suggestion flagged `duplicate_of` an existing followed author: fold the suggested external OpenAlex profile into that author (reassign its papers, record its id as an alias) instead of following it as a new person. Foreground write via run_write_unit.",
        "operationId": "merge_suggestion_into_endpoint_api_v1_authors_suggestions_merge_into_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MergeSuggestionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/suggestions/not-duplicate": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Mark a flagged duplicate suggestion as NOT a duplicate",
        "description": "The user says a suggestion flagged `duplicate_of` is actually a different person. Records the OpenAlex id so it's no longer flagged \u2014 it returns to the normal 'follow a new author' rail instead of being suppressed. Foreground write via run_write_unit.",
        "operationId": "mark_suggestion_not_duplicate_endpoint_api_v1_authors_suggestions_not_duplicate_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NotDuplicateRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/suggestions/reject": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Reject an author suggestion",
        "description": "Records a negative signal for this OpenAlex author so they are suppressed from future /authors/suggestions responses.",
        "operationId": "reject_author_suggestion_api_v1_authors_suggestions_reject_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RejectSuggestionRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/suggestions/track-follow": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Log a rail-originated author follow for outcome calibration",
        "description": "Fire-and-forget call from the Suggested Authors rail after a follow succeeds, so per-bucket outcome calibration can attribute the positive event to the bucket that surfaced the author. The actual follow write goes through the existing follow / author-create routes \u2014 this is the calibration log only.",
        "operationId": "track_followed_suggestion_api_v1_authors_suggestions_track_follow_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrackFollowSuggestionRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/suggestions/refresh-network": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Refresh OpenAlex + S2 author-suggestion caches (Activity-envelope)",
        "description": "Enqueues up to two Activity-envelope jobs, one per network source, that populate the `author_suggestion_cache` table. Sources whose cache is still fresh are skipped. Each job writes its own envelope; the response aggregates both.",
        "operationId": "refresh_author_suggestion_network_api_v1_authors_suggestions_refresh_network_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshAuthorNetworkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/backfill-works": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Backfill full works + SPECTER2 vectors for corpus authors (Activity-envelope)",
        "description": "Fetches every OpenAlex work for the target author(s), upserts papers + publication_authors rows, batch-fetches missing SPECTER2 vectors from Semantic Scholar, then recomputes the author_centroids entry.",
        "operationId": "backfill_author_works_api_v1_authors_backfill_works_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BackfillAuthorWorksRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/follow-from-paper": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Follow an author directly from a paper card",
        "operationId": "follow_author_from_paper_api_v1_authors_follow_from_paper_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthorFollowFromPaperRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorFollowFromPaperResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/needs-attention": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Authors whose identity / refresh needs manual attention",
        "description": "Surface authors that the automatic resolver couldn't finish: ambiguous name-based matches, OpenAlex 404s, last-refresh errors. Each row carries a human-readable reason + suggested next action so the UI can render a direct fix button.",
        "operationId": "list_authors_needs_attention_api_v1_authors_needs_attention_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/enrichment-status": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Author metadata hydration ledger",
        "description": "Read-only summary of author profile / affiliation hydration ledger rows.",
        "operationId": "get_author_enrichment_status_api_v1_authors_enrichment_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/identifiers": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Manually set authoritative identifiers for an author",
        "description": "Used by the Authors Needs-Attention 'Add identifier' action. Updates ORCID / OpenAlex / Scholar id on the row, sets id_resolution_status='resolved_manual', and clears any previous needs-attention reason. Subsequent refreshes use the provided OpenAlex id directly without re-running the resolver.",
        "operationId": "set_author_identifiers_api_v1_authors__author_id__identifiers_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetIdentifiersRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/merge-profiles": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Merge alt OpenAlex profiles into a primary author",
        "description": "Used by the Authors Needs-Attention 'Review profiles' dialog to collapse multiple OpenAlex IDs that represent the same human into one canonical row. For each alt: papers reattach to the primary's openalex_id, the alt's followed_authors / feed_monitors entries are dropped, the alt row is soft-removed (D3 lifecycle), and an `author_alt_identifiers` row records the alias so suggestion-rail dedup never resurfaces it.",
        "operationId": "merge_author_profiles_route_api_v1_authors__author_id__merge_profiles_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MergeProfilesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/conflicts/{conflict_id}/resolve": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Resolve a merge conflict by picking one side or dismissing",
        "operationId": "resolve_merge_conflict_api_v1_authors_conflicts__conflict_id__resolve_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "conflict_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Conflict Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveConflictRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/discover-aliases": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Discover OpenAlex split profiles via ORCID",
        "description": "Looks up the author's ORCID on OpenAlex and queries every OpenAlex author profile sharing that ORCID. ORCID is person-level and verified, so co-occurrence is high-confidence evidence of a split profile. Returns the alias list for the user to merge via /merge-profiles. Read-only \u2014 does not modify any rows.",
        "operationId": "discover_author_aliases_api_v1_authors__author_id__discover_aliases_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/merge-candidates": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "List pending author merge candidates (the review queue)",
        "description": "The duplicate author pairs the scan recorded and that haven't been merged yet \u2014 each with both names, its `source` ('orcid'/'name') + `confidence`, and the number of papers the merge would reassign. Drives the Merge card's review dialog. Defined before /{author_id} so the static path isn't shadowed.",
        "operationId": "list_merge_candidates_endpoint_api_v1_authors_merge_candidates_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "default": 200,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/merge-candidates/{candidate_id}/reject": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Reject one merge suggestion (permanent \u2014 never resurfaced)",
        "description": "The user says 'these two are NOT the same person'. Records a permanent rejection of the unordered author pair and drops the candidate, so every future scan skips it. Foreground write through the request's gated connection (run_write_unit).",
        "operationId": "reject_merge_candidate_endpoint_api_v1_authors_merge_candidates__candidate_id__reject_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "candidate_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Candidate Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/merge-candidates/{candidate_id}/merge": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Apply one merge suggestion (the per-row \u2713 Merge)",
        "description": "Merge this candidate's alt \u2192 primary (richer/followed profile wins, the other's papers reassigned) and consume the candidate. Destructive, not reversed automatically. Foreground write through the request's gated connection (run_write_unit).",
        "operationId": "merge_one_candidate_endpoint_api_v1_authors_merge_candidates__candidate_id__merge_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "candidate_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Candidate Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Get author details",
        "description": "Retrieve detailed information about a specific author.",
        "operationId": "get_author_api_v1_authors__author_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "authors"
        ],
        "summary": "Delete an author",
        "description": "Remove an author and all their cached publications from the system.",
        "operationId": "delete_author_api_v1_authors__author_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/remove": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Soft-remove an author",
        "description": "Soft-remove an author (status='removed', D3): the row + provenance stay for the Corpus explorer and Discovery's negative signal, and it drops out of active author views. Reversible. This is the normal-flow removal (e.g. the suggestion-detail Delete, alongside the suggestion dismiss); the hard DELETE is reserved for explicit purges.",
        "operationId": "remove_author_api_v1_authors__author_id__remove_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/type": {
      "patch": {
        "tags": [
          "authors"
        ],
        "summary": "Update author type",
        "description": "Set author classification: followed or background.",
        "operationId": "update_author_type_api_v1_authors__author_id__type_patch",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthorTypeUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/resolve-openalex": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Resolve OpenAlex candidates from a Scholar ID",
        "description": "Fetch name+affiliation+one work from Scholar, search OpenAlex works and return candidate authors for confirmation.",
        "operationId": "resolve_openalex_from_scholar_api_v1_authors_resolve_openalex_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveOpenAlexRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/confirm-openalex": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Confirm OpenAlex author for an existing Scholar author",
        "description": "Attach OpenAlex ID and ORCID to the existing author row.",
        "operationId": "confirm_openalex_for_author_api_v1_authors__author_id__confirm_openalex_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmOpenAlexRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/id-candidates": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Get identifier candidates for an author",
        "operationId": "author_id_candidates_api_v1_authors__author_id__id_candidates_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/search-scholar": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Manually search Google Scholar candidates for an author",
        "operationId": "author_search_scholar_manual_api_v1_authors__author_id__search_scholar_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/confirm-identifiers": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Manually confirm identifiers for an author",
        "operationId": "confirm_identifiers_for_author_api_v1_authors__author_id__confirm_identifiers_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmIdentifiersRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/resolve-identifiers": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Resolve OpenAlex/Scholar IDs for authors",
        "operationId": "resolve_identifiers_bulk_api_v1_authors_resolve_identifiers_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveIdentifiersRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/publications": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Get author's publications",
        "description": "Retrieve all cached publications for a specific author.",
        "operationId": "get_author_publications_api_v1_authors__author_id__publications_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Publication scope: all | library | background",
              "default": "all",
              "title": "Scope"
            },
            "description": "Publication scope: all | library | background"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Sort order: citations | recent",
              "default": "citations",
              "title": "Order"
            },
            "description": "Sort order: citations | recent"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "title": "Response Get Author Publications Api V1 Authors  Author Id  Publications Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/openalex-works": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Fetch a page of the author's full OpenAlex bibliography",
        "description": "Lazy cursor-paginated window onto the author's complete OpenAlex works list. Does NOT touch the local DB \u2014 use /publications for the already-saved view and /library/import/search/save to pull a work into Library. Accepts either a local author UUID (resolved to its openalex_id) or a bare OpenAlex author id (A\u2026).",
        "operationId": "list_author_openalex_works_api_v1_authors__author_id__openalex_works_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "OpenAlex cursor ('*' for the first page).",
              "default": "*",
              "title": "Cursor"
            },
            "description": "OpenAlex cursor ('*' for the first page)."
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 50,
              "title": "Per Page"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/detail": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Get lightweight author detail for the popup view",
        "description": "Profile + signal/score + top topics + monitor/backfill state. Excludes the heavier dossier lists (publications, collaborators, history).",
        "operationId": "get_author_detail_api_v1_authors__author_id__detail_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/dossier": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "Get author dossier",
        "description": "Return history, corpus split, topics, venues, collaborators, and recommended next actions for one author.",
        "operationId": "get_author_dossier_api_v1_authors__author_id__dossier_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/history-backfill": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Queue followed-author historical corpus backfill",
        "operationId": "history_backfill_author_api_v1_authors__author_id__history_backfill_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/repair": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Repair author identifiers and refreshability",
        "operationId": "repair_author_api_v1_authors__author_id__repair_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Run as a background Activity job when the scheduler is enabled",
              "title": "Background"
            },
            "description": "Run as a background Activity job when the scheduler is enabled"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/refresh-cache": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Refresh author cache (incremental)",
        "description": "Fetch latest publications since last fetch. Does NOT send notifications.",
        "operationId": "refresh_author_cache_api_v1_authors__author_id__refresh_cache_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run as background job and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run as background job and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/deep-refresh-all": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Deep refresh all refreshable authors",
        "description": "Full refresh pipeline for every selected author: hierarchical identity resolution \u2192 OpenAlex profile update (name, affiliation, institutions, citations, h-index, works_count, topics, cited_by_year, ORCID) \u2192 works + SPECTER2 vectors backfill \u2192 SPECTER2 centroid recompute. Same code the popup 'Refresh author' button runs \u2014 just iterated over the author pool. Imported-only placeholder authors without any upstream ID are skipped automatically.",
        "operationId": "deep_refresh_all_authors_api_v1_authors_deep_refresh_all_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "followed | needs_metadata | followed_plus_library | library | corpus",
              "default": "followed",
              "title": "Scope"
            },
            "description": "followed | needs_metadata | followed_plus_library | library | corpus"
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run as background job and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run as background job and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/rehydrate-metadata": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Hydrate author profile and affiliation metadata",
        "description": "Queues an Activity-backed author metadata job. The job uses a per-author/source/purpose ledger and fills profile fields plus structured affiliation evidence from OpenAlex, ORCID, Semantic Scholar, and Crossref when identifiers are available.",
        "operationId": "rehydrate_author_metadata_api_v1_authors_rehydrate_metadata_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 100000,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "description": "Maximum authors to prepare; omitted means all eligible authors",
              "title": "Limit"
            },
            "description": "Maximum authors to prepare; omitted means all eligible authors"
          },
          {
            "name": "force",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Ignore current ledger state and retry eligible authors",
              "default": false,
              "title": "Force"
            },
            "description": "Ignore current ledger state and retry eligible authors"
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run in background and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run in background and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/affiliations": {
      "get": {
        "tags": [
          "authors"
        ],
        "summary": "List affiliation evidence for one author",
        "description": "Read-only evidence rows used to pick an author's display affiliation.",
        "operationId": "get_author_affiliations_api_v1_authors__author_id__affiliations_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/affiliation": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Lock an author's display affiliation to a chosen institution",
        "description": "Terminal resolution for the 'affiliation evidence disagrees across sources' needs-attention flag (the `pick_affiliation` action). Records the choice as an authoritative manual evidence row that outranks every auto source and survives future refreshes, so the display affiliation sticks and the conflict clears for good. Gated write + Activity row.",
        "operationId": "pick_author_affiliation_api_v1_authors__author_id__affiliation_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PickAffiliationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/accept-unidentified": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Accept an author as unidentifiable (terminal \u2014 stops needs-attention flagging)",
        "description": "Terminal acknowledgment for an identity gap the resolver genuinely can't close (no_match / needs_manual_review / error / followed-without-id). Sets id_resolution_status='dismissed' so the author stops surfacing in needs-attention and the author-health counts \u2014 WITHOUT inventing an identifier. The user can still resolve it later by pasting an id (which flips it to resolved_manual). Gated write + Activity row.",
        "operationId": "accept_author_unidentified_api_v1_authors__author_id__accept_unidentified_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/dedup-by-orcid": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Scan followed authors for ORCID duplicates (record candidates)",
        "description": "Manual NON-destructive scan that walks every followed author with an OpenAlex ID, calls /authors?filter=orcid:X to discover every split profile sharing the same ORCID, then for each alias: (a) if it is another local author row, RECORDS the mergeable pair in `author_merge_candidates` for review (apply via the Merge card), or (b) records it in `author_alt_identifiers` so the suggestion rail filters it out. Never merges. Activity-enveloped \u2014 runs in the background and the Activity panel shows per-author progress.",
        "operationId": "dedup_authors_by_orcid_endpoint_api_v1_authors_dedup_by_orcid_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run as background job and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run as background job and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/garbage-collect-orphans": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Garbage-collect orphan author rows",
        "description": "Soft-removes (status='removed') every author who is (a) not followed and (b) has no publication_authors row pointing to a paper in a live state (anything other than 'removed' / 'dismissed'). Mirrors the lifecycle pattern used for papers (D3): the row stays in the table so Discovery can read it as a negative signal, but it's filtered out of bulk refresh and the canonical author list. Pass dry_run=true to preview without committing.",
        "operationId": "garbage_collect_orphan_authors_endpoint_api_v1_authors_garbage_collect_orphans_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Preview without writing",
              "default": false,
              "title": "Dry Run"
            },
            "description": "Preview without writing"
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run as background job and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run as background job and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/identity-profile-refresh": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Refresh author identity/profile",
        "description": "Refreshes identity and profile metadata only. Does not paginate works, fetch S2 vectors, or recompute the centroid unless the resolved identity changes.",
        "operationId": "identity_profile_refresh_author_api_v1_authors__author_id__identity_profile_refresh_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run as background job and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run as background job and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/deep-refresh": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Deep refresh author (full re-fetch)",
        "description": "Full re-fetch of all publications ignoring last_fetched_at. Use sparingly.",
        "operationId": "deep_refresh_author_api_v1_authors__author_id__deep_refresh_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run as background job and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run as background job and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/empty-cache": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Empty author cache",
        "description": "Delete all cached publications for the specified author without removing the author.",
        "operationId": "empty_author_cache_api_v1_authors__author_id__empty_cache_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/fetch-preview": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Fetch preview for author (Activity-backed)",
        "description": "Queue a background job that fetches latest publications for an author and stores the preview as the job's result. Returns an Activity envelope; poll `/activity/{job_id}/logs` or read `operation_status.result` on completion.",
        "operationId": "fetch_preview_author_api_v1_authors__author_id__fetch_preview_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/authors/{author_id}/preview/save": {
      "post": {
        "tags": [
          "authors"
        ],
        "summary": "Save preview publications to DB",
        "description": "Persist selected preview items to the publications database.",
        "operationId": "save_preview_publications_api_v1_authors__author_id__preview_save_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SavePublicationsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers": {
      "get": {
        "tags": [
          "papers"
        ],
        "summary": "Query papers",
        "description": "Search and filter papers across all authors.",
        "operationId": "query_publications_api_v1_papers_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Paper scope: all | library | background | followed_corpus",
              "title": "Scope"
            },
            "description": "Paper scope: all | library | background | followed_corpus"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Membership status: tracked | library | dismissed | removed",
              "title": "Status"
            },
            "description": "Membership status: tracked | library | dismissed | removed"
          },
          {
            "name": "added_from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by acquisition/provenance value",
              "title": "Added From"
            },
            "description": "Filter by acquisition/provenance value"
          },
          {
            "name": "openalex_resolution_status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by OpenAlex resolution status",
              "title": "Openalex Resolution Status"
            },
            "description": "Filter by OpenAlex resolution status"
          },
          {
            "name": "has_topics",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by presence of publication_topics rows",
              "title": "Has Topics"
            },
            "description": "Filter by presence of publication_topics rows"
          },
          {
            "name": "has_tags",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by presence of publication_tags rows",
              "title": "Has Tags"
            },
            "description": "Filter by presence of publication_tags rows"
          },
          {
            "name": "author_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional author ID to constrain results to one author corpus",
              "title": "Author Id"
            },
            "description": "Optional author ID to constrain results to one author corpus"
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by specific year",
              "title": "Year"
            },
            "description": "Filter by specific year"
          },
          {
            "name": "min_year",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Minimum year (inclusive)",
              "title": "Min Year"
            },
            "description": "Minimum year (inclusive)"
          },
          {
            "name": "max_year",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Maximum year (inclusive)",
              "title": "Max Year"
            },
            "description": "Maximum year (inclusive)"
          },
          {
            "name": "min_citations",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Minimum citations",
              "title": "Min Citations"
            },
            "description": "Minimum citations"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Search in title and abstract",
              "title": "Search"
            },
            "description": "Search in title and abstract"
          },
          {
            "name": "semantic",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Enable semantic search (requires AI provider)",
              "default": false,
              "title": "Semantic"
            },
            "description": "Enable semantic search (requires AI provider)"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Sort order: citations | recent | title | rating | authors | journal | status | added_at",
              "title": "Order"
            },
            "description": "Sort order: citations | recent | title | rating | authors | journal | status | added_at"
          },
          {
            "name": "order_dir",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Sort direction: asc | desc",
              "title": "Order Dir"
            },
            "description": "Sort direction: asc | desc"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "description": "Maximum results",
              "default": 100,
              "title": "Limit"
            },
            "description": "Maximum results"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Results to skip",
              "default": 0,
              "title": "Offset"
            },
            "description": "Results to skip"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PaperResponse"
                  },
                  "title": "Response Query Publications Api V1 Papers Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/semantic-search": {
      "post": {
        "tags": [
          "papers"
        ],
        "summary": "Run explicit SPECTER2 semantic paper search",
        "description": "Embed a short query with the SPECTER2 adhoc-query adapter and compare against cached S2/SPECTER2 paper vectors. Runs through Activity because query embedding is live AI inference.",
        "operationId": "semantic_paper_search_api_v1_papers_semantic_search_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SemanticPaperSearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Semantic Paper Search Api V1 Papers Semantic Search Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/enrichment-status": {
      "get": {
        "tags": [
          "papers"
        ],
        "summary": "Get paper metadata enrichment bookkeeping",
        "description": "Pure-read status for corpus metadata rehydration. Reports per-paper ledger counts and current OpenAlex metadata repair eligibility without performing any external API calls or writes.",
        "operationId": "get_paper_enrichment_status_api_v1_papers_enrichment_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Enrichment source; currently only openalex",
              "default": "openalex",
              "title": "Source"
            },
            "description": "Enrichment source; currently only openalex"
          },
          {
            "name": "purpose",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Enrichment purpose; currently only metadata",
              "default": "metadata",
              "title": "Purpose"
            },
            "description": "Enrichment purpose; currently only metadata"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional ledger status filter",
              "title": "Status"
            },
            "description": "Optional ledger status filter"
          },
          {
            "name": "paper_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional paper id to inspect",
              "title": "Paper Id"
            },
            "description": "Optional paper id to inspect"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 0,
              "description": "Number of per-paper ledger rows to include",
              "default": 20,
              "title": "Limit"
            },
            "description": "Number of per-paper ledger rows to include"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Per-paper ledger row offset",
              "default": 0,
              "title": "Offset"
            },
            "description": "Per-paper ledger row offset"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Get Paper Enrichment Status Api V1 Papers Enrichment Status Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/rehydrate-metadata": {
      "post": {
        "tags": [
          "papers"
        ],
        "summary": "Rehydrate missing paper metadata from OpenAlex",
        "description": "Queues an Activity-backed corpus repair job. The job batches OpenAlex work IDs, records one ledger row per paper/source/purpose, skips already-covered lookup/projection pairs, and writes only improving paper metadata.",
        "operationId": "rehydrate_paper_metadata_api_v1_papers_rehydrate_metadata_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 100000,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "description": "Maximum papers to inspect in this run; omit to process all eligible papers",
              "title": "Limit"
            },
            "description": "Maximum papers to inspect in this run; omit to process all eligible papers"
          },
          {
            "name": "force",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Ignore terminal ledger rows and refetch matching lookup/projection pairs",
              "default": false,
              "title": "Force"
            },
            "description": "Ignore terminal ledger rows and refetch matching lookup/projection pairs"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Rehydrate Paper Metadata Api V1 Papers Rehydrate Metadata Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/stats": {
      "get": {
        "tags": [
          "papers"
        ],
        "summary": "Get paper statistics",
        "description": "Get aggregate statistics about papers in the database.",
        "operationId": "get_publication_stats_api_v1_papers_stats_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "min_year",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Minimum publication year to include",
              "title": "Min Year"
            },
            "description": "Minimum publication year to include"
          },
          {
            "name": "max_year",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Maximum publication year to include",
              "title": "Max Year"
            },
            "description": "Maximum publication year to include"
          },
          {
            "name": "top_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Top authors/papers limit",
              "default": 10,
              "title": "Top Limit"
            },
            "description": "Top authors/papers limit"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}/action": {
      "post": {
        "tags": [
          "papers"
        ],
        "summary": "Apply a user action to a paper (the canonical triage route)",
        "description": "THE route for every paper action, from every surface. Feed, Discovery, Inbox, Map, Library and onboarding all come through here, so 'what does Like mean' has exactly one answer.\n\nPass `surface` so feedback provenance reflects where the user acted. `feed` and `discovery` additionally require `scope_ref` \u2014 their own row id \u2014 because they settle that row rather than the paper globally: dismissing in one lens must not mute the paper in another.",
        "operationId": "apply_paper_action_route_api_v1_papers__paper_id__action_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaperActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaperActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}/rate": {
      "put": {
        "tags": [
          "papers"
        ],
        "summary": "Rate a paper",
        "description": "Set a star rating (0-5) for a saved Library paper.",
        "operationId": "rate_publication_api_v1_papers__paper_id__rate_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "rating",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "description": "Star rating from 0 to 5",
              "title": "Rating"
            },
            "description": "Star rating from 0 to 5"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}/undo-feedback": {
      "post": {
        "tags": [
          "papers"
        ],
        "summary": "Undo one dimension of a paper's user feedback",
        "description": "Per-aspect toggle-off: each action button undoes only its own effect. `aspect=membership` removes from library; `rating` clears the like/love/dislike rating; `reading` clears the reading-list state; `all` is a full neutral reset. Each deletes the matching signal events.",
        "operationId": "undo_paper_feedback_endpoint_api_v1_papers__paper_id__undo_feedback_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "aspect",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "membership | rating | reading | all",
              "default": "all",
              "title": "Aspect"
            },
            "description": "membership | rating | reading | all"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}/details": {
      "get": {
        "tags": [
          "papers"
        ],
        "summary": "Get full paper details",
        "description": "Return a single paper row plus the semantic topics attached to it.",
        "operationId": "get_paper_details_api_v1_papers__paper_id__details_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}/detach": {
      "post": {
        "tags": [
          "papers"
        ],
        "summary": "Promote a merged duplicate / component back to a standalone paper",
        "description": "Clears the structural links (canonical_paper_id for a dedup/import duplicate twin; parent_paper_id + component_type for a part-of component) so the row becomes a first-class paper again. Backs the \"Not a duplicate\" / \"Not a child\" actions in the paper detail popup.",
        "operationId": "detach_paper_api_v1_papers__paper_id__detach_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}/prior-works": {
      "get": {
        "tags": [
          "papers"
        ],
        "summary": "Papers referenced by this paper (full OpenAlex graph)",
        "description": "Return every paper this paper references, fetched from OpenAlex.\n\nThe OpenAlex graph is the source of truth \u2014 local\n``publication_references`` is no longer queried for this view, so\nthe user sees the full bibliography rather than a corpus-only\nsubset. Local matches are looked up in bulk and surfaced via\n``in_library=true`` plus an attached ``paper_id`` so the Pivot\nbutton still works for in-library hits.\n\nCached for 24 h in ``paper_network_cache`` so repeat opens are\ninstant; cache key is ``paper_id + 'prior'``.",
        "operationId": "list_prior_works_api_v1_papers__paper_id__prior_works_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 30,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}/derivative-works": {
      "get": {
        "tags": [
          "papers"
        ],
        "summary": "Papers that cite this paper (full OpenAlex graph)",
        "description": "Return every paper that cites this paper, fetched from OpenAlex.\n\nUses OpenAlex's ``filter=cites:Wxxx`` query, sorted by\n``cited_by_count desc`` so high-impact citing papers surface\nfirst. Local-corpus matches are flagged via ``in_library=true``;\nthe user sees the full forward-citation graph rather than only\nlocally-known citers.\n\nCached for 24 h in ``paper_network_cache``.",
        "operationId": "list_derivative_works_api_v1_papers__paper_id__derivative_works_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 30,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/{paper_id}": {
      "delete": {
        "tags": [
          "papers"
        ],
        "summary": "Delete a paper",
        "description": "Remove a specific paper from the database.",
        "operationId": "delete_publication_api_v1_papers__paper_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/papers/dedup-preprints": {
      "post": {
        "tags": [
          "papers"
        ],
        "summary": "Detect + merge preprint\u2194journal twin papers",
        "description": "Scans for pairs where the same work exists as both a preprint (arXiv / bioRxiv / psyRxiv / chemRxiv / OSF / MDPI) and a published journal row, collapsing each pair into the journal version. `scope=library` only collapses pairs where at least one side is a saved Library paper (fast); `scope=corpus` considers every pair (can take a while on a large corpus). FK rows migrate preprint \u2192 canonical; Library + Discovery lists filter the merged preprint out automatically.",
        "operationId": "dedup_preprint_twins_api_v1_papers_dedup_preprints_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "library | corpus",
              "default": "corpus",
              "title": "Scope"
            },
            "description": "library | corpus"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Cap the number of pairs to merge",
              "title": "Limit"
            },
            "description": "Cap the number of pairs to merge"
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Queue via Activity envelope",
              "default": true,
              "title": "Background"
            },
            "description": "Queue via Activity envelope"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/plugins": {
      "get": {
        "tags": [
          "plugins"
        ],
        "summary": "List external integrations",
        "description": "Every registered external integration, its send/receive capabilities, generated configuration schema, activation, and direction status.",
        "operationId": "list_plugins_api_v1_plugins_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PluginInfo"
                  },
                  "title": "Response List Plugins Api V1 Plugins Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/plugins/{plugin_id}": {
      "get": {
        "tags": [
          "plugins"
        ],
        "summary": "Get integration details",
        "operationId": "get_plugin_api_v1_plugins__plugin_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Plugin Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginInfo"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/plugins/{plugin_id}/enabled": {
      "put": {
        "tags": [
          "plugins"
        ],
        "summary": "Activate or deactivate an integration",
        "description": "Deactivation retains credentials/configuration, stops capture polling and Alert delivery, and removes the integration's Home status pills.",
        "operationId": "set_plugin_enabled_api_v1_plugins__plugin_id__enabled_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Plugin Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PluginActivation"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginInfo"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/plugins/{plugin_id}/config": {
      "get": {
        "tags": [
          "plugins"
        ],
        "summary": "Read validated integration configuration",
        "operationId": "get_plugin_config_api_v1_plugins__plugin_id__config_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Plugin Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginConfigResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "plugins"
        ],
        "summary": "Validate and replace integration configuration",
        "operationId": "update_plugin_config_api_v1_plugins__plugin_id__config_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Plugin Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "title": "Payload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PluginConfigResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/plugins/{plugin_id}/test": {
      "post": {
        "tags": [
          "plugins"
        ],
        "summary": "Test an integration",
        "description": "Runs the integration manifest's registered connectivity test through the Activity envelope and the same transport used in production.",
        "operationId": "test_plugin_connection_api_v1_plugins__plugin_id__test_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "plugin_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Plugin Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Test Plugin Connection Api V1 Plugins  Plugin Id  Test Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/preview": {
      "post": {
        "tags": [
          "fetch"
        ],
        "summary": "Fetch & preview for all authors (Activity-backed)",
        "description": "Queue a background preview fetch across every author.\n\nThe previous implementation iterated authors synchronously in the request\nthread and held an anyio threadpool worker for the full duration of the\nremote round-trips (often many seconds). Now runs on the APS scheduler pool\nand reports progress per author; result JSON contains the combined preview.",
        "operationId": "fetch_preview_all_api_v1_fetch_preview_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/preview/save": {
      "post": {
        "tags": [
          "fetch"
        ],
        "summary": "Save preview publications (bulk) to DB",
        "description": "Persist selected preview publications as a background operation.",
        "operationId": "save_preview_publications_bulk_api_v1_fetch_preview_save_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SavePublicationsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/hard-reset": {
      "post": {
        "tags": [
          "fetch"
        ],
        "summary": "Hard reset publications database and refetch all authors",
        "description": "Schedule a background hard reset and return a job id for progress polling.",
        "operationId": "hard_reset_publications_db_api_v1_fetch_hard_reset_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/refresh-cache": {
      "post": {
        "tags": [
          "fetch"
        ],
        "summary": "Refresh cache for all authors (no send)",
        "description": "Refresh cached publications for all authors without sending notifications.",
        "operationId": "refresh_cache_all_api_v1_fetch_refresh_cache_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run in background and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run in background and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/jobs": {
      "post": {
        "tags": [
          "fetch"
        ],
        "summary": "Schedule a fetch job",
        "description": "Schedule a cron job for fetch operations.",
        "operationId": "schedule_job_api_v1_fetch_jobs_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "fetch"
        ],
        "summary": "List scheduled jobs",
        "operationId": "list_scheduled_jobs_api_v1_fetch_jobs_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/jobs/{job_id}": {
      "delete": {
        "tags": [
          "fetch"
        ],
        "summary": "Delete a scheduled job",
        "operationId": "delete_job_api_v1_fetch_jobs__job_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/jobs/{job_id}/run": {
      "post": {
        "tags": [
          "fetch"
        ],
        "summary": "Run job immediately",
        "operationId": "run_job_now_api_v1_fetch_jobs__job_id__run_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/fetch/run": {
      "post": {
        "tags": [
          "fetch"
        ],
        "summary": "Run fetch action asynchronously",
        "operationId": "run_async_action_api_v1_fetch_run_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "title": "Payload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get Settings",
        "description": "Retrieve core settings.\n\nPlugin configuration has its own schema-driven routes.",
        "operationId": "get_settings_api_v1_settings_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsModel"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "settings"
        ],
        "summary": "Update Settings",
        "description": "Update core settings locally.\n\nNotes:\n- `backend` must be either `scholar` or `openalex`\n- `openalex_email` is optional and sent as a contact parameter for OpenAlex requests\n- All paths MUST be relative (e.g., ./data/scholar.db)\n- No external APIs are called as part of this endpoint",
        "operationId": "update_settings_api_v1_settings_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingsModel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsModel"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/export": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Export Data Snapshot",
        "description": "Export a full JSON snapshot for backup/migration use.\n\nIncludes sanitized settings and core DB tables.",
        "operationId": "export_data_snapshot_api_v1_settings_export_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/test/openalex": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Test Openalex Connectivity",
        "description": "Test connectivity to the OpenAlex API via shared client.",
        "operationId": "test_openalex_connectivity_api_v1_settings_test_openalex_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/openalex/usage": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get Openalex Usage",
        "description": "Return current OpenAlex credit/rate usage from the shared client.",
        "operationId": "get_openalex_usage_api_v1_settings_openalex_usage_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/openalex/status": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get Openalex Status",
        "description": "Report whether the OpenAlex API key is configured and, if so, whether\na live probe accepts it. Drives the connection pill in Settings \u2192\nConnections \u2192 OpenAlex, mirroring the Semantic Scholar status contract.\n\nStates (green dot = ``valid is True``):\n  - ``configured=False`` \u2014 no key set (env or secret store).\n  - ``valid=True``       \u2014 probe returned 200, or 429 (key authenticated\n                           before the rate limiter applied).\n  - ``valid=False``      \u2014 OpenAlex rejected the key (401 / 403).\n  - ``valid=None``       \u2014 probe could not complete / unexpected status.\n\nThe probe hits ``/rate-limit`` directly (bypasses the response cache) so\na manual re-check always re-probes with the current key.",
        "operationId": "get_openalex_status_api_v1_settings_openalex_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/semantic-scholar/status": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Get Semantic Scholar Status",
        "description": "Report whether the Semantic Scholar key is configured and, if so,\nwhether a live authenticated probe accepts it. Drives the connection dot\nin Settings \u2192 Connections \u2192 Semantic Scholar.\n\nStates (green dot = ``valid is True``):\n  - ``configured=False``         \u2014 no key set (env or secret store).\n  - ``valid=True``               \u2014 probe returned 200, OR 429 (the key\n                                   was accepted; S2 authenticates before\n                                   applying the 1 req/s throttle).\n  - ``valid=False``              \u2014 S2 rejected the key (401 / 403).\n  - ``valid=None``               \u2014 probe could not complete (network /\n                                   timeout / unexpected status); unknown.\n\nThe probe is a single cheapest-possible `/paper/search?limit=1` call with\na short timeout and no retries \u2014 it is on-demand only (card mount / manual\nrefresh), so it doesn't meaningfully spend the 1 req/s budget.",
        "operationId": "get_semantic_scholar_status_api_v1_settings_semantic_scholar_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/test/scholar": {
      "get": {
        "tags": [
          "settings"
        ],
        "summary": "Test Scholar Connectivity",
        "description": "Best-effort test for scholarly availability (no real scrape).",
        "operationId": "test_scholar_connectivity_api_v1_settings_test_scholar_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/saved": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "List library papers",
        "description": "Return all library papers with optional search and pagination.",
        "operationId": "list_saved_api_v1_library_saved_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Search in title or notes",
              "title": "Search"
            },
            "description": "Search in title or notes"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Sort order: date | rating | signal | title | authors | journal | citations | added_at. 'signal' = the paper_signal composite ranking (not the user's star rating).",
              "default": "date",
              "title": "Order"
            },
            "description": "Sort order: date | rating | signal | title | authors | journal | citations | added_at. 'signal' = the paper_signal composite ranking (not the user's star rating)."
          },
          {
            "name": "order_dir",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Sort direction: asc | desc",
              "default": "desc",
              "title": "Order Dir"
            },
            "description": "Sort direction: asc | desc"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PaperResponse"
                  },
                  "title": "Response List Saved Api V1 Library Saved Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Add paper to library",
        "description": "Add a paper to the library.",
        "operationId": "save_publication_api_v1_library_saved_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_SavePaperRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaperResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/saved/{paper_id}": {
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Remove paper from library",
        "description": "Remove a paper from library.",
        "operationId": "unsave_publication_api_v1_library_saved__paper_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "library"
        ],
        "summary": "Update notes/rating on a library paper",
        "description": "Update editable fields on a library paper.\n\nAccepts any subset of: notes, rating, title, authors, abstract.\nSoft-edit pathway used by the PaperDetailPanel `...` menu so\nthe user can repair imports whose title / author list / abstract\ncame in malformed (typical for legacy BibTeX rows). Rating still\nwrites a feedback event; the metadata fields are silent edits.",
        "operationId": "update_saved_paper_api_v1_library_saved__paper_id__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "notes",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Notes"
            }
          },
          {
            "name": "rating",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Rating"
            }
          },
          {
            "name": "title",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Title"
            }
          },
          {
            "name": "authors",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authors"
            }
          },
          {
            "name": "abstract",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Abstract"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaperResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/bulk/clear-rating": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Bulk clear rating on library papers (set rating to 0)",
        "description": "Set rating to 0 for multiple library papers (paper stays saved).",
        "operationId": "bulk_clear_rating_api_v1_library_bulk_clear_rating_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_BulkActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_BulkActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/bulk/remove": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Bulk remove papers from library",
        "description": "Remove multiple papers from library with soft-remove semantics.",
        "operationId": "bulk_remove_api_v1_library_bulk_remove_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_BulkActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_BulkActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/bulk/add-to-collection": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Bulk add papers to a collection",
        "description": "Add multiple saved Library papers to a collection at once.",
        "operationId": "bulk_add_to_collection_api_v1_library_bulk_add_to_collection_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_BulkAddToCollectionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_BulkActionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/collections": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "List collections",
        "description": "Return all collections with item counts and health metrics.",
        "operationId": "list_collections_api_v1_library_collections_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CollectionResponse"
                  },
                  "title": "Response List Collections Api V1 Library Collections Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Create a collection",
        "description": "Create a new collection.",
        "operationId": "create_collection_api_v1_library_collections_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollectionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/collections/{collection_id}": {
      "put": {
        "tags": [
          "library"
        ],
        "summary": "Update a collection",
        "description": "Update name, description, or color of a collection.",
        "operationId": "update_collection_api_v1_library_collections__collection_id__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Collection Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CollectionCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CollectionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Delete a collection",
        "description": "Delete a collection and cascade-remove its items.",
        "operationId": "delete_collection_api_v1_library_collections__collection_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Collection Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/papers/{paper_id}/collections": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Save a paper and add it to selected collections",
        "description": "Compound paper-card action: Library promotion plus memberships.",
        "operationId": "save_paper_to_collections_api_v1_library_papers__paper_id__collections_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_AddPaperToCollectionsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/collections/{collection_id}/items": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Add paper to collection",
        "description": "Add a saved Library paper to a collection.",
        "operationId": "add_collection_item_api_v1_library_collections__collection_id__items_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Collection Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_AddItemBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "library"
        ],
        "summary": "List papers in a collection",
        "description": "List all papers in a collection.",
        "operationId": "list_collection_items_api_v1_library_collections__collection_id__items_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Collection Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PaperResponse"
                  },
                  "title": "Response List Collection Items Api V1 Library Collections  Collection Id  Items Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/collections/{collection_id}/items/{paper_id}": {
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Remove paper from collection",
        "description": "Remove a paper from a collection.",
        "operationId": "remove_collection_item_api_v1_library_collections__collection_id__items__paper_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "collection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Collection Id"
            }
          },
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/tags": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "List all tags",
        "description": "Return all tags.",
        "operationId": "list_tags_api_v1_library_tags_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagResponse"
                  },
                  "title": "Response List Tags Api V1 Library Tags Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Create a tag",
        "description": "Create a new tag.",
        "operationId": "create_tag_api_v1_library_tags_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TagCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/tags/{tag_id}": {
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Delete a tag",
        "description": "Delete a tag and cascade-remove its publication assignments.",
        "operationId": "delete_tag_api_v1_library_tags__tag_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "tag_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Tag Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/tags/assign": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Assign tag to paper",
        "description": "Assign a tag to a saved Library paper.",
        "operationId": "assign_tag_api_v1_library_tags_assign_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_AssignTagBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/tags/assign/{paper_id}/{tag_id}": {
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Remove tag from paper",
        "description": "Remove a tag assignment from a paper.",
        "operationId": "remove_tag_assignment_api_v1_library_tags_assign__paper_id___tag_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "tag_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Tag Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/topics": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "List canonical topics and aliases",
        "operationId": "list_topics_api_v1_library_topics_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TopicSummary"
                  },
                  "title": "Response List Topics Api V1 Library Topics Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Create a canonical topic",
        "operationId": "create_topic_api_v1_library_topics_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TopicCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopicSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/topics/hierarchy": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "Get OpenAlex topic hierarchy with paper counts",
        "description": "Return OpenAlex topic hierarchy (domain/field/subfield) with paper counts.",
        "operationId": "get_topic_hierarchy_api_v1_library_topics_hierarchy_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopicHierarchyResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/topics/aliases": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Create or update a topic alias",
        "operationId": "create_topic_alias_api_v1_library_topics_aliases_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TopicAliasCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopicSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/topics/{topic_name}": {
      "put": {
        "tags": [
          "library"
        ],
        "summary": "Rename a canonical topic",
        "operationId": "rename_topic_api_v1_library_topics__topic_name__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "topic_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Topic Name"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TopicRenameRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopicSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Delete a canonical topic mapping",
        "operationId": "delete_topic_api_v1_library_topics__topic_name__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "topic_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Topic Name"
            }
          },
          {
            "name": "replacement",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional replacement canonical topic for existing aliases",
              "title": "Replacement"
            },
            "description": "Optional replacement canonical topic for existing aliases"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/topics/group": {
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Group one topic under another canonical topic",
        "operationId": "group_topic_api_v1_library_topics_group_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TopicGroupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopicSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/topics/aliases/{alias_name}": {
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Delete a topic alias",
        "operationId": "delete_topic_alias_api_v1_library_topics_aliases__alias_name__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alias_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alias Name"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/followed-authors": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "List followed authors",
        "description": "Return all followed authors, joining with the authors table for display names.\n\nDeliberately fast: the canonical author *signal* is computed by the\nseparate ``/followed-authors/signals`` endpoint so the grid (which drives\noff this list) never waits on the signal context build, and a dismiss that\ninvalidates this list updates the grid instantly.",
        "operationId": "list_followed_authors_api_v1_library_followed_authors_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/FollowedAuthorResponse"
                  },
                  "title": "Response List Followed Authors Api V1 Library Followed Authors Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "library"
        ],
        "summary": "Follow an author",
        "description": "Start following an author.\n\nIdempotent: following an already-followed author returns the existing\nfollow instead of erroring \u2014 the user's intent (\"this author should be\nfollowed\") is already satisfied, and a 409 here turned harmless client\nretries / double-submits into scary error toasts.",
        "operationId": "follow_author_api_v1_library_followed_authors_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FollowAuthorRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FollowedAuthorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/followed-authors/signals": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "Canonical author signals for every followed author",
        "description": "Batched author-signal map keyed by author_id. Split from the followed-authors list so the (slow) signal context build never blocks the (fast) list that drives the grid. Computed on demand.",
        "operationId": "list_followed_author_signals_api_v1_library_followed_authors_signals_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/followed-authors/{author_id}": {
      "delete": {
        "tags": [
          "library"
        ],
        "summary": "Unfollow an author",
        "description": "Stop following an author.",
        "operationId": "unfollow_author_api_v1_library_followed_authors__author_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Author Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/papers/{paper_id}/reading-status": {
      "patch": {
        "tags": [
          "library"
        ],
        "summary": "Update paper reading status",
        "description": "Update the reading status of any tracked paper.\n\nD2 lifecycle (post-2026-04-26): reading state \u2208 {None, reading,\ndone, excluded}. Membership of the reading list IS `reading` \u2014\nthere's no separate `queued` step. The legacy `queued` value is\nsilently coerced to `reading` for back-compat with any client\nstill sending it.",
        "operationId": "update_reading_status_api_v1_library_papers__paper_id__reading_status_patch",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReadingStatusUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaperResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/reading-queue": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "Get reading list grouped by status",
        "description": "Return the reading list grouped by status.\n\nD2 lifecycle (post-2026-04-26): reading state \u2208 {None, reading,\ndone, excluded}. The legacy `queued` bucket has been retired \u2014\nmembership of the reading list IS `reading`. Reading state stays\nindependent from library membership: marking reading does not\nsave, saving does not mark reading.",
        "operationId": "get_reading_queue_api_v1_library_reading_queue_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadingQueueResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/workflow-summary": {
      "get": {
        "tags": [
          "library"
        ],
        "summary": "Get library workflow summary",
        "description": "Return a workflow-oriented summary of the library state.",
        "operationId": "get_library_workflow_summary_api_v1_library_workflow_summary_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/preflight/bibtex": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Preview enrichment cost for a BibTeX file upload",
        "description": "Parse a BibTeX file without writing rows and forecast enrichment cost.",
        "operationId": "preflight_bibtex_file_endpoint_api_v1_library_import_preflight_bibtex_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_preflight_bibtex_file_endpoint_api_v1_library_import_preflight_bibtex_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportPreflightResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/preflight/bibtex/text": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Preview enrichment cost for pasted BibTeX text",
        "description": "Parse pasted BibTeX without writing rows and forecast enrichment cost.",
        "operationId": "preflight_bibtex_text_endpoint_api_v1_library_import_preflight_bibtex_text_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BibtexTextImportRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportPreflightResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/preflight/zotero/rdf": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Preview enrichment cost for a Zotero RDF export",
        "description": "Parse Zotero RDF without writing rows and forecast enrichment cost.",
        "operationId": "preflight_zotero_rdf_file_endpoint_api_v1_library_import_preflight_zotero_rdf_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_preflight_zotero_rdf_file_endpoint_api_v1_library_import_preflight_zotero_rdf_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportPreflightResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/preflight/zotero": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Preview enrichment cost for a Zotero library import",
        "description": "Fetch Zotero metadata without writing rows and forecast enrichment cost.",
        "operationId": "preflight_zotero_endpoint_api_v1_library_import_preflight_zotero_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ZoteroImportRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportPreflightResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/bibtex": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Import from a BibTeX file upload",
        "description": "Upload a .bib file and import every entry into Saved Library.\n\nThe file contents are read from the request before any work starts so the\nbackground worker does not depend on request-scoped state. Duplicates that\nalready have a canonical `papers` row are promoted into Library instead of\nsilently skipped. Tags on each BibTeX entry become local tags.\n\nBy default the import runs as a background Activity job when the scheduler\nis available and the response is a queued envelope with `job_id` and\n`activity_url`. Pass `?background=false` to force inline execution and\nreceive the full `ImportResultResponse` in the response body (used by\ntests and minimal environments).",
        "operationId": "import_bibtex_file_endpoint_api_v1_library_import_bibtex_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Run as a background Activity job when the scheduler is enabled",
              "title": "Background"
            },
            "description": "Run as a background Activity job when the scheduler is enabled"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_import_bibtex_file_endpoint_api_v1_library_import_bibtex_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/bibtex/text": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Import from pasted BibTeX text",
        "description": "Import papers from a BibTeX string pasted into the UI.\n\nSame contract as the file-upload variant (background-first, sync fallback\nvia `?background=false`). Empty strings are rejected up front.",
        "operationId": "import_bibtex_text_endpoint_api_v1_library_import_bibtex_text_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Run as a background Activity job when the scheduler is enabled",
              "title": "Background"
            },
            "description": "Run as a background Activity job when the scheduler is enabled"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BibtexTextImportRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/zotero": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Import from a Zotero library",
        "description": "Import from a Zotero personal or group library.\n\nRequires `library_id` and either a provided `api_key` or a previously stored\nZotero key. Optional `collection_key` filters to a single Zotero collection.\nOptional `collection_name` groups the result into a local collection.\n\nZotero tags are imported as local tags; Zotero collections are mirrored as\nlocal collections. The API key is resolved in-request (before enqueueing)\nso the background worker never touches `_resolve_zotero_api_key`.",
        "operationId": "import_zotero_endpoint_api_v1_library_import_zotero_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Run as a background Activity job when the scheduler is enabled",
              "title": "Background"
            },
            "description": "Run as a background Activity job when the scheduler is enabled"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ZoteroImportRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/zotero/collections": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "List Zotero collections",
        "description": "Fetch Zotero collections via POST to avoid API key in query strings.\n\nPOST-only by design (43.3): the deleted GET wrapper took the API key as a\nquery parameter and PERSISTED it via `_resolve_zotero_api_key` \u2192 `set_secret`\n\u2014 a secret written from a URL on a read verb. The frontend only ever called\nthis POST; persisting the key belongs to the request body, not a query\nstring.",
        "operationId": "list_zotero_collections_post_endpoint_api_v1_library_import_zotero_collections_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ZoteroCollectionsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ZoteroCollectionResponse"
                  },
                  "title": "Response List Zotero Collections Post Endpoint Api V1 Library Import Zotero Collections Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/zotero/rdf": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Import from a Zotero RDF export file",
        "description": "Upload a Zotero RDF export and import every item into Saved Library.",
        "operationId": "import_zotero_rdf_file_endpoint_api_v1_library_import_zotero_rdf_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Run as a background Activity job when the scheduler is enabled",
              "title": "Background"
            },
            "description": "Run as a background Activity job when the scheduler is enabled"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_import_zotero_rdf_file_endpoint_api_v1_library_import_zotero_rdf_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/enrich": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Enrich imported publications",
        "description": "Resolve imported publications via OpenAlex to populate topics, institutions, and citations.",
        "operationId": "enrich_imports_api_v1_library_import_enrich_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run enrichment in background",
              "default": true,
              "title": "Background"
            },
            "description": "Run enrichment in background"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/unresolved": {
      "get": {
        "tags": [
          "library-import"
        ],
        "summary": "List publications not resolved via OpenAlex",
        "operationId": "list_unresolved_imported_publications_api_v1_library_import_unresolved_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 5000,
              "minimum": 1,
              "default": 200,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/staged/{paper_id}/confirm": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Save a staged low-confidence import to Library",
        "description": "Promote a reviewed low-confidence import through the Library write path.",
        "operationId": "confirm_staged_import_api_v1_library_import_staged__paper_id__confirm_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConfirmStagedImportResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/resolve-openalex": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Resolve selected or unresolved publications via OpenAlex",
        "operationId": "resolve_imported_publications_openalex_api_v1_library_import_resolve_openalex_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveImportedRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/search": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Search online sources (OpenAlex + S2 + Crossref + arXiv + bioRxiv)",
        "description": "Return a list of papers matching the query across all enabled discovery sources, ranked by query relevance (cross-source RRF + query-text match \u2014 search-engine semantics). Results are cross-source deduplicated (canonical triple) and each is decorated with `in_library`, `paper_id`, `sources` (provenance chip), `relevance`, and a personal `like_score` for the why-chips. No writes.",
        "operationId": "online_source_search_api_v1_library_import_search_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnlineSearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/search/authors": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Search OpenAlex /authors for the Find & Add author scope",
        "description": "Returns up to `limit` author candidates matching the query. The frontend uses this when the user prefixes the query with `author:` (scope=author) so the result list shows actionable author cards with a Follow button instead of paper cards. Pure read.",
        "operationId": "online_author_search_api_v1_library_import_search_authors_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnlineSearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/OnlineAuthorSearchResult"
                  },
                  "title": "Response Online Author Search Api V1 Library Import Search Authors Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/search/authors/top-works": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Top-cited paper titles for a set of OpenAlex authors",
        "description": "Returns `{openalex_id: [titles]}` \u2014 the N most-cited works per author (one small OpenAlex /works call each, run concurrently). Split from the author-search endpoint so it can be fetched non-blocking: the search cards render immediately and the titles fill in after. Pure read.",
        "operationId": "author_top_cited_works_api_v1_library_import_search_authors_top_works_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthorTopWorksRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/search/stream": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Streaming variant of /import/search (NDJSON, per-source events)",
        "description": "Same fan-out as `/import/search` but yields per-source events as each lane returns so the UI can render skeletons \u2192 partial results \u2192 final query-relevance-ranked list incrementally. Each newline-delimited JSON object carries a `type` field \u2014 `source_pending`, `source_partial`, `source_timeout`, `source_error`, or `final`.",
        "operationId": "online_source_search_stream_api_v1_library_import_search_stream_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnlineSearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library/import/search/save": {
      "post": {
        "tags": [
          "library-import"
        ],
        "summary": "Save an online search result with the add/like/love/dislike contract",
        "description": "Resolves one OpenAlex work and applies the shared `3/4/5/1` rating contract. add/like/love land in Library with `added_from='online_search'`; dislike writes a negative feedback event and marks the paper dismissed (unless it's already in Library \u2014 then the library entry is preserved and only the signal is recorded).",
        "operationId": "online_source_search_save_api_v1_library_import_search_save_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnlineSearchSaveRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/rules": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "List alert rules",
        "description": "Return all alert rules.",
        "operationId": "list_rules_api_v1_alerts_rules_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertRuleResponse"
                  },
                  "title": "Response List Rules Api V1 Alerts Rules Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Create an alert rule",
        "description": "Create a new alert rule.",
        "operationId": "create_rule_api_v1_alerts_rules_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertRuleCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/rules/{rule_id}": {
      "put": {
        "tags": [
          "alerts"
        ],
        "summary": "Update an alert rule",
        "description": "Update an existing alert rule.",
        "operationId": "update_rule_api_v1_alerts_rules__rule_id__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Rule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertRuleCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "alerts"
        ],
        "summary": "Delete an alert rule",
        "description": "Delete an alert rule.",
        "operationId": "delete_rule_api_v1_alerts_rules__rule_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Rule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/rules/{rule_id}/toggle": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Toggle alert rule enabled/disabled",
        "description": "Toggle the enabled state of an alert rule.",
        "operationId": "toggle_rule_api_v1_alerts_rules__rule_id__toggle_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Rule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/history": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "List alert history",
        "description": "Return alert history entries with optional rule_id/alert_id filter and pagination.",
        "operationId": "list_history_api_v1_alerts_history_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "rule_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by rule ID",
              "title": "Rule Id"
            },
            "description": "Filter by rule ID"
          },
          {
            "name": "alert_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by alert ID",
              "title": "Alert Id"
            },
            "description": "Filter by alert ID"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertHistoryResponse"
                  },
                  "title": "Response List History Api V1 Alerts History Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/test/{rule_id}": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Test-fire an alert rule",
        "description": "Test-fire an alert rule: check matching publications without actually sending.\n\nReturns a list of matching publication titles based on the rule configuration.",
        "operationId": "test_fire_rule_api_v1_alerts_test__rule_id__post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Rule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/templates": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "List suggested alert automations",
        "description": "Return one-click alert suggestions derived from monitors, branches, and workflow state.",
        "operationId": "list_alert_templates_api_v1_alerts_templates_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertAutomationTemplate"
                  },
                  "title": "Response List Alert Templates Api V1 Alerts Templates Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/templates/{template_key}/apply": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Apply a suggested alert automation",
        "description": "Materialize one template suggestion: create its rule and digest atomically.\n\nThe template payload is recomputed server-side from ``template_key`` (the\nclient never sends rule/alert bodies), and both inserts share one\ntransaction \u2014 no orphan rule when the digest insert fails. 404 when the\nkey no longer resolves (already applied, or the source stopped qualifying).",
        "operationId": "apply_alert_template_api_v1_alerts_templates__template_key__apply_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "template_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Template Key"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertTemplateApplyResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "List all alerts",
        "description": "Return all alerts (delivery configs) with their assigned rules.",
        "operationId": "list_alerts_api_v1_alerts__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AlertResponse"
                  },
                  "title": "Response List Alerts Api V1 Alerts  Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Create an alert",
        "description": "Create a new alert (delivery config).",
        "operationId": "create_alert_api_v1_alerts__post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/{alert_id}": {
      "get": {
        "tags": [
          "alerts"
        ],
        "summary": "Get a single alert",
        "description": "Return a single alert by ID with its assigned rules.",
        "operationId": "get_alert_api_v1_alerts__alert_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alert Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "alerts"
        ],
        "summary": "Update an alert",
        "description": "Update an existing alert's fields (partial update).",
        "operationId": "update_alert_api_v1_alerts__alert_id__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alert Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "alerts"
        ],
        "summary": "Delete an alert",
        "description": "Delete an alert and its rule assignments.",
        "operationId": "delete_alert_api_v1_alerts__alert_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alert Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/{alert_id}/rules": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Assign rules to an alert",
        "description": "Assign one or more rules to an alert.",
        "operationId": "assign_rules_api_v1_alerts__alert_id__rules_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alert Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertRuleAssignment"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/{alert_id}/rules/{rule_id}": {
      "delete": {
        "tags": [
          "alerts"
        ],
        "summary": "Unassign a rule from an alert",
        "description": "Remove a rule assignment from an alert.",
        "operationId": "unassign_rule_api_v1_alerts__alert_id__rules__rule_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alert Id"
            }
          },
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Rule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/{alert_id}/evaluate": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Evaluate and send alert (async-enveloped)",
        "description": "Queue a digest evaluation and return the canonical activity envelope.\n\nThe actual rule matching, deduplication, and Slack delivery run on the\nscheduler thread pool so the request thread is released in ~100 ms.\nProgress flows into ``operation_status``; the frontend polls\n``GET /activity/{job_id}`` and reads ``result`` once the job completes.\n\nConforms to the activity-envelope pattern (`lessons.md:1027`):\n1. Validate input synchronously -> fast 4xx for missing alert.\n2. Dedupe with ``find_active_job`` so concurrent clicks don't double-send.\n3. ``_runner`` opens its own connection (per `lessons.md:1042`).\n4. Returns the envelope; result lands in ``operation_status.result``.",
        "operationId": "evaluate_alert_api_v1_alerts__alert_id__evaluate_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alert Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/{alert_id}/dry-run": {
      "post": {
        "tags": [
          "alerts"
        ],
        "summary": "Dry-run alert evaluation",
        "description": "Same as evaluate but don't send and don't record. Returns matching papers.",
        "operationId": "dry_run_alert_api_v1_alerts__alert_id__dry_run_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "alert_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Alert Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertEvaluationResult"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/status": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Discovery refresh status",
        "description": "Return lightweight discovery status, including the last successful refresh.\n\n``new_count`` and recommendation ``is_new`` use this same refresh window.",
        "operationId": "get_discovery_status_api_v1_discovery_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/settings": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Get discovery settings",
        "description": "Return the current discovery engine settings.",
        "operationId": "get_discovery_settings_api_v1_discovery_settings_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoverySettingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "discovery"
        ],
        "summary": "Update discovery settings",
        "description": "Partially update discovery settings (only supplied fields are changed).",
        "operationId": "update_discovery_settings_api_v1_discovery_settings_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DiscoverySettingsUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoverySettingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/settings/reset": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Reset discovery settings to defaults",
        "description": "Reset all discovery settings to their default values.",
        "operationId": "reset_discovery_settings_api_v1_discovery_settings_reset_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoverySettingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/similar": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Discover papers similar to selected publications",
        "description": "Return cached similar papers inline, or queue a discovery Activity job.\n\nA fresh cache entry is served synchronously (fast read, no job). A cache\nmiss or forced refresh queues the discovery engine on the APS scheduler\npool and returns an ``activity_envelope``; the frontend polls\n``GET /activity/{job_id}`` for the ``result.similarity`` payload.",
        "operationId": "discover_similar_api_v1_discovery_similar_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimilarityRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/similarity-cache/clear": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Clear cached similarity-search results",
        "operationId": "clear_similarity_cache_api_v1_discovery_similarity_cache_clear_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/manual-search": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Search online sources by query/title/author/link (Activity-backed)",
        "description": "Queue a multi-source online search as an Activity job and return its envelope.\n\nFans out across OpenAlex, Semantic Scholar, Crossref, arXiv, and bioRxiv\nvia the shared ``search_online_sources`` stack and returns deduplicated\nresults ranked by query relevance (cross-source RRF + query-text match;\npersonal fit rides along as chip data). Runs on the APS scheduler pool so the\nrequest thread is released before the remote round-trips. Frontend\ncallers poll ``GET /activity/{job_id}`` and read the ``result`` payload\nonce the status turns ``completed``.",
        "operationId": "manual_discovery_search_api_v1_discovery_manual_search_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManualSearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/manual-search/add": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Add a manually discovered paper to library",
        "description": "Resolve one external paper and upsert it into local library.",
        "operationId": "manual_discovery_add_api_v1_discovery_manual_search_add_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManualAddRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaperResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/impressions": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Record visible Discovery recommendations",
        "description": "Persist actual item visibility; unrendered recommendations stay unlabeled.",
        "operationId": "record_discovery_impressions_api_v1_discovery_impressions_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DiscoveryImpressionBatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoveryImpressionBatchResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/recommendations": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "List recommendations",
        "description": "Return recommendations that have not been dismissed, with pagination.",
        "operationId": "list_recommendations_api_v1_discovery_recommendations_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by title/authors/source key",
              "title": "Search"
            },
            "description": "Filter by title/authors/source key"
          },
          {
            "name": "semantic",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Reserved semantic filter toggle",
              "default": false,
              "title": "Semantic"
            },
            "description": "Reserved semantic filter toggle"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RecommendationResponse"
                  },
                  "title": "Response List Recommendations Api V1 Discovery Recommendations Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "discovery"
        ],
        "summary": "Clear all recommendations",
        "description": "Delete all recommendations.",
        "operationId": "clear_recommendations_api_v1_discovery_recommendations_delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/recommendations/{rec_id}/seen": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Mark recommendation as seen",
        "description": "Mark a recommendation as seen.",
        "operationId": "mark_seen_api_v1_discovery_recommendations__rec_id__seen_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Rec Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/recommendations/{rec_id}/explain": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Explain a recommendation's score",
        "description": "Return a detailed breakdown of how a recommendation's score was computed.\n\nShows each scoring signal's raw value, weight, and weighted contribution,\nalong with human-readable descriptions of what each signal measures.",
        "operationId": "explain_recommendation_api_v1_discovery_recommendations__rec_id__explain_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "rec_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Rec Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecommendationExplainResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/frontier/rebuild": {
      "post": {
        "tags": [
          "discovery"
        ],
        "summary": "Rebuild the candidate frontier",
        "description": "Build the citation/query frontier on demand.\n\nThe frontier is what lets Discovery return a paper the corpus has never\nheld: works cited by the Library that we hold no row for, plus query and\ntaste leads, each carrying an S2 vector so the dense lane can reach it.\nUntil now it was built only by the periodic citation-graph job, so a fresh\ninstall had an empty frontier and a dense lane that could only re-rank\npapers already in the corpus.\n\nRuns in the background on its own connection: the three phases each make\nnetwork calls, and a request connection may not hold a write txn across\nthose (CLAUDE.md \u2192 SQLite write discipline).",
        "operationId": "rebuild_frontier_api_v1_discovery_frontier_rebuild_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/discovery/stats": {
      "get": {
        "tags": [
          "discovery"
        ],
        "summary": "Get discovery stats",
        "description": "Return aggregate discovery statistics: total, seen, liked, dismissed.",
        "operationId": "discovery_stats_api_v1_discovery_stats_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/settings": {
      "get": {
        "tags": [
          "feed"
        ],
        "summary": "Get feed auto-refresh settings",
        "description": "Return the feed inbox auto-refresh opt-in + interval.",
        "operationId": "get_feed_settings_api_v1_feed_settings_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedSettings"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "feed"
        ],
        "summary": "Update feed auto-refresh settings",
        "description": "Persist the feed auto-refresh settings and (re)register the periodic job.\n\nThe two KV upserts run in one gated write unit (SQLite write discipline);\nrescheduling happens after the commit so the live scheduler matches the new\nsetting without a restart.",
        "operationId": "update_feed_settings_api_v1_feed_settings_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedSettings"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedSettings"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed": {
      "get": {
        "tags": [
          "feed"
        ],
        "summary": "List feed inbox items",
        "description": "Return feed inbox items from feed_items table.",
        "operationId": "list_feed_items_api_v1_feed_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional status filter: all | new | add | like | love | dislike",
              "title": "Status"
            },
            "description": "Optional status filter: all | new | add | like | love | dislike"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Sort order: chronological (default) or relevance",
              "default": "chronological",
              "title": "Sort"
            },
            "description": "Sort order: chronological (default) or relevance"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "since_days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 3650,
              "minimum": 1,
              "description": "Restrict to items published (or fetched) within the last N days. Defaults to 60.",
              "default": 60,
              "title": "Since Days"
            },
            "description": "Restrict to items published (or fetched) within the last N days. Defaults to 60."
          },
          {
            "name": "hide_library",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Hide papers already saved to the Library or on the reading list.",
              "default": false,
              "title": "Hide Library"
            },
            "description": "Hide papers already saved to the Library or on the reading list."
          },
          {
            "name": "monitor_scope",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Split by monitor type: 'inbox' (exclude journals) | 'journals' (venue only) | omit for all",
              "title": "Monitor Scope"
            },
            "description": "Split by monitor type: 'inbox' (exclude journals) | 'journals' (venue only) | omit for all"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/status": {
      "get": {
        "tags": [
          "feed"
        ],
        "summary": "Feed refresh status",
        "description": "Return lightweight feed status, including the last successful refresh.\n\n``last_refresh_at`` is the latest ``finished_at`` across completed full\ninbox or per-monitor feed refreshes in ``operation_status``. ``new_count``\ncounts distinct visible papers fetched during that latest refresh OR\nduring the rolling last 24 hours.",
        "operationId": "get_feed_status_api_v1_feed_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/seen": {
      "post": {
        "tags": [
          "feed"
        ],
        "summary": "Mark the Feed as seen",
        "description": "Stamps owner review state for Home carryover; Feed New remains time-based.",
        "operationId": "post_feed_seen_api_v1_feed_seen_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/monitors": {
      "get": {
        "tags": [
          "feed"
        ],
        "summary": "List feed monitors",
        "operationId": "list_feed_monitors_api_v1_feed_monitors_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "feed"
        ],
        "summary": "Create a non-author feed monitor",
        "operationId": "create_feed_monitor_api_v1_feed_monitors_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedMonitorCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/monitors/venue-search": {
      "get": {
        "tags": [
          "feed"
        ],
        "summary": "Autocomplete OpenAlex journals/venues for a journal monitor",
        "description": "Search OpenAlex sources (journals) by name for the journal-follow UI.\n\nPure read \u2014 no DB access. Defined BEFORE the dynamic ``/monitors/{id}``\nroutes so the literal path is not captured as a monitor id. ``?search=``\nis the paid OpenAlex cost class, so this is only ever called interactively\nfrom the follow UI, never by a background job.",
        "operationId": "venue_search_api_v1_feed_monitors_venue_search_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Q"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/monitors/order": {
      "put": {
        "tags": [
          "feed"
        ],
        "summary": "Reorder feed monitors (drag-to-reorder)",
        "description": "Persist a new display order. Defined BEFORE /monitors/{id} so the literal\n'order' path is not captured as a monitor id.",
        "operationId": "reorder_feed_monitors_api_v1_feed_monitors_order_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/monitors/{monitor_id}": {
      "delete": {
        "tags": [
          "feed"
        ],
        "summary": "Delete a non-author feed monitor",
        "operationId": "delete_feed_monitor_api_v1_feed_monitors__monitor_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Monitor Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "feed"
        ],
        "summary": "Update a feed monitor",
        "operationId": "update_feed_monitor_api_v1_feed_monitors__monitor_id__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Monitor Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedMonitorUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/refresh": {
      "post": {
        "tags": [
          "feed"
        ],
        "summary": "Refresh feed inbox from active monitors",
        "description": "Fetch recent works from active monitors and populate the feed inbox.",
        "operationId": "refresh_feed_inbox_api_v1_feed_refresh_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Run as a background Activity job when the scheduler is enabled",
              "title": "Background"
            },
            "description": "Run as a background Activity job when the scheduler is enabled"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/monitors/{monitor_id}/refresh": {
      "post": {
        "tags": [
          "feed"
        ],
        "summary": "Refresh one feed monitor",
        "operationId": "refresh_feed_monitor_api_v1_feed_monitors__monitor_id__refresh_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Monitor Id"
            }
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Run as a background Activity job when the scheduler is enabled",
              "title": "Background"
            },
            "description": "Run as a background Activity job when the scheduler is enabled"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feed/bulk-action": {
      "post": {
        "tags": [
          "feed"
        ],
        "summary": "Apply one action to multiple feed items",
        "operationId": "bulk_feed_action_api_v1_feed_bulk_action_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedBulkActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses": {
      "get": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "List discovery lenses",
        "operationId": "list_lenses_api_v1_lenses_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "is_active",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Is Active"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LensResponse"
                  },
                  "title": "Response List Lenses Api V1 Lenses Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Create a discovery lens",
        "operationId": "create_lens_api_v1_lenses_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LensCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LensResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses/order": {
      "put": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Reorder discovery lenses (drag-to-reorder)",
        "description": "Persist a new lens display order. Defined BEFORE /{lens_id} so the\nliteral 'order' path is not captured as a lens id.",
        "operationId": "reorder_lenses_api_v1_lenses_order_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses/{lens_id}": {
      "get": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Get discovery lens",
        "operationId": "get_lens_api_v1_lenses__lens_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LensResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Update discovery lens",
        "operationId": "update_lens_api_v1_lenses__lens_id__put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LensUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LensResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Delete discovery lens",
        "operationId": "delete_lens_api_v1_lenses__lens_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses/{lens_id}/seen": {
      "post": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Mark one Discovery lens as reviewed",
        "description": "Stamps the lens only after its recommendation deck renders. Home reads this owner state but never changes it.",
        "operationId": "mark_lens_seen_api_v1_lenses__lens_id__seen_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses/{lens_id}/signals": {
      "get": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "List lens signals",
        "operationId": "list_lens_signals_api_v1_lenses__lens_id__signals_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses/{lens_id}/recommendations": {
      "get": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "List recommendations for a lens",
        "operationId": "list_lens_recommendations_api_v1_lenses__lens_id__recommendations_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "hide_library",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Hide papers already saved to the Library or on the reading list.",
              "default": false,
              "title": "Hide Library"
            },
            "description": "Hide papers already saved to the Library or on the reading list."
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RecommendationResponse"
                  },
                  "title": "Response List Lens Recommendations Api V1 Lenses  Lens Id  Recommendations Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses/{lens_id}/branches": {
      "get": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Preview branch map for a lens",
        "operationId": "preview_lens_branches_api_v1_lenses__lens_id__branches_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "max_branches",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 12,
              "minimum": 2,
              "default": 6,
              "title": "Max Branches"
            }
          },
          {
            "name": "temperature",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "number",
                  "maximum": 1.0,
                  "minimum": 0.0
                },
                {
                  "type": "null"
                }
              ],
              "title": "Temperature"
            }
          },
          {
            "name": "resolution",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "number",
                  "maximum": 3.0,
                  "minimum": 0.5
                },
                {
                  "type": "null"
                }
              ],
              "title": "Resolution"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LensBranchPreviewResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lenses/{lens_id}/refresh": {
      "post": {
        "tags": [
          "discovery-lenses"
        ],
        "summary": "Refresh recommendations for a lens",
        "description": "Queue a lens refresh on the APS scheduler pool.\n\nPer the Activity-envelope migration pattern (see `tasks/lessons.md`): the\nrequest thread validates synchronously (404 on missing lens, dedup via\n`find_active_job`), seeds `operation_status`, schedules the runner, and\nreturns the queued envelope in ~100 ms. The runner opens its own SQLite\nconnection (don't reuse the request-scoped `db` inside the scheduler\nthread) and writes the final `result=` payload via `set_job_status`.\n\nFrontends poll `GET /activity/{job_id}` for status; `useOperationToasts`\nauto-invalidates `lens-recommendations` on `discovery.*` completion, so\nno per-call cache wiring is needed.",
        "operationId": "refresh_lens_api_v1_lenses__lens_id__refresh_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Lens Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scheduler/status": {
      "get": {
        "tags": [
          "scheduler"
        ],
        "summary": "Get scheduler status",
        "description": "Returns whether the scheduler is running and a list of registered jobs with their next run times.",
        "operationId": "scheduler_status_api_v1_scheduler_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scheduler/trigger/{job_id}": {
      "post": {
        "tags": [
          "scheduler"
        ],
        "summary": "Manually trigger a scheduled job",
        "description": "Trigger a registered scheduler job to run immediately.",
        "operationId": "trigger_job_api_v1_scheduler_trigger__job_id__post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/insights": {
      "get": {
        "tags": [
          "insights",
          "insights"
        ],
        "summary": "Get insights data",
        "description": "Returns aggregated statistics for the Insights dashboard.",
        "operationId": "get_insights_api_v1_insights_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/insights/papers": {
      "get": {
        "tags": [
          "insights",
          "insights"
        ],
        "summary": "Papers behind an Insights figure (drilldown)",
        "description": "Paginated paper list for ONE Insights figure \u2014 a graph cluster, or a topic / journal / institution / year / source bar. Pure read; rows are the standard Publication shape.",
        "operationId": "get_insights_papers_api_v1_insights_papers_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "filter_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "cluster | topic | journal | institution | country | year | source | all",
              "title": "Filter Type"
            },
            "description": "cluster | topic | journal | institution | country | year | source | all"
          },
          {
            "name": "filter_value",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "the figure's value (cluster id, topic name, \u2026); ignored for 'all'",
              "title": "Filter Value"
            },
            "description": "the figure's value (cluster id, topic name, \u2026); ignored for 'all'"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "library | corpus \u2014 only affects cluster",
              "default": "library",
              "title": "Scope"
            },
            "description": "library | corpus \u2014 only affects cluster"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 30,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/insights/health": {
      "get": {
        "tags": [
          "insights",
          "insights"
        ],
        "summary": "Canonical corpus data-health snapshot",
        "description": "The single source of truth for corpus data-health (task 24, Pillar 1). Returns uniform dimension records \u2014 each with a count, severity, a plain-language explanation/impact, and the fix actions \u2014 so every surface (Health page, needs-attention, operational status) renders the same numbers and guidance. Served via the materialised-view layer (<1s cached read, background rebuild on change; no external calls).",
        "operationId": "get_corpus_health_api_v1_insights_health_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/insights/diagnostics": {
      "get": {
        "tags": [
          "insights",
          "insights"
        ],
        "summary": "Get monitor and discovery diagnostics",
        "description": "Returns the full diagnostics payload composed from per-section materialised views. Each section is also exposed at `/insights/diagnostics/sections/{section}` so the frontend can stream cards in independently with per-card skeletons.",
        "operationId": "get_insights_diagnostics_api_v1_insights_diagnostics_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/insights/discovery/branch-action": {
      "post": {
        "tags": [
          "insights",
          "insights"
        ],
        "summary": "Apply a branch control action from Insights",
        "operationId": "apply_branch_action_api_v1_insights_discovery_branch_action_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BranchTuningActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/insights/diagnostics/sections/{section}": {
      "get": {
        "tags": [
          "insights",
          "insights"
        ],
        "summary": "Get one diagnostics section",
        "description": "Returns just one section of the Insights diagnostics payload. Each section is cached as a materialised view with a narrow fingerprint, so cards stream in independently and stay fresh without recomputing unrelated work.",
        "operationId": "get_diagnostics_section_api_v1_insights_diagnostics_sections__section__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "section",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Section"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/dimensions/{key}/items": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Papers affected by a health dimension",
        "description": "Paginated list of the papers a Data Health dimension is flagging, so the Health page can drill down to which papers and offer fixes.",
        "operationId": "get_dimension_items_api_v1_health_dimensions__key__items_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Key"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/operations": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Maintenance operations status",
        "description": "Every registered maintenance task with its enabled / daily-cap config, the canonical count of papers it would address, and its most-recent run.",
        "operationId": "get_operations_api_v1_health_operations_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/governance": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Background-ops governance knobs (idle-wait + API reserve)",
        "operationId": "get_governance_settings_api_v1_health_governance_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceSettings"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "health"
        ],
        "summary": "Update background-ops governance knobs",
        "description": "Persist the two knobs (one gated write unit; SQLite write discipline). The\ngate reads them live per check, so no restart/reschedule is needed.",
        "operationId": "update_governance_settings_api_v1_health_governance_put",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GovernanceSettings"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceSettings"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/operations/{key}/estimate": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Recompute a maintenance op's pending count + ETA for chosen params",
        "description": "Cheap recompute of just ``candidates_pending`` + ``eta`` for a given ``scope`` / ``dry_run`` \u2014 lets the UI refresh the ETA when the user changes a control without re-listing every operation.",
        "operationId": "estimate_operation_api_v1_health_operations__key__estimate_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Key"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Scope"
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Dry Run"
            }
          },
          {
            "name": "max_items",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Max Items"
            }
          },
          {
            "name": "request_batch_size",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Request Batch Size"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/operations/{key}/run": {
      "post": {
        "tags": [
          "health"
        ],
        "summary": "Run a maintenance task now",
        "description": "Schedule one bounded run (trigger_source='user'). Idempotent \u2014 returns the in-flight job if the same operation is already running. An optional body restricts the run to specific paper ids.",
        "operationId": "run_operation_api_v1_health_operations__key__run_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Key"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RunMaintenanceRequest"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/operations/{key}/resume": {
      "post": {
        "tags": [
          "health"
        ],
        "summary": "Re-arm automation for a manually stopped task",
        "description": "Clear the cooldown a manual stop put on this task, so the idle healer and the startup orphan-resume may schedule it again. No-op when the task is not paused.",
        "operationId": "resume_operation_api_v1_health_operations__key__resume_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Key"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/operations/{key}/config": {
      "post": {
        "tags": [
          "health"
        ],
        "summary": "Configure a maintenance task",
        "description": "Set the auto-enable flag and/or the daily cap for one task.",
        "operationId": "set_operation_config_api_v1_health_operations__key__config_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Key"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaintenanceConfigRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/threads": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "Dump all backend thread stacks (diagnostic)",
        "description": "Read-only diagnostic for write-lock stalls: returns every live thread's name + current stack so the holder of the SQLite writer (or the process writer gate) can be identified while reads still flow. No DB access \u2014 usable even when the writer is wedged.",
        "operationId": "dump_thread_stacks_api_v1_health_threads_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/info": {
      "get": {
        "tags": [
          "library-management"
        ],
        "summary": "Database information",
        "description": "Return metadata about the unified database and available backups.",
        "operationId": "db_info_api_v1_library_mgmt_info_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/backup": {
      "post": {
        "tags": [
          "library-management"
        ],
        "summary": "Create database backup",
        "description": "Create a timestamped backup of the unified database.",
        "operationId": "create_backup_api_v1_library_mgmt_backup_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/restore/{backup_name}": {
      "post": {
        "tags": [
          "library-management"
        ],
        "summary": "Restore from backup",
        "description": "Restore the unified database from a previously created backup.",
        "operationId": "restore_backup_api_v1_library_mgmt_restore__backup_name__post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "backup_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backup Name"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/backup/{backup_name}": {
      "delete": {
        "tags": [
          "library-management"
        ],
        "summary": "Delete a backup",
        "description": "Delete a backup file from the backups directory.",
        "operationId": "delete_backup_api_v1_library_mgmt_backup__backup_name__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "backup_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Backup Name"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/embeddings/reset": {
      "post": {
        "tags": [
          "library-management"
        ],
        "summary": "Delete every cached embedding so they can be re-fetched",
        "description": "Wipes `publication_embeddings`, `author_centroids`, and `publication_embedding_fetch_status` so the next AI run / S2 backfill repopulates them from scratch. Synchronous (small tables, < 1 s). Library papers, followed authors, lenses, feedback events, collections, tags, and the corpus are preserved \u2014 only the vector caches and their per-paper fetch markers are removed.",
        "operationId": "reset_embeddings_api_v1_library_mgmt_embeddings_reset_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/reset": {
      "delete": {
        "tags": [
          "library-management"
        ],
        "summary": "Reset library data",
        "description": "Queue a destructive reset of the unified library database. A backup is automatically created before the reset, tables are cleared, and the database is compacted. Runs as an Activity job so the request returns immediately and progress is visible in the Activity panel.",
        "operationId": "reset_publications_api_v1_library_mgmt_reset_delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/deduplicate": {
      "post": {
        "tags": [
          "library-management"
        ],
        "summary": "Deduplicate authors and publications",
        "description": "Run deduplication and stable-ID maintenance as a background job.",
        "operationId": "deduplicate_database_api_v1_library_mgmt_deduplicate_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/library-mgmt/backfill-components": {
      "post": {
        "tags": [
          "library-management"
        ],
        "summary": "Reconcile paper groups (published papers / preprints / components)",
        "description": "Run the corpus-wide parent/child reconciliation pass: published journal papers become the root when present, preprints and components point to that root, and child rows lose vectors / graph state / preference sidecars. Runs as a background job.",
        "operationId": "backfill_components_route_api_v1_library_mgmt_backfill_components_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/logs": {
      "get": {
        "tags": [
          "logs"
        ],
        "summary": "View recent log entries",
        "description": "Return the most recent log entries captured by the in-memory ring buffer.",
        "operationId": "get_logs_api_v1_logs_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "description": "Maximum entries to return",
              "default": 100,
              "title": "Limit"
            },
            "description": "Maximum entries to return"
          },
          {
            "name": "level",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
              "title": "Level"
            },
            "description": "Filter by log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)"
          },
          {
            "name": "logger",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by logger name",
              "title": "Logger"
            },
            "description": "Filter by logger name"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Only include logs at/after this ISO timestamp",
              "title": "Since"
            },
            "description": "Only include logs at/after this ISO timestamp"
          },
          {
            "name": "operation_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by operation id correlation marker",
              "title": "Operation Id"
            },
            "description": "Filter by operation id correlation marker"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity": {
      "get": {
        "tags": [
          "activity"
        ],
        "summary": "List active operations",
        "description": "Return all active and recently completed job statuses from the scheduler.",
        "operationId": "get_active_operations_api_v1_activity_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by status",
              "title": "Status"
            },
            "description": "Filter by status"
          },
          {
            "name": "trigger_source",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by trigger source",
              "title": "Trigger Source"
            },
            "description": "Filter by trigger source"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only include operations updated at/after ISO timestamp",
              "title": "Since"
            },
            "description": "Only include operations updated at/after ISO timestamp"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Cursor for pagination",
              "title": "Cursor"
            },
            "description": "Cursor for pagination"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 2000,
              "minimum": 1,
              "default": 200,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity/{job_id}": {
      "get": {
        "tags": [
          "activity"
        ],
        "summary": "Get one operation status",
        "description": "Return the latest status envelope for a specific job id, including any result JSON once the job has completed. Frontend callers use this to poll for Activity-backed operations that produce result payloads (e.g. discovery search, author preview).",
        "operationId": "get_operation_status_api_v1_activity__job_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "activity"
        ],
        "summary": "Dismiss an operation from Activity",
        "description": "Removes an operation entry and its detailed logs from Activity.",
        "operationId": "dismiss_operation_api_v1_activity__job_id__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity/{job_id}/logs": {
      "get": {
        "tags": [
          "activity"
        ],
        "summary": "Get logs for one operation",
        "description": "Return detailed structured log entries for a specific job id.",
        "operationId": "get_operation_logs_api_v1_activity__job_id__logs_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Cursor for pagination",
              "title": "Cursor"
            },
            "description": "Cursor for pagination"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity/{job_id}/cancel": {
      "post": {
        "tags": [
          "activity"
        ],
        "summary": "Cancel an operation",
        "description": "Request cancellation for a queued/running operation. Queued jobs are unscheduled immediately; running jobs are marked as cancel-requested and stop at the next cooperative checkpoint.",
        "operationId": "cancel_operation_api_v1_activity__job_id__cancel_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/activity/{job_id}/stop": {
      "post": {
        "tags": [
          "activity"
        ],
        "summary": "Gracefully stop an operation",
        "description": "Request a GRACEFUL stop for a running operation: the worker keeps control, finishes its in-flight batch, commits the work done so far and exits at its next cooperative checkpoint. No thread interrupt is sent (contrast with /cancel, which kills the worker thread). Queued jobs are unscheduled immediately.",
        "operationId": "stop_operation_api_v1_activity__job_id__stop_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/status": {
      "get": {
        "tags": [
          "ai"
        ],
        "summary": "Ai Status",
        "description": "Return the current AI/ML system status.\n\nIncludes embedding provider info, embedding coverage statistics, and\ndependency availability.",
        "operationId": "ai_status_api_v1_ai_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Ai Status Api V1 Ai Status Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/configure": {
      "post": {
        "tags": [
          "ai"
        ],
        "summary": "Ai Configure",
        "description": "Update AI/ML configuration settings and return the updated status.",
        "operationId": "ai_configure_api_v1_ai_configure_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AIConfigureRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Ai Configure Api V1 Ai Configure Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/recheck-environment": {
      "post": {
        "tags": [
          "ai"
        ],
        "summary": "Recheck Environment",
        "description": "Refresh dependency import caches and return current AI status.",
        "operationId": "recheck_environment_api_v1_ai_recheck_environment_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Recheck Environment Api V1 Ai Recheck Environment Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/compute-embeddings": {
      "post": {
        "tags": [
          "ai"
        ],
        "summary": "Compute Embeddings",
        "description": "Trigger batch embedding computation as a background job.\n\nFor every publication that does not yet have an entry in\n``publication_embeddings``, computes and stores the embedding using\nthe active provider.",
        "operationId": "compute_embeddings_api_v1_ai_compute_embeddings_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Which papers to embed: missing, stale, missing_stale, or all.",
              "default": "missing_stale",
              "title": "Scope"
            },
            "description": "Which papers to embed: missing, stale, missing_stale, or all."
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComputeEmbeddingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/backfill-s2-vectors": {
      "post": {
        "tags": [
          "ai"
        ],
        "summary": "Backfill S2 Vectors",
        "description": "Fetch missing API-sourced Semantic Scholar SPECTER2 vectors.",
        "operationId": "backfill_s2_vectors_api_v1_ai_backfill_s2_vectors_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 5000,
              "minimum": 1,
              "default": 5000,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComputeEmbeddingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/title-resolution-sweep": {
      "post": {
        "tags": [
          "ai"
        ],
        "summary": "Title Resolution Sweep",
        "description": "Resolve paper identity via Semantic Scholar /paper/search.\n\nDistinct from `/backfill-s2-vectors`: this sweep handles papers\nwithout a usable s2_id / DOI (or stamped `unmatched` /\n`bad_local_doi`). It writes the resolved identity back to the\n`papers` row so the next vector sweep can pick the paper up.",
        "operationId": "title_resolution_sweep_api_v1_ai_title_resolution_sweep_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 500,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ComputeEmbeddingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/embeddings/inactive": {
      "delete": {
        "tags": [
          "ai"
        ],
        "summary": "Delete Inactive Embeddings",
        "description": "Delete vectors for models other than the active embedding model.",
        "operationId": "delete_inactive_embeddings_api_v1_ai_embeddings_inactive_delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteInactiveEmbeddingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/ai/dependencies": {
      "get": {
        "tags": [
          "ai"
        ],
        "summary": "Ai Dependencies",
        "description": "Return install status and version for each AI/ML dependency.",
        "operationId": "ai_dependencies_api_v1_ai_dependencies_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Ai Dependencies Api V1 Ai Dependencies Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/selection/lens": {
      "post": {
        "tags": [
          "graphs"
        ],
        "summary": "Create a collection-backed lens from a visible map selection",
        "description": "Atomically save selected papers into a new collection and lens.",
        "operationId": "create_selection_lens_api_v1_graphs_selection_lens_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MapSelectionLensCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapSelectionLensResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/paper-map": {
      "get": {
        "tags": [
          "graphs"
        ],
        "summary": "Get Paper Map",
        "description": "Get paper map visualization data.\n\nDefault options (cluster labels, cluster colour, citation size, edges\non, resolution 1.0) are served via the materialised-view\nlayer: cache hit returns instantly, fingerprint mismatch enqueues a\nbackground rebuild and serves the prior payload meanwhile. Custom\noption combinations (incl. a non-default cluster_resolution) bypass the\ncache and build inline \u2014 those are rare, ad-hoc views where caching every\nvariant would be wasteful.",
        "operationId": "get_paper_map_api_v1_graphs_paper_map_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "label_mode",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Label mode: cluster (c-TF-IDF over title text)",
              "default": "cluster",
              "title": "Label Mode"
            },
            "description": "Label mode: cluster (c-TF-IDF over title text)"
          },
          {
            "name": "color_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Color by: cluster, year, rating, citations",
              "default": "cluster",
              "title": "Color By"
            },
            "description": "Color by: cluster, year, rating, citations"
          },
          {
            "name": "size_by",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Size by: citations, uniform, rating",
              "default": "citations",
              "title": "Size By"
            },
            "description": "Size by: citations, uniform, rating"
          },
          {
            "name": "show_edges",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Show edges between nodes",
              "default": true,
              "title": "Show Edges"
            },
            "description": "Show edges between nodes"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "library (default: Library-only papers) or corpus (every stored paper)",
              "default": "library",
              "title": "Scope"
            },
            "description": "library (default: Library-only papers) or corpus (every stored paper)"
          },
          {
            "name": "cluster_resolution",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 3.0,
              "minimum": 0.5,
              "description": "Cluster detail (default = the substrate resolution, 1.5): >1 finer (more clusters), <1 coarser. Non-default builds a variant in the background (202 while building).",
              "default": 1.5,
              "title": "Cluster Resolution"
            },
            "description": "Cluster detail (default = the substrate resolution, 1.5): >1 finer (more clusters), <1 coarser. Non-default builds a variant in the background (202 while building)."
          },
          {
            "name": "w_semantic",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0,
              "description": "PROTOTYPE: semantic-similarity weight in the fused layout",
              "default": 1.0,
              "title": "W Semantic"
            },
            "description": "PROTOTYPE: semantic-similarity weight in the fused layout"
          },
          {
            "name": "w_coauthorship",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0,
              "description": "PROTOTYPE: co-authorship weight in the fused layout (0 = pure semantic)",
              "default": 0.0,
              "title": "W Coauthorship"
            },
            "description": "PROTOTYPE: co-authorship weight in the fused layout (0 = pure semantic)"
          },
          {
            "name": "w_bibliographic",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0,
              "description": "PROTOTYPE: bibliographic-coupling weight in the fused layout",
              "default": 0.0,
              "title": "W Bibliographic"
            },
            "description": "PROTOTYPE: bibliographic-coupling weight in the fused layout"
          },
          {
            "name": "w_cocitation",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0,
              "description": "Citation influence: co-citation weight in the fused layout (shared citers)",
              "default": 0.0,
              "title": "W Cocitation"
            },
            "description": "Citation influence: co-citation weight in the fused layout (shared citers)"
          },
          {
            "name": "prefetch",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Read-only warm-up. A prefetch NEVER enqueues a layout build: it reports 'building' and returns. Set by speculative callers (sidebar hover) so brushing a nav item cannot start minutes of background work the user never asked for.",
              "default": false,
              "title": "Prefetch"
            },
            "description": "Read-only warm-up. A prefetch NEVER enqueues a layout build: it reports 'building' and returns. Set by speculative callers (sidebar hover) so brushing a nav item cannot start minutes of background work the user never asked for."
          },
          {
            "name": "if-none-match",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Conditional read. A layout is an immutable artifact, so a matching validator answers 304 without ever decoding the stored payload.",
              "title": "If-None-Match"
            },
            "description": "Conditional read. A layout is an immutable artifact, so a matching validator answers 304 without ever decoding the stored payload."
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphData"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/frontier": {
      "get": {
        "tags": [
          "graphs"
        ],
        "summary": "Get Frontier",
        "description": "Layered semantic-map nodes for the Discovery frontier view (task 47 P3).\n\nThree layers over the corpus-scope 2-D layout: (a) all library papers\n(`layer=library`), (b) the lens's CURRENT suggestion set, branch-stamped\n(`layer=rec`), (c) opt-in top-N seen papers by cosine to the library\ncentroid (`layer=seen`). `dismissed`/`removed` papers are never returned\n(D6/D3). Pure read except the one-time corpus-layout build, which returns\n202 `{status:'building'}` (the sanctioned cache-build path).",
        "operationId": "get_frontier_api_v1_graphs_frontier_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "lens_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Discovery lens whose CURRENT suggestions to plot",
              "title": "Lens Id"
            },
            "description": "Discovery lens whose CURRENT suggestions to plot"
          },
          {
            "name": "seen_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 0,
              "description": "Top-N seen-but-unacted papers by centroid similarity (0 = hide the seen layer)",
              "default": 0,
              "title": "Seen Limit"
            },
            "description": "Top-N seen-but-unacted papers by centroid similarity (0 = hide the seen layer)"
          },
          {
            "name": "include_edges",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Also return coupling + co-citation edges between the placed nodes (off by default)",
              "default": false,
              "title": "Include Edges"
            },
            "description": "Also return coupling + co-citation edges between the placed nodes (off by default)"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/region/describe": {
      "post": {
        "tags": [
          "graphs"
        ],
        "summary": "Describe Region",
        "description": "Characterise an arbitrary set of papers by its dominant vocabulary \u2014 the\nread behind selecting a region on the frontier map (task 47 \u00a78, \"Directions\").\n\nPOST only because the body carries up to ~300 paper ids; it is a **pure read**\n(verified by the GET-purity suite). Reuses the SAME c-TF-IDF labeler the\ncluster labels use \u2014 no second TF-IDF. Returns the region's label, top terms,\nthree sample titles, honest membership counts (library / current suggestions /\nseen), and a `sufficient` flag (false below 5 papers \u2192 the UI shows \"too few\npapers to characterize\" and disables actions).",
        "operationId": "describe_region_api_v1_graphs_region_describe_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegionDescribeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/author-network": {
      "get": {
        "tags": [
          "graphs"
        ],
        "summary": "Get Author Network",
        "description": "Get author network visualization data.\n\nThe default (resolution 1.0, pure-semantic layout) is served from the\nmaterialised view. A non-default cluster_resolution OR a fused layout (a\nnon-zero co-authorship / bib-coupling weight) is a variant \u2014 served from the\nSAME durable, proportionally-invalidated cache as the paper map (task #20):\nbuild once, reuse across restarts, rebuild only when a real proportion of the\nunderlying papers has changed. The build itself is a pure read (no\npublication-layout persistence), mirroring the paper map (I-2).",
        "operationId": "get_author_network_api_v1_graphs_author_network_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "library (default) or corpus",
              "default": "library",
              "title": "Scope"
            },
            "description": "library (default) or corpus"
          },
          {
            "name": "cluster_resolution",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 3.0,
              "minimum": 0.5,
              "description": "Cluster detail: >1 finer (more clusters), <1 coarser",
              "default": 1.0,
              "title": "Cluster Resolution"
            },
            "description": "Cluster detail: >1 finer (more clusters), <1 coarser"
          },
          {
            "name": "w_semantic",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0,
              "description": "PROTOTYPE: semantic weight in the fused author layout",
              "default": 1.0,
              "title": "W Semantic"
            },
            "description": "PROTOTYPE: semantic weight in the fused author layout"
          },
          {
            "name": "w_coauthorship",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0,
              "description": "PROTOTYPE: co-authorship weight in the fused author layout",
              "default": 0.0,
              "title": "W Coauthorship"
            },
            "description": "PROTOTYPE: co-authorship weight in the fused author layout"
          },
          {
            "name": "w_bibliographic",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.0,
              "description": "PROTOTYPE: bibliographic-coupling weight in the fused author layout",
              "default": 0.0,
              "title": "W Bibliographic"
            },
            "description": "PROTOTYPE: bibliographic-coupling weight in the fused author layout"
          },
          {
            "name": "prefetch",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Read-only warm-up. A prefetch NEVER enqueues a layout build: it reports 'building' and returns. Set by speculative callers (sidebar hover) so brushing a nav item cannot start minutes of background work the user never asked for.",
              "default": false,
              "title": "Prefetch"
            },
            "description": "Read-only warm-up. A prefetch NEVER enqueues a layout build: it reports 'building' and returns. Set by speculative callers (sidebar hover) so brushing a nav item cannot start minutes of background work the user never asked for."
          },
          {
            "name": "if-none-match",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Conditional read. A layout is an immutable artifact, so a matching validator answers 304 without ever decoding the stored payload.",
              "title": "If-None-Match"
            },
            "description": "Conditional read. A layout is an immutable artifact, so a matching validator answers 304 without ever decoding the stored payload."
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphData"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/signal-field": {
      "get": {
        "tags": [
          "graphs"
        ],
        "summary": "Get Signal Field",
        "description": "The SPACE-OWNED preference field over the corpus substrate.\n\nOne valence per signal-carrying paper, at its substrate coordinates \u2014\nindependent of which dots any view renders (user call 2026-07-25: the\nstats of the space belong to the space; toggling layers must never\nchange the terrain). Every map host splats THIS field for its Heat\nmode, so Discovery and the Map page show the same landscape.\n\nThe valence hierarchy and every weight live in ONE place:\n`alma.core.signal_valence` (strongest user signal wins; engine\nevidence at reduced authority; no-signal papers carry\nVALENCE_NO_SIGNAL so EVERY substrate point has a value \u2014 the\nterrain has no holes, user call 2026-07-25).\n\nSince 2026-07-27 the field is a FIELD: where a paper carries no signal\nof its own, `alma.application.terrain` predicts one from its\nneighbourhood in embedding space and reports how much it trusts the\nprediction. Every point therefore carries `c` (confidence, 0\u20131) and\n`src` (what produced the value) so hosts can render a guess\ndifferently from a fact. See that module for the method.\n\nPure read; the substrate is the durable corpus layout.",
        "operationId": "get_signal_field_api_v1_graphs_signal_field_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/author-field": {
      "get": {
        "tags": [
          "graphs"
        ],
        "summary": "Get Author Field",
        "description": "The LIVE preference + score field for the author map.\n\nThe author analogue of `/graphs/signal-field`, and deliberately built from\nthe SAME contract: an author's valence aggregates `paper_valence` evidence\nover the papers of theirs you have an opinion about. User evidence carries\nfull confidence, engine-only evidence is weak, and a neutral prior prevents\none paper from reading as a settled author verdict. So \"how do I feel about\nthis author\" is derived from \"how do I feel about their papers\" \u2014 one owner\nof the hierarchy, confidence, and weights (`alma.core.signal_valence`).\n\n**Not scoped.** How you feel about an author is a fact about the author, not\nabout which view is open, so this is computed over ALL of their papers. It\nused to take a scope and average only the in-scope ones, which recoloured 48\nauthors when you switched between Corpus and Library (measured 2026-07-26) \u2014\ntwo different opinions about the same person depending on where you stood.\n\nTwo reasons this is an endpoint rather than a field baked into the network\npayload (user catch 2026-07-26 \u2014 \"terrain is all yellow and no scores\"):\n\n* **Live.** The author network is a materialized view; the score baked into\n  it goes stale the moment Discovery re-scores, which greyed the dots and\n  flattened the terrain exactly like the paper map's baked score did.\n* **Coverage.** The old terrain used the mean recommendation score alone and\n  substituted 0 for every author without one \u2014 in corpus scope that is ~90%\n  of them, and a flood of hard zeros diluted the splat's local mean to\n  nothing: uniform yellow. Valence covers every author carrying ANY signal\n  (saved / rated / dismissed / scored), and authors with NO signal are\n  returned with `v: null` so the host can omit them from the splat instead\n  of drowning it. Pale paper where you have no opinion is the honest render.\n\nKeyed by author id (the OpenAlex id, as the network's nodes are) rather than\nby coordinates: unlike the paper substrate there is no off-view author to\naccount for \u2014 the author map always draws every author in scope \u2014 so an\nid-keyed field is view-independent for exactly the same reason.\n\nPure read.",
        "operationId": "get_author_field_api_v1_graphs_author_field_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/cluster-labels/refresh": {
      "post": {
        "tags": [
          "graphs"
        ],
        "summary": "Refresh Cluster Labels",
        "description": "Regenerate representative cluster labels for one graph + scope.\n\nRuns in the Activity envelope so the UI can track per-cluster\nprogress without blocking the GET path. The GET route picks up\ncached labels from `graph_cluster_labels` on the next refresh \u2014\nthis endpoint invalidates `graph_cache` at the end to force that\nrebuild.",
        "operationId": "refresh_cluster_labels_api_v1_graphs_cluster_labels_refresh_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClusterLabelRefreshRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/rebuild": {
      "post": {
        "tags": [
          "graphs"
        ],
        "summary": "Rebuild Graphs",
        "description": "Rebuild the graph caches for the requested scope (I-3: scope-aware).",
        "operationId": "rebuild_graphs_api_v1_graphs_rebuild_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "library (default) or corpus \u2014 the scope to rebuild",
              "default": "library",
              "title": "Scope"
            },
            "description": "library (default) or corpus \u2014 the scope to rebuild"
          },
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run rebuild in background and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run rebuild in background and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/graphs/reference-backfill": {
      "post": {
        "tags": [
          "graphs"
        ],
        "summary": "Backfill Graph References",
        "description": "Backfill missing publication references from OpenAlex without rebuilding caches.",
        "operationId": "backfill_graph_references_api_v1_graphs_reference_backfill_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "background",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Run backfill in background and track in Activity",
              "default": true,
              "title": "Background"
            },
            "description": "Run backfill in background and track in Activity"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tags/suggestions/{paper_id}": {
      "get": {
        "tags": [
          "tags"
        ],
        "summary": "Get tag suggestions for a publication",
        "description": "Returns AI-generated tag suggestions for the specified publication.",
        "operationId": "get_tag_suggestions_api_v1_tags_suggestions__paper_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "max_tags",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 5,
              "title": "Max Tags"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagSuggestionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tags/suggestions/generate": {
      "post": {
        "tags": [
          "tags"
        ],
        "summary": "Bulk generate tag suggestions",
        "description": "Generate tag suggestions for all publications that don't have them yet. Runs as a background job.",
        "operationId": "bulk_generate_suggestions_api_v1_tags_suggestions_generate_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkSuggestResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tags/merge-suggestions": {
      "get": {
        "tags": [
          "tags"
        ],
        "summary": "List suggested tag merges",
        "description": "Find likely duplicate/overlapping tags based on normalized names and token overlap.",
        "operationId": "list_tag_merge_suggestions_api_v1_tags_merge_suggestions_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 25,
              "title": "Limit"
            }
          },
          {
            "name": "min_confidence",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "default": 0.8,
              "title": "Min Confidence"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagMergeSuggestionResponse"
                  },
                  "title": "Response List Tag Merge Suggestions Api V1 Tags Merge Suggestions Get"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tags/merge": {
      "post": {
        "tags": [
          "tags"
        ],
        "summary": "Merge one tag into another",
        "description": "Reassign all source tag usages/suggestions to target tag and delete source tag.",
        "operationId": "merge_tags_api_v1_tags_merge_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TagMergeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Merge Tags Api V1 Tags Merge Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tags/suggestions/{paper_id}/accept": {
      "post": {
        "tags": [
          "tags"
        ],
        "summary": "Accept a tag suggestion",
        "description": "Accept a tag suggestion, creating a real tag assignment for the publication.",
        "operationId": "accept_tag_suggestion_api_v1_tags_suggestions__paper_id__accept_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptTagRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Accept Tag Suggestion Api V1 Tags Suggestions  Paper Id  Accept Post"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tags/suggestions/{paper_id}/{tag}": {
      "delete": {
        "tags": [
          "tags"
        ],
        "summary": "Dismiss a tag suggestion",
        "description": "Remove a tag suggestion for a publication.",
        "operationId": "dismiss_tag_suggestion_api_v1_tags_suggestions__paper_id___tag__delete",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "paper_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Paper Id"
            }
          },
          {
            "name": "tag",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Tag"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topics": {
      "get": {
        "tags": [
          "topics",
          "topics"
        ],
        "summary": "List canonical topics",
        "description": "Returns all canonical topics with alias and publication counts.",
        "operationId": "list_topics_api_v1_topics_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "default": 200,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by topic name",
              "title": "Search"
            },
            "description": "Filter by topic name"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topics/{topic_id}": {
      "get": {
        "tags": [
          "topics",
          "topics"
        ],
        "summary": "Get topic details",
        "description": "Returns a single canonical topic with all its aliases.",
        "operationId": "get_topic_api_v1_topics__topic_id__get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "topic_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Topic Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topics/dedup": {
      "post": {
        "tags": [
          "topics",
          "topics"
        ],
        "summary": "Run topic deduplication",
        "description": "Runs the deterministic deduplication pass: normalizes all publication_topics terms, groups synonyms, and links to canonical topics.",
        "operationId": "run_dedup_api_v1_topics_dedup_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topics/dedup/dry-run": {
      "post": {
        "tags": [
          "topics",
          "topics"
        ],
        "summary": "Dry-run topic deduplication",
        "description": "Returns proposed merge candidates without applying changes. Includes both deterministic (token-overlap) and optionally AI-based candidates.",
        "operationId": "dedup_dry_run_api_v1_topics_dedup_dry_run_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "threshold",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number",
              "maximum": 1.0,
              "minimum": 0.5,
              "description": "Minimum similarity threshold",
              "default": 0.85,
              "title": "Threshold"
            },
            "description": "Minimum similarity threshold"
          },
          {
            "name": "include_ai",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include AI-based candidates",
              "default": false,
              "title": "Include Ai"
            },
            "description": "Include AI-based candidates"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/topics/{topic_id}/merge": {
      "post": {
        "tags": [
          "topics",
          "topics"
        ],
        "summary": "Merge two topics",
        "description": "Merges the specified topic into the target topic. All aliases and publication links are transferred.",
        "operationId": "merge_topic_api_v1_topics__topic_id__merge_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "topic_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Topic Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MergeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feedback/track": {
      "post": {
        "tags": [
          "feedback"
        ],
        "summary": "Track passive interaction events",
        "description": "Record passive UI interactions without mutating preference profiles.",
        "operationId": "track_interaction_api_v1_feedback_track_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrackRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feedback/reset": {
      "post": {
        "tags": [
          "feedback"
        ],
        "summary": "Reset learned feedback state",
        "description": "Wipes every table that encodes user-derived feedback signal \u2014 raw feedback events, per-lens aggregates, author dismissals, author centroids, and cached author suggestion buckets \u2014 and clears `recommendations.user_action` so past actions no longer count as evidence. Saved Library papers, followed authors, lenses, and the corpus itself are preserved.",
        "operationId": "reset_feedback_learning_api_v1_feedback_reset_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "tags": [
          "search"
        ],
        "summary": "Global Search",
        "description": "Search across papers, authors, collections, and topics.\n\nReturns up to 5 results per category.",
        "operationId": "global_search_api_v1_search_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Search query",
              "title": "Q"
            },
            "description": "Search query"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/backup/export": {
      "get": {
        "tags": [
          "backup",
          "backup"
        ],
        "summary": "Export Database",
        "description": "Export the entire SQLite database as a downloadable file.\n\nCreates a snapshot copy of the database file and returns it.\nFilename: alma-backup-{date}.db",
        "operationId": "export_database_api_v1_backup_export_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/backup/export/bibtex": {
      "get": {
        "tags": [
          "backup",
          "backup"
        ],
        "summary": "Export Bibtex",
        "description": "Export library papers as BibTeX.\n\nReturns all papers with status='library' formatted as valid BibTeX entries.",
        "operationId": "export_bibtex_api_v1_backup_export_bibtex_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/backup/export/json": {
      "get": {
        "tags": [
          "backup",
          "backup"
        ],
        "summary": "Export Json",
        "description": "Export library papers as JSON.\n\nReturns all papers with status='library', including their tags, collections,\nauthors, and topics.",
        "operationId": "export_json_api_v1_backup_export_json_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/weekly-brief": {
      "get": {
        "tags": [
          "reports",
          "reports"
        ],
        "summary": "Weekly research brief",
        "description": "New papers, trending topics, active authors over the past week.",
        "operationId": "get_weekly_brief_api_v1_reports_weekly_brief_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/collection-intelligence": {
      "get": {
        "tags": [
          "reports",
          "reports"
        ],
        "summary": "Collection intelligence report",
        "description": "Per-collection analysis: growth, citations, topic diversity.",
        "operationId": "get_collection_intelligence_api_v1_reports_collection_intelligence_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/topic-drift": {
      "get": {
        "tags": [
          "reports",
          "reports"
        ],
        "summary": "Topic drift report",
        "description": "Track how research topics shift across time windows.",
        "operationId": "get_topic_drift_api_v1_reports_topic_drift_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/signal-impact": {
      "get": {
        "tags": [
          "reports",
          "reports"
        ],
        "summary": "Signal impact report",
        "description": "Which scoring signals correlate with positive vs negative recommendation outcomes.",
        "operationId": "get_signal_impact_api_v1_reports_signal_impact_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/home/brief": {
      "get": {
        "tags": [
          "home",
          "home"
        ],
        "summary": "Home daily research brief",
        "description": "Pure-read activity, carryover, source-balanced highlights, reading continuity, and user-fixable blockers for the browser's local day.",
        "operationId": "get_home_brief_api_v1_home_brief_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "timezone",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Browser IANA timezone, for example Europe/Brussels.",
              "default": "UTC",
              "title": "Timezone"
            },
            "description": "Browser IANA timezone, for example Europe/Brussels."
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/bootstrap": {
      "get": {
        "tags": [
          "bootstrap",
          "bootstrap"
        ],
        "summary": "Bootstrap data for frontend",
        "description": "Returns summary stats, library counts, and settings needed for the initial page load in a single request.",
        "operationId": "get_bootstrap_api_v1_bootstrap_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extension/ping": {
      "get": {
        "tags": [
          "extension"
        ],
        "summary": "Connector handshake / health check",
        "description": "Lets the browser connector confirm it is talking to an ALMa build that exposes this endpoint and that the save contract is compatible. Pure read.",
        "operationId": "ping_api_v1_extension_ping_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extension/collections": {
      "get": {
        "tags": [
          "extension"
        ],
        "summary": "List collections for the connector's picker (read-only)",
        "description": "Compact collection list (id / name / saved-paper count) so the popup can offer 'Add to collection' at save time. Pure read. Connectors detect an older ALMa without this endpoint by the 404 and simply hide the picker.",
        "operationId": "list_collections_for_extension_api_v1_extension_collections_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extension/save": {
      "post": {
        "tags": [
          "extension"
        ],
        "summary": "Save the paper open in the browser into ALMa",
        "description": "Resolves the scraped paper (DOI \u2192 OpenAlex preferred, scraped metadata as fallback) and applies the shared add/like/love \u2192 3/4/5 contract via the canonical save helper, stamped `added_from='browser_extension'`. `destination='reading_list'` additionally lands the paper on the reading list.",
        "operationId": "save_from_extension_api_v1_extension_save_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExtensionSaveRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extension/lookup": {
      "post": {
        "tags": [
          "extension"
        ],
        "summary": "Check membership + resolve a paper's metadata (read-only)",
        "description": "Resolves the scraped identifiers against the local corpus and reports membership ('already in Library / Reading list'). Returns the title/authors/year/journal from the local row when present; with `resolve=true` it also fetches them from OpenAlex when the paper isn't local yet (so a PDF's title can be shown before saving). Pure read \u2014 never writes.",
        "operationId": "lookup_from_extension_api_v1_extension_lookup_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExtensionLookupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extension/undo": {
      "post": {
        "tags": [
          "extension"
        ],
        "summary": "Reverse a connector save",
        "description": "Restores the paper to the state captured before the save (or, for a row the save created, reverts it to a tracked, non-Library row) and removes the positive feedback signal the save recorded. Never hard-deletes (D3).",
        "operationId": "undo_from_extension_api_v1_extension_undo_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExtensionUndoRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/inbox/status": {
      "get": {
        "tags": [
          "inbox"
        ],
        "summary": "Inbox capture status (pure read)",
        "description": "Whether any delivery channel is configured, how many papers are waiting in the Inbox, and how many captured messages failed to resolve and need a human. Never writes.",
        "operationId": "inbox_status_api_v1_inbox_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/inbox/sweep": {
      "post": {
        "tags": [
          "inbox"
        ],
        "summary": "Check capture channels now",
        "description": "Polls every configured delivery channel immediately instead of waiting for the next scheduled tick. Idempotent: messages already captured are skipped on their `(channel, external_id)` key, so pressing this twice cannot duplicate a paper.",
        "operationId": "sweep_inbox_now_api_v1_inbox_sweep_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/games": {
      "get": {
        "tags": [
          "signal-lab"
        ],
        "summary": "List Games",
        "description": "The explicit game roster. What is not listed cannot reach your signal.",
        "operationId": "list_games_api_v1_signal_lab_games_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response List Games Api V1 Signal Lab Games Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/summary": {
      "get": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Get Summary",
        "description": "Unique/fitted evidence, structural coverage, and effects. Pure read.",
        "operationId": "get_summary_api_v1_signal_lab_summary_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalLabSummaryResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/{game_id}/queue": {
      "get": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Get Queue",
        "description": "A signed round deck for ``game_id``. Zero writes until each answer.\n\n``available: False`` (with a reason) when the substrate isn't ready or\nno region has a judgeable pool; never an error. The paper payload is the\ntile-rendering minimum; every token binds what its answer needs. Home asks\nfor twelve, and the API contract never permits fewer than ten.",
        "operationId": "get_queue_api_v1_signal_lab__game_id__queue_get",
        "parameters": [
          {
            "name": "game_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Game Id"
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 30,
              "minimum": 10,
              "default": 12,
              "title": "Count"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Get Queue Api V1 Signal Lab  Game Id  Queue Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/{game_id}/round/answer": {
      "post": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Answer Round",
        "description": "Persist one answered round \u2014 one INSERT through the layer's writer.",
        "operationId": "answer_round_api_v1_signal_lab__game_id__round_answer_post",
        "parameters": [
          {
            "name": "game_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Game Id"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoundAnswer"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Answer Round Api V1 Signal Lab  Game Id  Round Answer Post"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/settings": {
      "get": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Get Signal Lab Settings",
        "description": "Read first-class Signal Lab feature settings.",
        "operationId": "get_signal_lab_settings_api_v1_signal_lab_settings_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalLabSettings"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Update Signal Lab Settings",
        "description": "Replace Signal Lab settings after strict Pydantic validation.",
        "operationId": "update_signal_lab_settings_api_v1_signal_lab_settings_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SignalLabSettings"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalLabSettings"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/model": {
      "get": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Get Model",
        "description": "The fitted model summary \u2014 heads, counts, holdout metrics.\n\nPure stored read (task 50 ownership split): never fits inline. ``ready``\nis False until the first background fit lands.",
        "operationId": "get_model_api_v1_signal_lab_model_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Get Model Api V1 Signal Lab Model Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/eval": {
      "get": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Get Eval",
        "description": "Stage-1 promotion evidence: held-out accuracy + hypothetical churn.\n\nUses ``mv.get`` (fingerprint-driven): first call builds inline (bounded \u2014\n\u2264200 recommendation vectors), later calls serve the cached row and refresh\nin the background when rounds or the live list change.",
        "operationId": "get_eval_api_v1_signal_lab_eval_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Get Eval Api V1 Signal Lab Eval Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/signal-lab/purge": {
      "post": {
        "tags": [
          "signal-lab"
        ],
        "summary": "Purge Signal Lab",
        "description": "Delete every lab round and everything derived from them (D20).\n\nLibrary, ratings, and the always-on feedback history are untouched.\nIrreversible by design \u2014 the confirm lives in the Settings UI.",
        "operationId": "purge_signal_lab_api_v1_signal_lab_purge_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Purge Signal Lab Api V1 Signal Lab Purge Post"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/status": {
      "get": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Get Onboarding Status",
        "description": "First-run state + the counts the gate and step copy read.",
        "operationId": "get_onboarding_status_api_v1_onboarding_status_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardingStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/profile": {
      "post": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Set Onboarding Profile",
        "description": "Store the user's display name (local greeting; no external call).",
        "operationId": "set_onboarding_profile_api_v1_onboarding_profile_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/user-profile": {
      "get": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Get User Profile",
        "description": "The greeting name plus the claimed owner identity, for Settings.\n\n`/status` reports `has_owner` as a boolean because onboarding only needs to\nknow whether to ask. Settings has to SHOW who you claimed and let you change\nit, which needs the row itself.",
        "operationId": "get_user_profile_api_v1_onboarding_user_profile_get",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserProfileResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/clear-owner": {
      "post": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Clear Owner",
        "description": "Un-claim the \"this is me\" author WITHOUT unfollowing them.\n\nTwo different statements: \"I am not this person\" and \"I do not want their\npapers\". Clearing the owner flag leaves the follow \u2014 and therefore the Feed\nmonitor and everything already in the Library \u2014 exactly as it was. Use the\nAuthors page to stop following.",
        "operationId": "clear_owner_api_v1_onboarding_clear_owner_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/complete": {
      "post": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Complete Onboarding",
        "description": "Mark onboarding done so the gate stops showing, then start the\nMANDATORY convergence chain (audit 39 finding #4): the coordinator walks\nthe maintenance registry's dependency order \u2014 identity \u2192 metadata \u2192\nvectors \u2192 local embeddings \u2192 centroids \u2192 reference graph \u2192 cluster\nlabels \u2192 topic normalization \u2014 until nothing actionable remains, so the\nfresh library ends healthy, not \"queued\". Its `auto:onboarding_complete`\ntrigger is user-facing (never yields to the idle gate) and survives\nrestarts via the orphan-resume path.",
        "operationId": "complete_onboarding_api_v1_onboarding_complete_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/reset": {
      "post": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Reset Onboarding",
        "description": "Clear the completed flag so Settings \u2192 Restart re-shows the flow.",
        "operationId": "reset_onboarding_api_v1_onboarding_reset_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/resolve-owner": {
      "post": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Resolve Owner Identity",
        "description": "Resolve an ORCID or OpenAlex id to a profile for the confirm card.\n\nRead-only \u2014 no follow, no write. The frontend shows the resolved name +\naffiliation + works count, then calls ``/ingest-owner`` on confirm.",
        "operationId": "resolve_owner_identity_api_v1_onboarding_resolve_owner_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResolveOwnerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OwnerProfileResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/ingest-owner": {
      "post": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Ingest Owner",
        "description": "Follow the user's own author profile + schedule the full backfill.\n\nReuses the canonical follow path (``apply_follow_state`` +\n``schedule_followed_author_historical_backfill``) so all three follow\ntables and the deep-refresh job behave exactly as a normal follow \u2014 then\nmarks the row as the single owner. The owner's papers are promoted to the\nLibrary by ``/promote-owner-papers`` once the backfill has landed them.",
        "operationId": "ingest_owner_api_v1_onboarding_ingest_owner_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IngestOwnerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IngestOwnerResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/onboarding/promote-owner-papers": {
      "post": {
        "tags": [
          "onboarding",
          "onboarding"
        ],
        "summary": "Promote Owner Papers",
        "description": "Save the owner's backfilled papers into the Library (idempotent).\n\nCalled by the frontend once the owner backfill job completes. Selects every\npaper attributed to the owner via ``publication_authors`` and routes it\nthrough ``add_to_library`` (monotonic rating, provenance preserved).",
        "operationId": "promote_owner_papers_api_v1_onboarding_promote_owner_papers_post",
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PromoteOwnerResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/{full_path}": {
      "get": {
        "summary": "Serve Frontend",
        "description": "Serve a real dist file if it exists, else 404.",
        "operationId": "serve_frontend__full_path__get",
        "parameters": [
          {
            "name": "full_path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Full Path"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AIConfigureRequest": {
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider",
            "description": "Embedding provider name (none, local, openai)"
          },
          "openai_api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openai Api Key",
            "description": "OpenAI API key"
          },
          "local_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Local Model",
            "description": "Local embedding model key (specter2-base)"
          },
          "python_env_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Python Env Type",
            "description": "Dependency environment type (system, venv, uv, conda, miniconda, miniforge)"
          },
          "python_env_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Python Env Path",
            "description": "Path to dependency environment folder or python executable"
          }
        },
        "type": "object",
        "title": "AIConfigureRequest",
        "description": "Request body for POST /configure."
      },
      "AcceptTagRequest": {
        "properties": {
          "tag": {
            "type": "string",
            "title": "Tag",
            "description": "Tag name to accept"
          }
        },
        "type": "object",
        "required": [
          "tag"
        ],
        "title": "AcceptTagRequest",
        "description": "Request body for accepting a tag suggestion."
      },
      "AlertAutomationTemplate": {
        "properties": {
          "key": {
            "type": "string",
            "title": "Key"
          },
          "category": {
            "type": "string",
            "title": "Category"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "rationale": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rationale"
          },
          "metrics": {
            "additionalProperties": true,
            "type": "object",
            "title": "Metrics"
          },
          "rule": {
            "$ref": "#/components/schemas/AlertAutomationTemplateRule"
          },
          "alert": {
            "$ref": "#/components/schemas/AlertAutomationTemplateDigest"
          }
        },
        "type": "object",
        "required": [
          "key",
          "category",
          "title",
          "description",
          "rule",
          "alert"
        ],
        "title": "AlertAutomationTemplate",
        "description": "Suggested alert automation derived from current product state."
      },
      "AlertAutomationTemplateDigest": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Channels"
          },
          "schedule": {
            "type": "string",
            "title": "Schedule",
            "default": "manual"
          },
          "schedule_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Schedule Config"
          },
          "format": {
            "type": "string",
            "title": "Format",
            "default": "text"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "AlertAutomationTemplateDigest",
        "description": "One digest payload proposed for an automation template."
      },
      "AlertAutomationTemplateRule": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "rule_type": {
            "type": "string",
            "title": "Rule Type"
          },
          "rule_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Rule Config"
          },
          "channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Channels"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "name",
          "rule_type",
          "rule_config"
        ],
        "title": "AlertAutomationTemplateRule",
        "description": "One rule payload proposed for an automation template."
      },
      "AlertCreate": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Channels"
          },
          "schedule": {
            "type": "string",
            "title": "Schedule",
            "default": "manual"
          },
          "schedule_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Schedule Config"
          },
          "format": {
            "type": "string",
            "title": "Format",
            "default": "grouped"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          },
          "rule_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rule Ids"
          }
        },
        "type": "object",
        "required": [
          "name",
          "channels"
        ],
        "title": "AlertCreate",
        "description": "Request model for creating an alert (digest)."
      },
      "AlertEvaluationResult": {
        "properties": {
          "alert_id": {
            "type": "string",
            "title": "Alert Id"
          },
          "alert_name": {
            "type": "string",
            "title": "Alert Name"
          },
          "digest_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Digest Id"
          },
          "digest_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Digest Name"
          },
          "matched_rules": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Matched Rules"
          },
          "papers_found": {
            "type": "integer",
            "title": "Papers Found"
          },
          "papers_new": {
            "type": "integer",
            "title": "Papers New"
          },
          "papers_sent": {
            "type": "integer",
            "title": "Papers Sent"
          },
          "papers_failed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Papers Failed"
          },
          "channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Channels"
          },
          "channel_results": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Channel Results"
          },
          "trigger_source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trigger Source"
          },
          "dry_run": {
            "type": "boolean",
            "title": "Dry Run"
          },
          "papers": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Papers"
          }
        },
        "type": "object",
        "required": [
          "alert_id",
          "alert_name",
          "papers_found",
          "papers_new",
          "papers_sent",
          "channels",
          "dry_run"
        ],
        "title": "AlertEvaluationResult",
        "description": "Response model for alert evaluation."
      },
      "AlertHistoryResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "rule_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rule Id"
          },
          "alert_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Alert Id"
          },
          "channel": {
            "type": "string",
            "title": "Channel"
          },
          "paper_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paper Id"
          },
          "publications": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Publications"
          },
          "publication_count": {
            "type": "integer",
            "title": "Publication Count",
            "default": 0
          },
          "sent_at": {
            "type": "string",
            "title": "Sent At"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "message_preview": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message Preview"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          }
        },
        "type": "object",
        "required": [
          "id",
          "channel",
          "sent_at",
          "status"
        ],
        "title": "AlertHistoryResponse",
        "description": "Response model for an alert history entry."
      },
      "AlertResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Channels"
          },
          "schedule": {
            "type": "string",
            "title": "Schedule"
          },
          "schedule_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Schedule Config"
          },
          "format": {
            "type": "string",
            "title": "Format"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "last_evaluated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Evaluated At"
          },
          "last_outcome": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Outcome"
          },
          "next_due_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Due At"
          },
          "rules": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rules"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "channels",
          "schedule",
          "format",
          "enabled",
          "created_at"
        ],
        "title": "AlertResponse",
        "description": "Response model for an alert (digest)."
      },
      "AlertRuleAssignment": {
        "properties": {
          "rule_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Rule Ids"
          }
        },
        "type": "object",
        "required": [
          "rule_ids"
        ],
        "title": "AlertRuleAssignment",
        "description": "Request model for assigning rules to an alert."
      },
      "AlertRuleCreate": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "rule_type": {
            "type": "string",
            "title": "Rule Type",
            "description": "Rule type: author, collection, keyword, topic, similarity, discovery_lens, feed_monitor, branch, library_workflow"
          },
          "rule_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Rule Config"
          },
          "channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Channels"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "name",
          "rule_type",
          "rule_config",
          "channels"
        ],
        "title": "AlertRuleCreate",
        "description": "Request model for creating an alert rule."
      },
      "AlertRuleResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "rule_type": {
            "type": "string",
            "title": "Rule Type"
          },
          "rule_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Rule Config"
          },
          "channels": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Channels"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "rule_type",
          "rule_config",
          "channels",
          "enabled",
          "created_at"
        ],
        "title": "AlertRuleResponse",
        "description": "Response model for an alert rule."
      },
      "AlertTemplateApplyResponse": {
        "properties": {
          "template_key": {
            "type": "string",
            "title": "Template Key"
          },
          "template_title": {
            "type": "string",
            "title": "Template Title"
          },
          "rule": {
            "$ref": "#/components/schemas/AlertRuleResponse"
          },
          "alert": {
            "$ref": "#/components/schemas/AlertResponse"
          }
        },
        "type": "object",
        "required": [
          "template_key",
          "template_title",
          "rule",
          "alert"
        ],
        "title": "AlertTemplateApplyResponse",
        "description": "Result of materializing a suggested automation (rule + digest)."
      },
      "AlertUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "channels": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Channels"
          },
          "schedule": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Schedule"
          },
          "schedule_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Schedule Config"
          },
          "format": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Format"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          }
        },
        "type": "object",
        "title": "AlertUpdate",
        "description": "Request model for updating an alert."
      },
      "AuthorCreate": {
        "properties": {
          "scholar_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scholar Id",
            "description": "Google Scholar ID"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id",
            "description": "OpenAlex author ID"
          },
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid",
            "description": "ORCID"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "Optional display name fallback"
          }
        },
        "type": "object",
        "title": "AuthorCreate",
        "description": "Request model for creating a new author."
      },
      "AuthorFollowFromPaperRequest": {
        "properties": {
          "paper_id": {
            "type": "string",
            "title": "Paper Id",
            "description": "Paper UUID"
          },
          "author_name": {
            "type": "string",
            "minLength": 1,
            "title": "Author Name",
            "description": "Author name shown on the paper card"
          }
        },
        "type": "object",
        "required": [
          "paper_id",
          "author_name"
        ],
        "title": "AuthorFollowFromPaperRequest",
        "description": "Request model for following one author from a paper card."
      },
      "AuthorFollowFromPaperResponse": {
        "properties": {
          "author": {
            "$ref": "#/components/schemas/AuthorResponse"
          },
          "created": {
            "type": "boolean",
            "title": "Created",
            "default": false
          },
          "already_followed": {
            "type": "boolean",
            "title": "Already Followed",
            "default": false
          },
          "matched_via": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Matched Via"
          }
        },
        "type": "object",
        "required": [
          "author"
        ],
        "title": "AuthorFollowFromPaperResponse",
        "description": "Follow-author result for paper-card actions."
      },
      "AuthorMergeMatch": {
        "properties": {
          "author_id": {
            "type": "string",
            "title": "Author Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "confidence": {
            "type": "string",
            "title": "Confidence"
          }
        },
        "type": "object",
        "required": [
          "author_id",
          "name",
          "confidence"
        ],
        "title": "AuthorMergeMatch",
        "description": "The followed author a suggestion is a likely name-duplicate of."
      },
      "AuthorResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "added_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Added At"
          },
          "publication_count": {
            "type": "integer",
            "title": "Publication Count",
            "default": 0
          },
          "affiliation": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Affiliation"
          },
          "email_domain": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email Domain"
          },
          "citedby": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Citedby"
          },
          "h_index": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "H Index"
          },
          "interests": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Interests"
          },
          "url_picture": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url Picture"
          },
          "works_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Works Count"
          },
          "last_fetched_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Fetched At"
          },
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "scholar_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scholar Id"
          },
          "author_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Type"
          },
          "id_resolution_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Status"
          },
          "id_resolution_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Reason"
          },
          "id_resolution_updated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Updated At"
          },
          "id_resolution_method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Method"
          },
          "id_resolution_confidence": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Confidence"
          },
          "monitor_health": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Health"
          },
          "monitor_health_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Health Reason"
          },
          "monitor_last_checked_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Last Checked At"
          },
          "monitor_last_success_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Last Success At"
          },
          "monitor_last_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Last Status"
          },
          "monitor_last_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Last Error"
          },
          "monitor_last_result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Last Result"
          },
          "monitor_papers_found": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Papers Found"
          },
          "monitor_items_created": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Items Created"
          },
          "background_corpus_state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Background Corpus State"
          },
          "background_corpus_detail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Background Corpus Detail"
          },
          "background_corpus_last_success_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Background Corpus Last Success At"
          },
          "background_corpus_age_days": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Background Corpus Age Days"
          },
          "background_corpus_publications": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Background Corpus Publications"
          },
          "background_corpus_coverage_ratio": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Background Corpus Coverage Ratio"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "title": "AuthorResponse",
        "description": "Response model for author data."
      },
      "AuthorSuggestionResponse": {
        "properties": {
          "key": {
            "type": "string",
            "title": "Key"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "suggestion_type": {
            "type": "string",
            "title": "Suggestion Type"
          },
          "score": {
            "type": "number",
            "title": "Score",
            "default": 0.0
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "existing_author_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Existing Author Id"
          },
          "known_author_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Known Author Type"
          },
          "duplicate_of": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AuthorMergeMatch"
              },
              {
                "type": "null"
              }
            ]
          },
          "shared_paper_count": {
            "type": "integer",
            "title": "Shared Paper Count",
            "default": 0
          },
          "shared_followed_count": {
            "type": "integer",
            "title": "Shared Followed Count",
            "default": 0
          },
          "local_paper_count": {
            "type": "integer",
            "title": "Local Paper Count",
            "default": 0
          },
          "recent_paper_count": {
            "type": "integer",
            "title": "Recent Paper Count",
            "default": 0
          },
          "shared_followed_authors": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Shared Followed Authors"
          },
          "shared_topics": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Shared Topics"
          },
          "shared_venues": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Shared Venues"
          },
          "sample_titles": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Sample Titles"
          },
          "signals": {
            "items": {
              "$ref": "#/components/schemas/AuthorSuggestionSignal"
            },
            "type": "array",
            "title": "Signals"
          },
          "negative_signal": {
            "type": "number",
            "title": "Negative Signal",
            "default": 0.0
          },
          "last_removed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Removed At"
          },
          "consensus_count": {
            "type": "integer",
            "title": "Consensus Count",
            "default": 1
          },
          "consensus_buckets": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Consensus Buckets"
          },
          "paper_signal_adjustment": {
            "type": "number",
            "title": "Paper Signal Adjustment",
            "default": 0.0
          },
          "bucket_calibration_multiplier": {
            "type": "number",
            "title": "Bucket Calibration Multiplier",
            "default": 1.0
          }
        },
        "type": "object",
        "required": [
          "key",
          "name",
          "suggestion_type"
        ],
        "title": "AuthorSuggestionResponse",
        "description": "Suggested collaborator or adjacent author to monitor."
      },
      "AuthorSuggestionSignal": {
        "properties": {
          "kind": {
            "type": "string",
            "title": "Kind"
          },
          "label": {
            "type": "string",
            "title": "Label"
          },
          "count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Count"
          },
          "value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Value"
          },
          "subject": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subject"
          }
        },
        "type": "object",
        "required": [
          "kind",
          "label"
        ],
        "title": "AuthorSuggestionSignal",
        "description": "One piece of evidence backing an author suggestion.\n\nT7 (2026-04-24) \u2014 replaces the single opaque `suggestion_type`\nlabel with a priority-ordered list of concrete evidence chips.\n`label` is the user-facing string; `kind` is a stable machine\ntag for analytics / future targeting. `count` / `value` /\n`subject` are optional numeric / string facets the UI can use\nfor tooltip-rich rendering."
      },
      "AuthorTopWorksRequest": {
        "properties": {
          "openalex_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 25,
            "title": "Openalex Ids"
          },
          "per_author": {
            "type": "integer",
            "maximum": 5.0,
            "minimum": 1.0,
            "title": "Per Author",
            "default": 2
          }
        },
        "type": "object",
        "title": "AuthorTopWorksRequest",
        "description": "Resolve the two most-cited papers for a set of OpenAlex author ids."
      },
      "AuthorTypeUpdateRequest": {
        "properties": {
          "author_type": {
            "type": "string",
            "title": "Author Type"
          }
        },
        "type": "object",
        "required": [
          "author_type"
        ],
        "title": "AuthorTypeUpdateRequest"
      },
      "BackfillAuthorWorksRequest": {
        "properties": {
          "author_openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Openalex Id",
            "description": "Single author OpenAlex id, or null for the full batch"
          },
          "full_refetch": {
            "type": "boolean",
            "title": "Full Refetch",
            "description": "Bypass the 'local paper count >= declared works_count' skip shortcut",
            "default": false
          },
          "limit": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Limit",
            "description": "Batch runs only: cap the number of authors processed this job"
          }
        },
        "type": "object",
        "title": "BackfillAuthorWorksRequest",
        "description": "Trigger a full works + vectors backfill for one author or the batch.\n\nWhen `author_openalex_id` is null the runner enumerates every\nresolved corpus author whose `author_centroids` row is missing or\nolder than 14 days. Set `full_refetch=True` to bypass the\n`local >= declared` shortcut on per-author runs \u2014 useful when\nOpenAlex reshuffles counts and the shortcut would cache stale\ncoverage."
      },
      "BibtexTextImportRequest": {
        "properties": {
          "content": {
            "type": "string",
            "title": "Content"
          },
          "collection_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collection Name"
          }
        },
        "type": "object",
        "required": [
          "content"
        ],
        "title": "BibtexTextImportRequest",
        "description": "Request model for importing BibTeX from text."
      },
      "Body_import_bibtex_file_endpoint_api_v1_library_import_bibtex_post": {
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "description": "A .bib file to import"
          },
          "collection_name": {
            "type": "string",
            "title": "Collection Name",
            "description": "Optional target collection name"
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_import_bibtex_file_endpoint_api_v1_library_import_bibtex_post"
      },
      "Body_import_zotero_rdf_file_endpoint_api_v1_library_import_zotero_rdf_post": {
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "description": "A Zotero RDF (.rdf) export file"
          },
          "collection_name": {
            "type": "string",
            "title": "Collection Name",
            "description": "Optional target collection name"
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_import_zotero_rdf_file_endpoint_api_v1_library_import_zotero_rdf_post"
      },
      "Body_preflight_bibtex_file_endpoint_api_v1_library_import_preflight_bibtex_post": {
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "description": "A .bib file to preview"
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_preflight_bibtex_file_endpoint_api_v1_library_import_preflight_bibtex_post"
      },
      "Body_preflight_zotero_rdf_file_endpoint_api_v1_library_import_preflight_zotero_rdf_post": {
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "description": "A Zotero RDF (.rdf) export file to preview"
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_preflight_zotero_rdf_file_endpoint_api_v1_library_import_preflight_zotero_rdf_post"
      },
      "BranchPreviewItem": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "label": {
            "type": "string",
            "title": "Label"
          },
          "seed_count": {
            "type": "integer",
            "title": "Seed Count"
          },
          "branch_score": {
            "type": "number",
            "title": "Branch Score",
            "default": 0.0
          },
          "core_topics": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Core Topics"
          },
          "explore_topics": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Explore Topics"
          },
          "direction_hint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Direction Hint"
          },
          "sample_papers": {
            "items": {
              "$ref": "#/components/schemas/BranchSeedSample"
            },
            "type": "array",
            "title": "Sample Papers"
          },
          "control_state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Control State"
          },
          "is_pinned": {
            "type": "boolean",
            "title": "Is Pinned",
            "default": false
          },
          "is_boosted": {
            "type": "boolean",
            "title": "Is Boosted",
            "default": false
          },
          "is_muted": {
            "type": "boolean",
            "title": "Is Muted",
            "default": false
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active",
            "default": true
          },
          "recommendation_count": {
            "type": "integer",
            "title": "Recommendation Count",
            "default": 0
          },
          "avg_score": {
            "type": "number",
            "title": "Avg Score",
            "default": 0.0
          },
          "positive_rate": {
            "type": "number",
            "title": "Positive Rate",
            "default": 0.0
          },
          "dismiss_rate": {
            "type": "number",
            "title": "Dismiss Rate",
            "default": 0.0
          },
          "engagement_rate": {
            "type": "number",
            "title": "Engagement Rate",
            "default": 0.0
          },
          "unseen": {
            "type": "integer",
            "title": "Unseen",
            "default": 0
          },
          "unique_sources": {
            "type": "integer",
            "title": "Unique Sources",
            "default": 0
          },
          "auto_weight": {
            "type": "number",
            "title": "Auto Weight",
            "default": 1.0
          },
          "auto_weight_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Weight Reason"
          }
        },
        "type": "object",
        "required": [
          "id",
          "label",
          "seed_count"
        ],
        "title": "BranchPreviewItem",
        "description": "One branch node in the lens branch explorer."
      },
      "BranchSeedSample": {
        "properties": {
          "paper_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paper Id"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Year"
          },
          "rating": {
            "type": "integer",
            "title": "Rating",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "title"
        ],
        "title": "BranchSeedSample",
        "description": "Small paper summary for branch visualization previews."
      },
      "BranchTuningActionRequest": {
        "properties": {
          "branch_id": {
            "type": "string",
            "title": "Branch Id"
          },
          "action": {
            "type": "string",
            "title": "Action"
          }
        },
        "type": "object",
        "required": [
          "branch_id",
          "action"
        ],
        "title": "BranchTuningActionRequest"
      },
      "BulkSuggestResponse": {
        "properties": {
          "job_id": {
            "type": "string",
            "title": "Job Id",
            "description": "Background job identifier"
          },
          "operation_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Operation Id",
            "description": "Canonical operation identifier"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status",
            "description": "Operation enqueue status"
          },
          "activity_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Activity Url",
            "description": "Activity log URL"
          },
          "operation_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Operation Key",
            "description": "Operation dedupe key"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Status message"
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "message"
        ],
        "title": "BulkSuggestResponse",
        "description": "Response for bulk tag suggestion generation."
      },
      "ClusterLabelRefreshRequest": {
        "properties": {
          "graph_type": {
            "type": "string",
            "title": "Graph Type",
            "default": "paper_map"
          },
          "scope": {
            "type": "string",
            "title": "Scope",
            "default": "library"
          }
        },
        "type": "object",
        "title": "ClusterLabelRefreshRequest"
      },
      "CollectionCreate": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "color": {
            "type": "string",
            "title": "Color",
            "default": "#3B82F6"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "CollectionCreate",
        "description": "Request model for creating a collection."
      },
      "CollectionResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "color": {
            "type": "string",
            "title": "Color"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "item_count": {
            "type": "integer",
            "title": "Item Count",
            "default": 0
          },
          "last_added_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Added At"
          },
          "avg_citations": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Citations"
          },
          "avg_rating": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Rating"
          },
          "activity_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Activity Status"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "color",
          "created_at"
        ],
        "title": "CollectionResponse",
        "description": "Response model for a collection."
      },
      "ComputeEmbeddingsResponse": {
        "properties": {
          "job_id": {
            "type": "string",
            "title": "Job Id"
          },
          "operation_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Operation Id"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "activity_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Activity Url"
          },
          "operation_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Operation Key"
          },
          "scope": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scope"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "message"
        ],
        "title": "ComputeEmbeddingsResponse",
        "description": "Response body for POST /compute-embeddings."
      },
      "ConfirmIdentifiersRequest": {
        "properties": {
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "scholar_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scholar Id"
          },
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "default": "resolved_manual"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          }
        },
        "type": "object",
        "title": "ConfirmIdentifiersRequest"
      },
      "ConfirmOpenAlexRequest": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "title": "Openalex Id"
          }
        },
        "type": "object",
        "required": [
          "openalex_id"
        ],
        "title": "ConfirmOpenAlexRequest"
      },
      "ConfirmStagedImportResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status"
          },
          "paper_id": {
            "type": "string",
            "title": "Paper Id"
          }
        },
        "type": "object",
        "required": [
          "status",
          "paper_id"
        ],
        "title": "ConfirmStagedImportResponse"
      },
      "DeleteInactiveEmbeddingsResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status"
          },
          "active_model": {
            "type": "string",
            "title": "Active Model"
          },
          "deleted": {
            "type": "integer",
            "title": "Deleted"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "status",
          "active_model",
          "deleted",
          "message"
        ],
        "title": "DeleteInactiveEmbeddingsResponse",
        "description": "Response body for DELETE /embeddings/inactive."
      },
      "DiscoveryBranchSettings": {
        "properties": {
          "temperature": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Temperature",
            "default": 0.28
          },
          "max_clusters": {
            "type": "integer",
            "maximum": 12.0,
            "minimum": 2.0,
            "title": "Max Clusters",
            "default": 6
          },
          "max_active_for_retrieval": {
            "type": "integer",
            "maximum": 12.0,
            "minimum": 1.0,
            "title": "Max Active For Retrieval",
            "default": 4
          },
          "query_core_variants": {
            "type": "integer",
            "maximum": 4.0,
            "minimum": 1.0,
            "title": "Query Core Variants",
            "default": 2
          },
          "query_explore_variants": {
            "type": "integer",
            "maximum": 4.0,
            "minimum": 1.0,
            "title": "Query Explore Variants",
            "default": 2
          }
        },
        "type": "object",
        "title": "DiscoveryBranchSettings",
        "description": "Global branch-behavior defaults used by branch-aware retrieval."
      },
      "DiscoveryCache": {
        "properties": {
          "similarity_ttl_hours": {
            "type": "integer",
            "maximum": 168.0,
            "minimum": 1.0,
            "title": "Similarity Ttl Hours",
            "default": 24
          }
        },
        "type": "object",
        "title": "DiscoveryCache",
        "description": "Cache settings for similarity searches."
      },
      "DiscoveryImpressionBatch": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/DiscoveryImpressionItem"
            },
            "type": "array",
            "maxItems": 200,
            "minItems": 1,
            "title": "Items"
          }
        },
        "type": "object",
        "required": [
          "items"
        ],
        "title": "DiscoveryImpressionBatch",
        "description": "Idempotent batch of first-visibility observations."
      },
      "DiscoveryImpressionBatchResponse": {
        "properties": {
          "received": {
            "type": "integer",
            "title": "Received"
          },
          "inserted": {
            "type": "integer",
            "title": "Inserted"
          }
        },
        "type": "object",
        "required": [
          "received",
          "inserted"
        ],
        "title": "DiscoveryImpressionBatchResponse"
      },
      "DiscoveryImpressionItem": {
        "properties": {
          "recommendation_id": {
            "type": "string",
            "minLength": 1,
            "title": "Recommendation Id"
          },
          "position": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Position"
          },
          "surface": {
            "type": "string",
            "enum": [
              "discovery_card",
              "discovery_compact"
            ],
            "title": "Surface"
          },
          "sort_mode": {
            "type": "string",
            "enum": [
              "relevance",
              "recent",
              "custom"
            ],
            "title": "Sort Mode"
          }
        },
        "type": "object",
        "required": [
          "recommendation_id",
          "position",
          "surface",
          "sort_mode"
        ],
        "title": "DiscoveryImpressionItem",
        "description": "One recommendation that was actually visible on a Discovery surface."
      },
      "DiscoveryLimits": {
        "properties": {
          "max_results": {
            "type": "integer",
            "maximum": 200.0,
            "minimum": 10.0,
            "title": "Max Results",
            "default": 50
          },
          "min_score": {
            "type": "number",
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Min Score",
            "default": 0.0
          },
          "max_candidates_per_strategy": {
            "type": "integer",
            "maximum": 50.0,
            "minimum": 5.0,
            "title": "Max Candidates Per Strategy",
            "default": 20
          },
          "recency_window_years": {
            "type": "integer",
            "maximum": 20.0,
            "minimum": 1.0,
            "title": "Recency Window Years",
            "default": 10
          },
          "feedback_decay_days_full": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Feedback Decay Days Full",
            "default": 90
          },
          "feedback_decay_days_half": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Feedback Decay Days Half",
            "default": 180
          }
        },
        "type": "object",
        "title": "DiscoveryLimits",
        "description": "Numeric limits for the discovery engine."
      },
      "DiscoveryMonitorDefaults": {
        "properties": {
          "author_per_refresh": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Author Per Refresh",
            "default": 20
          },
          "search_limit": {
            "type": "integer",
            "maximum": 50.0,
            "minimum": 1.0,
            "title": "Search Limit",
            "default": 15
          },
          "search_temperature": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Search Temperature",
            "default": 0.22
          },
          "recency_years": {
            "type": "integer",
            "maximum": 10.0,
            "minimum": 0.0,
            "title": "Recency Years",
            "default": 2
          },
          "include_preprints": {
            "type": "boolean",
            "title": "Include Preprints",
            "default": true
          },
          "semantic_scholar_bulk": {
            "type": "boolean",
            "title": "Semantic Scholar Bulk",
            "default": true
          }
        },
        "type": "object",
        "title": "DiscoveryMonitorDefaults",
        "description": "Default retrieval behavior for Feed monitors."
      },
      "DiscoverySchedule": {
        "properties": {
          "refresh_enabled": {
            "type": "boolean",
            "title": "Refresh Enabled",
            "default": false
          },
          "refresh_interval_hours": {
            "type": "integer",
            "maximum": 168.0,
            "minimum": 0.0,
            "title": "Refresh Interval Hours",
            "default": 6
          },
          "graph_maintenance_interval_hours": {
            "type": "integer",
            "maximum": 168.0,
            "minimum": 0.0,
            "title": "Graph Maintenance Interval Hours",
            "default": 24
          }
        },
        "type": "object",
        "title": "DiscoverySchedule",
        "description": "Schedule settings for automatic recommendation refresh.\n\nAuto-refresh is opt-in: the periodic job registers only when\n``refresh_enabled`` is true AND ``refresh_interval_hours`` > 0. The\nDiscovery page toggle drives ``refresh_enabled``; the interval lives in\nSettings."
      },
      "DiscoverySettingsResponse": {
        "properties": {
          "weights": {
            "$ref": "#/components/schemas/DiscoveryWeights"
          },
          "strategies": {
            "$ref": "#/components/schemas/DiscoveryStrategies"
          },
          "limits": {
            "$ref": "#/components/schemas/DiscoveryLimits"
          },
          "schedule": {
            "$ref": "#/components/schemas/DiscoverySchedule"
          },
          "cache": {
            "$ref": "#/components/schemas/DiscoveryCache"
          },
          "sources": {
            "$ref": "#/components/schemas/DiscoverySources"
          },
          "branches": {
            "$ref": "#/components/schemas/DiscoveryBranchSettings"
          },
          "monitor_defaults": {
            "$ref": "#/components/schemas/DiscoveryMonitorDefaults"
          },
          "embedding_model": {
            "type": "string",
            "title": "Embedding Model",
            "default": "allenai/specter2_base"
          },
          "recommendation_mode": {
            "type": "string",
            "title": "Recommendation Mode",
            "default": "balanced"
          }
        },
        "type": "object",
        "title": "DiscoverySettingsResponse",
        "description": "Full discovery settings response."
      },
      "DiscoverySettingsUpdate": {
        "properties": {
          "weights": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoveryWeights"
              },
              {
                "type": "null"
              }
            ]
          },
          "strategies": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoveryStrategies"
              },
              {
                "type": "null"
              }
            ]
          },
          "limits": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoveryLimits"
              },
              {
                "type": "null"
              }
            ]
          },
          "schedule": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoverySchedule"
              },
              {
                "type": "null"
              }
            ]
          },
          "cache": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoveryCache"
              },
              {
                "type": "null"
              }
            ]
          },
          "sources": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoverySources"
              },
              {
                "type": "null"
              }
            ]
          },
          "branches": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoveryBranchSettings"
              },
              {
                "type": "null"
              }
            ]
          },
          "monitor_defaults": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DiscoveryMonitorDefaults"
              },
              {
                "type": "null"
              }
            ]
          },
          "embedding_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Embedding Model"
          },
          "recommendation_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recommendation Mode"
          }
        },
        "type": "object",
        "title": "DiscoverySettingsUpdate",
        "description": "Partial update for discovery settings."
      },
      "DiscoverySourcePolicy": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          }
        },
        "type": "object",
        "title": "DiscoverySourcePolicy",
        "description": "One external source toggle."
      },
      "DiscoverySources": {
        "properties": {
          "openalex": {
            "$ref": "#/components/schemas/DiscoverySourcePolicy"
          },
          "semantic_scholar": {
            "$ref": "#/components/schemas/DiscoverySourcePolicy"
          },
          "crossref": {
            "$ref": "#/components/schemas/DiscoverySourcePolicy"
          },
          "arxiv": {
            "$ref": "#/components/schemas/DiscoverySourcePolicy"
          },
          "biorxiv": {
            "$ref": "#/components/schemas/DiscoverySourcePolicy"
          },
          "europe_pmc": {
            "$ref": "#/components/schemas/DiscoverySourcePolicy"
          }
        },
        "type": "object",
        "title": "DiscoverySources",
        "description": "Source control plane for external discovery retrieval."
      },
      "DiscoveryStrategies": {
        "properties": {
          "related_works": {
            "type": "boolean",
            "title": "Related Works",
            "default": true
          },
          "topic_search": {
            "type": "boolean",
            "title": "Topic Search",
            "default": true
          },
          "followed_authors": {
            "type": "boolean",
            "title": "Followed Authors",
            "default": true
          },
          "coauthor_network": {
            "type": "boolean",
            "title": "Coauthor Network",
            "default": true
          },
          "citation_chain": {
            "type": "boolean",
            "title": "Citation Chain",
            "default": true
          },
          "semantic_scholar": {
            "type": "boolean",
            "title": "Semantic Scholar",
            "default": true
          },
          "branch_explorer": {
            "type": "boolean",
            "title": "Branch Explorer",
            "default": true
          },
          "taste_topics": {
            "type": "boolean",
            "title": "Taste Topics",
            "default": true
          },
          "taste_authors": {
            "type": "boolean",
            "title": "Taste Authors",
            "default": true
          },
          "taste_venues": {
            "type": "boolean",
            "title": "Taste Venues",
            "default": true
          },
          "recent_wins": {
            "type": "boolean",
            "title": "Recent Wins",
            "default": true
          }
        },
        "type": "object",
        "title": "DiscoveryStrategies",
        "description": "Toggle switches for each retrieval strategy."
      },
      "DiscoveryWeights": {
        "properties": {
          "source_relevance": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Source Relevance",
            "default": 0.15
          },
          "topic_score": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Topic Score",
            "default": 0.2
          },
          "text_similarity": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Text Similarity",
            "default": 0.2
          },
          "author_affinity": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Author Affinity",
            "default": 0.15
          },
          "journal_affinity": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Journal Affinity",
            "default": 0.05
          },
          "recency_boost": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Recency Boost",
            "default": 0.1
          },
          "citation_quality": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Citation Quality",
            "default": 0.05
          },
          "feedback_adj": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Feedback Adj",
            "default": 0.1
          },
          "preference_affinity": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Preference Affinity",
            "default": 0.1
          }
        },
        "type": "object",
        "title": "DiscoveryWeights",
        "description": "Weights for scoring signals (should sum to ~1.0)."
      },
      "ErrorResponse": {
        "properties": {
          "error": {
            "type": "string",
            "title": "Error"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "detail": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Detail"
          }
        },
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "title": "ErrorResponse"
      },
      "ExtensionLookupRequest": {
        "properties": {
          "doi": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Doi"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Year"
          },
          "resolve": {
            "type": "boolean",
            "title": "Resolve",
            "default": false
          }
        },
        "type": "object",
        "title": "ExtensionLookupRequest",
        "description": "Identify a paper to check membership + (optionally) resolve metadata."
      },
      "ExtensionSaveRequest": {
        "properties": {
          "action": {
            "type": "string",
            "title": "Action",
            "description": "add | like | love \u2192 3/4/5 stars",
            "default": "add"
          },
          "destination": {
            "type": "string",
            "title": "Destination",
            "description": "library (untriaged) | reading_list (reading_status='reading')",
            "default": "library"
          },
          "doi": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Doi"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "authors": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Authors"
          },
          "year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Year"
          },
          "journal": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Journal"
          },
          "abstract": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Abstract"
          },
          "collection_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collection Id"
          },
          "collection_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collection Name"
          }
        },
        "type": "object",
        "title": "ExtensionSaveRequest",
        "description": "A single paper scraped from the page the user has open.\n\nAt least one resolvable identifier is required (``doi`` /\n``openalex_id`` / ``title``). The remaining scraped fields are passed\nthrough as the ``candidate`` fallback so a DOI-less page (some\npreprints, working papers) still saves with the metadata we could\nread off the page."
      },
      "ExtensionUndoRequest": {
        "properties": {
          "paper_id": {
            "type": "string",
            "title": "Paper Id"
          },
          "prior": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Prior"
          },
          "collections_added": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collections Added"
          }
        },
        "type": "object",
        "required": [
          "paper_id"
        ],
        "title": "ExtensionUndoRequest",
        "description": "Reverse a connector save using the token returned by /save."
      },
      "FeedBulkActionRequest": {
        "properties": {
          "feed_item_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Feed Item Ids"
          },
          "action": {
            "type": "string",
            "title": "Action"
          }
        },
        "type": "object",
        "required": [
          "feed_item_ids",
          "action"
        ],
        "title": "FeedBulkActionRequest"
      },
      "FeedMonitorCreateRequest": {
        "properties": {
          "monitor_type": {
            "type": "string",
            "title": "Monitor Type",
            "description": "query (keyword monitor) | topic | venue | preprint | branch"
          },
          "query": {
            "type": "string",
            "minLength": 1,
            "title": "Query",
            "description": "Search string or boolean keyword expression used by the monitor"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label",
            "description": "Optional display label"
          },
          "config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Config"
          },
          "source_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Id",
            "description": "Resolved OpenAlex source id (S...) \u2014 REQUIRED for monitor_type='venue' (resolve via /feed/monitors/venue-search)"
          },
          "filter_keywords": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Filter Keywords",
            "description": "Optional keyword filter for venue monitors: admit a paper only if any keyword matches its title or abstract"
          }
        },
        "type": "object",
        "required": [
          "monitor_type",
          "query"
        ],
        "title": "FeedMonitorCreateRequest",
        "description": "Request model for creating a non-author feed monitor."
      },
      "FeedMonitorUpdateRequest": {
        "properties": {
          "query": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Query",
            "description": "Updated search string or boolean keyword expression used by the monitor"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label",
            "description": "Optional display label"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled",
            "description": "Enable or disable this monitor without deleting it"
          },
          "config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Config"
          }
        },
        "type": "object",
        "title": "FeedMonitorUpdateRequest",
        "description": "Request model for updating a feed monitor."
      },
      "FeedSettings": {
        "properties": {
          "auto_refresh_enabled": {
            "type": "boolean",
            "title": "Auto Refresh Enabled",
            "default": false
          },
          "refresh_interval_hours": {
            "type": "integer",
            "maximum": 168.0,
            "minimum": 0.0,
            "title": "Refresh Interval Hours",
            "default": 6
          }
        },
        "type": "object",
        "title": "FeedSettings",
        "description": "Opt-in auto-refresh settings for the feed inbox.\n\nPersisted in the shared ``discovery_settings`` KV store under the\n``schedule.feed_refresh_*`` keys. The Feed page toggle drives\n``auto_refresh_enabled``; the interval lives in Settings. Default OFF \u2014 the\nperiodic job registers only when enabled AND interval > 0."
      },
      "FollowAuthorRequest": {
        "properties": {
          "author_id": {
            "type": "string",
            "title": "Author Id"
          },
          "notify_new_papers": {
            "type": "boolean",
            "title": "Notify New Papers",
            "default": true
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "type": "object",
        "required": [
          "author_id"
        ],
        "title": "FollowAuthorRequest",
        "description": "Request model for following an author.\n\n``author_id`` accepts any author reference the canonical resolver\nunderstands (local ``authors.id`` or an OpenAlex author id \u2014 the row is\ncreated when missing). ``name`` is the display name to stamp on a row\ncreated this way; without it the row would be named after the raw id\nuntil the historical backfill hydrates it."
      },
      "FollowedAuthorResponse": {
        "properties": {
          "author_id": {
            "type": "string",
            "title": "Author Id"
          },
          "followed_at": {
            "type": "string",
            "title": "Followed At"
          },
          "notify_new_papers": {
            "type": "boolean",
            "title": "Notify New Papers"
          },
          "is_owner": {
            "type": "boolean",
            "title": "Is Owner",
            "default": false
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "type": "object",
        "required": [
          "author_id",
          "followed_at",
          "notify_new_papers"
        ],
        "title": "FollowedAuthorResponse",
        "description": "Response model for a followed author."
      },
      "GovernanceSettings": {
        "properties": {
          "idle_wait_minutes": {
            "type": "integer",
            "maximum": 120.0,
            "minimum": 0.0,
            "title": "Idle Wait Minutes",
            "description": "Minutes the app must be idle (no user request) before a background sweep may run. 0 = run as soon as nothing else is active.",
            "default": 3
          },
          "reserved_api_calls": {
            "type": "integer",
            "maximum": 100000.0,
            "minimum": 0.0,
            "title": "Reserved Api Calls",
            "description": "External-API calls (OpenAlex daily quota) a background sweep always leaves for your manual operations.",
            "default": 200
          }
        },
        "type": "object",
        "title": "GovernanceSettings",
        "description": "Background-ops governance knobs (task 37) \u2014 Settings \u2192 Data & system.\n\nKV-backed in the shared `discovery_settings` store; the shipped constants are\nthe defaults. The gate reads `idle_wait_minutes`; the per-sweep reserve + the\nHealth budget read `reserved_api_calls`."
      },
      "GraphData": {
        "properties": {
          "nodes": {
            "items": {
              "$ref": "#/components/schemas/GraphNode"
            },
            "type": "array",
            "title": "Nodes"
          },
          "edges": {
            "items": {
              "$ref": "#/components/schemas/GraphEdge"
            },
            "type": "array",
            "title": "Edges"
          },
          "metadata": {
            "additionalProperties": true,
            "type": "object",
            "title": "Metadata",
            "default": {}
          }
        },
        "type": "object",
        "required": [
          "nodes",
          "edges"
        ],
        "title": "GraphData"
      },
      "GraphEdge": {
        "properties": {
          "source": {
            "type": "string",
            "title": "Source"
          },
          "target": {
            "type": "string",
            "title": "Target"
          },
          "weight": {
            "type": "number",
            "title": "Weight",
            "default": 1.0
          },
          "edge_type": {
            "type": "string",
            "title": "Edge Type",
            "default": "semantic"
          }
        },
        "type": "object",
        "required": [
          "source",
          "target"
        ],
        "title": "GraphEdge"
      },
      "GraphNode": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "x": {
            "type": "number",
            "title": "X",
            "default": 0.5
          },
          "y": {
            "type": "number",
            "title": "Y",
            "default": 0.5
          },
          "cluster_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cluster Id"
          },
          "color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Color"
          },
          "size": {
            "type": "number",
            "title": "Size",
            "default": 1.0
          },
          "node_type": {
            "type": "string",
            "title": "Node Type",
            "default": "paper"
          },
          "in_library": {
            "type": "boolean",
            "title": "In Library",
            "default": true
          },
          "metadata": {
            "additionalProperties": true,
            "type": "object",
            "title": "Metadata",
            "default": {}
          }
        },
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "title": "GraphNode"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "HealthResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status"
          },
          "version": {
            "type": "string",
            "title": "Version"
          },
          "uptime_seconds": {
            "type": "number",
            "title": "Uptime Seconds"
          },
          "database_ok": {
            "type": "boolean",
            "title": "Database Ok"
          }
        },
        "type": "object",
        "required": [
          "status",
          "version",
          "uptime_seconds",
          "database_ok"
        ],
        "title": "HealthResponse"
      },
      "ImportPreflightResponse": {
        "properties": {
          "source": {
            "type": "string",
            "title": "Source"
          },
          "total_entries": {
            "type": "integer",
            "title": "Total Entries"
          },
          "valid_entries": {
            "type": "integer",
            "title": "Valid Entries"
          },
          "parse_errors": {
            "type": "integer",
            "title": "Parse Errors"
          },
          "errors": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Errors"
          },
          "identifiers": {
            "additionalProperties": true,
            "type": "object",
            "title": "Identifiers"
          },
          "metadata": {
            "additionalProperties": true,
            "type": "object",
            "title": "Metadata"
          },
          "dedup": {
            "additionalProperties": true,
            "type": "object",
            "title": "Dedup"
          },
          "likely_source_calls": {
            "additionalProperties": true,
            "type": "object",
            "title": "Likely Source Calls"
          },
          "eta": {
            "additionalProperties": true,
            "type": "object",
            "title": "Eta"
          }
        },
        "type": "object",
        "required": [
          "source",
          "total_entries",
          "valid_entries",
          "parse_errors",
          "identifiers",
          "metadata",
          "dedup",
          "likely_source_calls",
          "eta"
        ],
        "title": "ImportPreflightResponse"
      },
      "IngestOwnerRequest": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "minLength": 1,
            "title": "Openalex Id"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "type": "object",
        "required": [
          "openalex_id"
        ],
        "title": "IngestOwnerRequest"
      },
      "IngestOwnerResponse": {
        "properties": {
          "author_id": {
            "type": "string",
            "title": "Author Id"
          },
          "openalex_id": {
            "type": "string",
            "title": "Openalex Id"
          },
          "job_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Job Id"
          }
        },
        "type": "object",
        "required": [
          "author_id",
          "openalex_id"
        ],
        "title": "IngestOwnerResponse"
      },
      "JobCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "cron_expression": {
            "type": "string",
            "title": "Cron Expression"
          },
          "action": {
            "type": "string",
            "pattern": "^(fetch)$",
            "title": "Action"
          },
          "plugin_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Name"
          },
          "author_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Ids"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "name",
          "cron_expression",
          "action"
        ],
        "title": "JobCreate",
        "description": "Request model for creating a scheduled job."
      },
      "JobResponse": {
        "properties": {
          "id": {
            "type": "integer",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "cron_expression": {
            "type": "string",
            "title": "Cron Expression"
          },
          "action": {
            "type": "string",
            "title": "Action"
          },
          "plugin_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plugin Name"
          },
          "author_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Ids"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "next_run": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Run"
          },
          "last_run": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "cron_expression",
          "action",
          "enabled",
          "created_at"
        ],
        "title": "JobResponse",
        "description": "Response model for job data."
      },
      "LensBranchPreviewResponse": {
        "properties": {
          "lens_id": {
            "type": "string",
            "title": "Lens Id"
          },
          "lens_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lens Name"
          },
          "context_type": {
            "type": "string",
            "title": "Context Type"
          },
          "seed_count": {
            "type": "integer",
            "title": "Seed Count",
            "default": 0
          },
          "temperature": {
            "type": "number",
            "title": "Temperature",
            "default": 0.0
          },
          "resolution": {
            "type": "number",
            "title": "Resolution",
            "default": 1.0
          },
          "generated_at": {
            "type": "string",
            "title": "Generated At"
          },
          "branches": {
            "items": {
              "$ref": "#/components/schemas/BranchPreviewItem"
            },
            "type": "array",
            "title": "Branches"
          }
        },
        "type": "object",
        "required": [
          "lens_id",
          "context_type",
          "generated_at"
        ],
        "title": "LensBranchPreviewResponse",
        "description": "Tree-like preview of branch structure for a lens."
      },
      "LensCreate": {
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "title": "Name"
          },
          "context_type": {
            "type": "string",
            "title": "Context Type",
            "description": "library_global | collection | topic_keyword | tag"
          },
          "context_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Context Config"
          },
          "weights": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Weights"
          }
        },
        "type": "object",
        "required": [
          "name",
          "context_type"
        ],
        "title": "LensCreate",
        "description": "Request model for creating a discovery lens."
      },
      "LensResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "context_type": {
            "type": "string",
            "title": "Context Type"
          },
          "context_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Context Config"
          },
          "weights": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Weights"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "last_refreshed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Refreshed At"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active",
            "default": true
          },
          "position": {
            "type": "integer",
            "title": "Position",
            "default": 0
          },
          "signal_count": {
            "type": "integer",
            "title": "Signal Count",
            "default": 0
          },
          "recommendation_count": {
            "type": "integer",
            "title": "Recommendation Count",
            "default": 0
          },
          "last_suggestion_set_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Suggestion Set Id"
          },
          "last_ranker_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Ranker Version"
          },
          "last_retrieval_summary": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Retrieval Summary"
          },
          "branch_controls": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Controls"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "context_type",
          "created_at"
        ],
        "title": "LensResponse",
        "description": "Response model for a discovery lens."
      },
      "LensUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "context_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Context Config"
          },
          "weights": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Weights"
          },
          "branch_controls": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Controls"
          },
          "is_active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Active"
          }
        },
        "type": "object",
        "title": "LensUpdate",
        "description": "Request model for updating a discovery lens."
      },
      "MaintenanceConfigRequest": {
        "properties": {
          "auto_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Enabled",
            "description": "Allow safe idle repair"
          },
          "auto_daily_cap": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Daily Cap"
          },
          "remembered_manual_limit": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Remembered Manual Limit"
          },
          "request_batch_size": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Batch Size"
          }
        },
        "type": "object",
        "title": "MaintenanceConfigRequest",
        "description": "Partial update \u2014 only provided fields change."
      },
      "ManualAddRequest": {
        "properties": {
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "doi": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Doi"
          },
          "link": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Link"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "query": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Query"
          }
        },
        "type": "object",
        "title": "ManualAddRequest"
      },
      "ManualSearchRequest": {
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1,
            "title": "Query",
            "description": "Search string, title, author:..., DOI, OpenAlex URL/ID, or paper link"
          },
          "limit": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Limit",
            "default": 20
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "ManualSearchRequest"
      },
      "MapSelectionLensCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120,
            "minLength": 1,
            "title": "Name"
          },
          "selection_kind": {
            "type": "string",
            "enum": [
              "papers",
              "authors"
            ],
            "title": "Selection Kind"
          },
          "ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "minItems": 1,
            "title": "Ids"
          },
          "scope": {
            "type": "string",
            "enum": [
              "library",
              "corpus"
            ],
            "title": "Scope"
          }
        },
        "type": "object",
        "required": [
          "name",
          "selection_kind",
          "ids",
          "scope"
        ],
        "title": "MapSelectionLensCreate",
        "description": "Create a collection-backed lens from the current map selection."
      },
      "MapSelectionLensResponse": {
        "properties": {
          "collection_id": {
            "type": "string",
            "title": "Collection Id"
          },
          "lens_id": {
            "type": "string",
            "title": "Lens Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "paper_count": {
            "type": "integer",
            "title": "Paper Count"
          }
        },
        "type": "object",
        "required": [
          "collection_id",
          "lens_id",
          "name",
          "paper_count"
        ],
        "title": "MapSelectionLensResponse",
        "description": "Atomic collection + lens result for a lassoed map region."
      },
      "MergeProfilesRequest": {
        "properties": {
          "alt_author_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Alt Author Ids"
          },
          "alt_openalex_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Alt Openalex Ids"
          },
          "field_choices": {
            "additionalProperties": {
              "additionalProperties": {
                "type": "string"
              },
              "type": "object"
            },
            "type": "object",
            "title": "Field Choices"
          }
        },
        "type": "object",
        "title": "MergeProfilesRequest",
        "description": "Body for `POST /authors/{primary_id}/merge-profiles`. Each\n`alt_author_ids` entry is an `authors.id` value (NOT an OpenAlex\nID) so the frontend can pass through `alt_profiles[].author_id`\nfrom the needs-attention payload directly. `alt_openalex_ids`\nabsorbs identities with NO local row (suggestion-rail duplicates):\npapers reattach + the id is recorded as an alias of the primary.\nAt least one of the two lists must be non-empty."
      },
      "MergeRequest": {
        "properties": {
          "merge_topic_id": {
            "type": "string",
            "title": "Merge Topic Id"
          }
        },
        "type": "object",
        "required": [
          "merge_topic_id"
        ],
        "title": "MergeRequest",
        "description": "Request body for merging two topics."
      },
      "MergeSuggestionRequest": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "title": "Openalex Id"
          },
          "primary_author_id": {
            "type": "string",
            "title": "Primary Author Id"
          }
        },
        "type": "object",
        "required": [
          "openalex_id",
          "primary_author_id"
        ],
        "title": "MergeSuggestionRequest"
      },
      "NotDuplicateRequest": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "title": "Openalex Id"
          }
        },
        "type": "object",
        "required": [
          "openalex_id"
        ],
        "title": "NotDuplicateRequest"
      },
      "OnboardingStatusResponse": {
        "properties": {
          "completed": {
            "type": "boolean",
            "title": "Completed"
          },
          "has_owner": {
            "type": "boolean",
            "title": "Has Owner"
          },
          "library_count": {
            "type": "integer",
            "title": "Library Count"
          },
          "followed_count": {
            "type": "integer",
            "title": "Followed Count"
          },
          "user_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Name"
          }
        },
        "type": "object",
        "required": [
          "completed",
          "has_owner",
          "library_count",
          "followed_count"
        ],
        "title": "OnboardingStatusResponse"
      },
      "OnlineAuthorSearchResult": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "title": "Openalex Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid"
          },
          "institution": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Institution"
          },
          "works_count": {
            "type": "integer",
            "title": "Works Count",
            "default": 0
          },
          "cited_by_count": {
            "type": "integer",
            "title": "Cited By Count",
            "default": 0
          },
          "h_index": {
            "type": "integer",
            "title": "H Index",
            "default": 0
          },
          "i10_index": {
            "type": "integer",
            "title": "I10 Index",
            "default": 0
          },
          "top_topics": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Top Topics",
            "default": []
          },
          "already_followed": {
            "type": "boolean",
            "title": "Already Followed",
            "default": false
          },
          "existing_author_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Existing Author Id"
          },
          "existing_author_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Existing Author Type"
          },
          "top_cited_titles": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Top Cited Titles",
            "default": []
          }
        },
        "type": "object",
        "required": [
          "openalex_id",
          "name"
        ],
        "title": "OnlineAuthorSearchResult",
        "description": "One author candidate from `/library/import/search/authors`."
      },
      "OnlineSearchRequest": {
        "properties": {
          "query": {
            "type": "string",
            "maxLength": 500,
            "minLength": 1,
            "title": "Query",
            "description": "Free-form search: paper title, DOI, OpenAlex URL/ID, `author:<name>`, or `title:<fragment>`."
          },
          "limit": {
            "type": "integer",
            "maximum": 50.0,
            "minimum": 1.0,
            "title": "Limit",
            "default": 20
          },
          "year_min": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 2100.0,
                "minimum": 1800.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Year Min"
          },
          "year_max": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 2100.0,
                "minimum": 1800.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Year Max"
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "OnlineSearchRequest"
      },
      "OnlineSearchSaveRequest": {
        "properties": {
          "action": {
            "type": "string",
            "title": "Action",
            "description": "One of add | like | love | dislike (shared 3/4/5/1 contract)."
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "doi": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Doi"
          },
          "link": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Link"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "query": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Query"
          },
          "candidate": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Candidate",
            "description": "Full multi-source search candidate (fields as returned by `/library/import/search`). Used as a fallback when OpenAlex cannot resolve the paper but another source (Semantic Scholar, Crossref, arXiv, bioRxiv) already provided full metadata."
          },
          "collection_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collection Name",
            "description": "Optional local collection name. When set and the paper lands in Library (add/like/love), the collection is created/found and the paper is added to it. Ignored for dislike."
          },
          "collection_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Collection Ids",
            "description": "Existing collection ids selected by the paper-card chooser."
          }
        },
        "type": "object",
        "required": [
          "action"
        ],
        "title": "OnlineSearchSaveRequest"
      },
      "OwnerIdentity": {
        "properties": {
          "author_id": {
            "type": "string",
            "title": "Author Id"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid"
          }
        },
        "type": "object",
        "required": [
          "author_id"
        ],
        "title": "OwnerIdentity"
      },
      "OwnerProfileResponse": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "title": "Openalex Id"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "institution": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Institution"
          },
          "works_count": {
            "type": "integer",
            "title": "Works Count",
            "default": 0
          },
          "cited_by_count": {
            "type": "integer",
            "title": "Cited By Count",
            "default": 0
          },
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid"
          }
        },
        "type": "object",
        "required": [
          "openalex_id"
        ],
        "title": "OwnerProfileResponse"
      },
      "PaperActionRequest": {
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "add",
              "save",
              "like",
              "love",
              "dislike",
              "dismiss",
              "defer",
              "read",
              "seen",
              "undo"
            ],
            "title": "Action"
          },
          "surface": {
            "type": "string",
            "enum": [
              "feed",
              "discovery",
              "inbox",
              "map",
              "papers",
              "library",
              "onboarding"
            ],
            "title": "Surface",
            "default": "papers"
          },
          "scope_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scope Ref"
          },
          "collection_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collection Ids"
          },
          "undo_aspect": {
            "type": "string",
            "enum": [
              "membership",
              "rating",
              "reading",
              "all"
            ],
            "title": "Undo Aspect",
            "default": "all"
          }
        },
        "type": "object",
        "required": [
          "action"
        ],
        "title": "PaperActionRequest",
        "description": "One user action on one paper, from whichever surface raised it.\n\n`save` is accepted as Discovery's spelling of `add`. `defer` is the Inbox\n\u2715 \u2014 leaves the Inbox for `tracked` writing no rating and no feedback event,\ndeliberately NOT `dismiss` (the global hide). See docs/concepts/inbox.md."
      },
      "PaperActionResponse": {
        "properties": {
          "paper_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paper Id"
          },
          "action": {
            "type": "string",
            "title": "Action"
          },
          "surface": {
            "type": "string",
            "title": "Surface"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "rating": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating"
          },
          "surface_result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Surface Result"
          }
        },
        "type": "object",
        "required": [
          "action",
          "surface"
        ],
        "title": "PaperActionResponse"
      },
      "PaperResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "Paper UUID"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "authors": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Authors"
          },
          "year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Year"
          },
          "journal": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Journal"
          },
          "abstract": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Abstract"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "doi": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Doi"
          },
          "publication_date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Publication Date"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "work_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Work Type"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Language"
          },
          "is_oa": {
            "type": "boolean",
            "title": "Is Oa",
            "default": false
          },
          "oa_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Oa Status"
          },
          "oa_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Oa Url"
          },
          "is_retracted": {
            "type": "boolean",
            "title": "Is Retracted",
            "default": false
          },
          "fwci": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Fwci"
          },
          "cited_by_count": {
            "type": "integer",
            "title": "Cited By Count",
            "default": 0
          },
          "referenced_works_count": {
            "type": "integer",
            "title": "Referenced Works Count",
            "default": 0
          },
          "keywords": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Keywords"
          },
          "tldr": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tldr"
          },
          "influential_citation_count": {
            "type": "integer",
            "title": "Influential Citation Count",
            "default": 0
          },
          "status": {
            "type": "string",
            "title": "Status",
            "default": "tracked"
          },
          "rating": {
            "type": "integer",
            "title": "Rating",
            "default": 0
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "added_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Added At"
          },
          "added_from": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Added From"
          },
          "reading_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reading Status"
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At"
          },
          "openalex_resolution_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Resolution Status"
          },
          "openalex_resolution_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Resolution Reason"
          },
          "source_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Id"
          },
          "global_signal_score": {
            "type": "number",
            "title": "Global Signal Score",
            "default": 0.0
          }
        },
        "type": "object",
        "required": [
          "id",
          "title"
        ],
        "title": "PaperResponse",
        "description": "Response model for a paper."
      },
      "PickAffiliationRequest": {
        "properties": {
          "institution_name": {
            "type": "string",
            "title": "Institution Name",
            "description": "Institution to display for this author"
          },
          "institution_openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Institution Openalex Id"
          },
          "institution_ror": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Institution Ror"
          }
        },
        "type": "object",
        "required": [
          "institution_name"
        ],
        "title": "PickAffiliationRequest"
      },
      "PluginActivation": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "enabled"
        ],
        "title": "PluginActivation"
      },
      "PluginConfigResponse": {
        "properties": {
          "plugin_id": {
            "type": "string",
            "title": "Plugin Id"
          },
          "config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config"
          }
        },
        "type": "object",
        "required": [
          "plugin_id",
          "config"
        ],
        "title": "PluginConfigResponse",
        "description": "Validated configuration for one plugin; secrets are masked."
      },
      "PluginInfo": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "display_name": {
            "type": "string",
            "title": "Display Name"
          },
          "version": {
            "type": "string",
            "title": "Version"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "kind": {
            "type": "string",
            "const": "integration",
            "title": "Kind"
          },
          "config_schema": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config Schema"
          },
          "capabilities": {
            "items": {
              "type": "string",
              "enum": [
                "send",
                "receive"
              ]
            },
            "type": "array",
            "title": "Capabilities"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "configured": {
            "type": "boolean",
            "title": "Configured"
          },
          "can_send": {
            "type": "boolean",
            "title": "Can Send",
            "default": false
          },
          "can_receive": {
            "type": "boolean",
            "title": "Can Receive",
            "default": false
          },
          "status": {
            "additionalProperties": true,
            "type": "object",
            "title": "Status"
          },
          "actions": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Actions"
          },
          "docs_path": {
            "type": "string",
            "title": "Docs Path"
          }
        },
        "type": "object",
        "required": [
          "id",
          "display_name",
          "version",
          "description",
          "kind",
          "config_schema",
          "enabled",
          "configured",
          "docs_path"
        ],
        "title": "PluginInfo",
        "description": "Runtime plugin manifest plus current activation/configuration status."
      },
      "ProfileRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 120,
            "minLength": 1,
            "title": "Name"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "ProfileRequest"
      },
      "PromoteOwnerResponse": {
        "properties": {
          "promoted": {
            "type": "integer",
            "title": "Promoted"
          }
        },
        "type": "object",
        "required": [
          "promoted"
        ],
        "title": "PromoteOwnerResponse"
      },
      "PublicationRef": {
        "properties": {
          "paper_id": {
            "type": "string",
            "title": "Paper Id"
          }
        },
        "type": "object",
        "required": [
          "paper_id"
        ],
        "title": "PublicationRef"
      },
      "PublicationSendItem": {
        "properties": {
          "paper_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paper Id",
            "description": "Paper UUID (preferred)"
          },
          "author_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Id"
          },
          "title": {
            "type": "string",
            "title": "Title",
            "default": ""
          },
          "authors": {
            "type": "string",
            "title": "Authors",
            "default": ""
          },
          "year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Year"
          },
          "abstract": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Abstract"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "citations": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Citations",
            "default": 0
          },
          "journal": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Journal"
          }
        },
        "type": "object",
        "title": "PublicationSendItem",
        "description": "Item to send via a plugin from a preview."
      },
      "ReadingQueueResponse": {
        "properties": {
          "reading": {
            "items": {
              "$ref": "#/components/schemas/PaperResponse"
            },
            "type": "array",
            "title": "Reading"
          },
          "done": {
            "items": {
              "$ref": "#/components/schemas/PaperResponse"
            },
            "type": "array",
            "title": "Done"
          },
          "excluded": {
            "items": {
              "$ref": "#/components/schemas/PaperResponse"
            },
            "type": "array",
            "title": "Excluded"
          }
        },
        "type": "object",
        "title": "ReadingQueueResponse",
        "description": "Response model for reading list grouped by status."
      },
      "ReadingStatusUpdateRequest": {
        "properties": {
          "reading_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reading Status",
            "description": "Reading status: reading | done | excluded | null"
          }
        },
        "type": "object",
        "title": "ReadingStatusUpdateRequest",
        "description": "Request model for updating paper reading status."
      },
      "RecommendationExplainResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "score": {
            "type": "number",
            "title": "Score"
          },
          "source_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Type"
          },
          "source_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Key"
          },
          "breakdown": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Breakdown"
          },
          "explanation": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Explanation"
          }
        },
        "type": "object",
        "required": [
          "id",
          "title",
          "score"
        ],
        "title": "RecommendationExplainResponse",
        "description": "Detailed explanation of a recommendation's score.\n\n``breakdown`` is an opaque ``Dict[str, Any]`` rather than a typed\nPydantic envelope. Different ranker versions emit different signal\ntaxonomies \u2014 the legacy 10-signal layout\n(``source_relevance``, ``topic_score``, ``text_similarity``, \u2026,\n``usefulness_boost``), the v2 retrieval-channel layout\n(``lexical``, ``vector``), and various raw-diagnostic fields \u2014 and a\nhardcoded Pydantic model silently dropped every v2 key via\n``extra='ignore'``, rendering 48 / 201 rows as all-nulls on the live\nDB. The route returns the stored breakdown exactly as scoring wrote\nit, annotated with descriptions for known signal names; the frontend\niterates keys generically and renders the ones it recognises (see\n``components/shared/PaperCard.tsx::SIGNAL_META``)."
      },
      "RecommendationResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "suggestion_set_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suggestion Set Id"
          },
          "lens_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lens Id"
          },
          "paper_id": {
            "type": "string",
            "title": "Paper Id"
          },
          "rank": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rank"
          },
          "score": {
            "type": "number",
            "title": "Score",
            "description": "Recommendation score (0-100)"
          },
          "in_library": {
            "type": "boolean",
            "title": "In Library",
            "description": "Paper is already a saved Library paper (collection lenses surface these so they can be added to the linked collection).",
            "default": false
          },
          "score_breakdown": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Score Breakdown"
          },
          "user_action": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Action"
          },
          "action_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Action At"
          },
          "source_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Type"
          },
          "source_api": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Api"
          },
          "source_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Key"
          },
          "branch_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Id"
          },
          "branch_label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Label"
          },
          "branch_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Branch Mode"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "is_new": {
            "type": "boolean",
            "title": "Is New",
            "default": false
          },
          "paper": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PaperResponse"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "paper_id",
          "score",
          "created_at"
        ],
        "title": "RecommendationResponse",
        "description": "Response model for a recommendation."
      },
      "RefreshAuthorNetworkRequest": {
        "properties": {
          "force": {
            "type": "boolean",
            "title": "Force",
            "description": "Refresh even when cache is fresh",
            "default": false
          }
        },
        "type": "object",
        "title": "RefreshAuthorNetworkRequest",
        "description": "Trigger the two network author-suggestion refresh runners.\n\n`force=True` re-runs both even if their caches are fresh; by\ndefault stale/missing caches are the only ones refreshed\n(fresh caches are left alone \u2014 cheap no-op)."
      },
      "RegionDescribeRequest": {
        "properties": {
          "paper_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Paper Ids"
          }
        },
        "type": "object",
        "required": [
          "paper_ids"
        ],
        "title": "RegionDescribeRequest"
      },
      "RejectSuggestionRequest": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "minLength": 1,
            "title": "Openalex Id",
            "description": "OpenAlex author ID of the suggestion to reject"
          },
          "suggestion_bucket": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suggestion Bucket",
            "description": "Originating rail bucket (library_core / cited_by_high_signal / adjacent / semantic_similar / openalex_related / s2_related). Optional \u2014 used by outcome calibration to reweight per-bucket scoring; NULL is fine for non-rail rejections."
          }
        },
        "type": "object",
        "required": [
          "openalex_id"
        ],
        "title": "RejectSuggestionRequest"
      },
      "ReorderRequest": {
        "properties": {
          "ordered_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Ordered Ids",
            "description": "Row ids in their new order; index becomes position"
          }
        },
        "type": "object",
        "required": [
          "ordered_ids"
        ],
        "title": "ReorderRequest",
        "description": "Body for a drag-reorder: ids in their new display order."
      },
      "ResolveConflictRequest": {
        "properties": {
          "choice": {
            "type": "string",
            "pattern": "^(primary|alt|dismiss)$",
            "title": "Choice"
          }
        },
        "type": "object",
        "required": [
          "choice"
        ],
        "title": "ResolveConflictRequest",
        "description": "Body for `POST /authors/conflicts/{conflict_id}/resolve`.\n`choice` = which side wins ('primary' or 'alt'). When 'alt' wins,\nthe primary author row's column gets overwritten with the alt's\nvalue before the conflict is marked resolved. `dismiss` skips\nboth \u2014 the conflict goes away without changing the row."
      },
      "ResolveIdentifiersRequest": {
        "properties": {
          "limit": {
            "type": "integer",
            "title": "Limit",
            "default": 200
          },
          "only_unresolved": {
            "type": "boolean",
            "title": "Only Unresolved",
            "default": true
          },
          "background": {
            "type": "boolean",
            "title": "Background",
            "default": true
          },
          "scope": {
            "type": "string",
            "title": "Scope",
            "description": "Which authors to run resolution on: `library` (authors linked to Library papers), `followed` (followed authors only), `corpus` (every author row).",
            "default": "corpus"
          }
        },
        "type": "object",
        "title": "ResolveIdentifiersRequest"
      },
      "ResolveImportedRequest": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/PublicationRef"
            },
            "type": "array",
            "title": "Items"
          },
          "unresolved_only": {
            "type": "boolean",
            "title": "Unresolved Only",
            "default": true
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "default": 1000
          },
          "background": {
            "type": "boolean",
            "title": "Background",
            "default": true
          }
        },
        "type": "object",
        "title": "ResolveImportedRequest"
      },
      "ResolveOpenAlexRequest": {
        "properties": {
          "scholar_id": {
            "type": "string",
            "title": "Scholar Id"
          }
        },
        "type": "object",
        "required": [
          "scholar_id"
        ],
        "title": "ResolveOpenAlexRequest"
      },
      "ResolveOwnerRequest": {
        "properties": {
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          }
        },
        "type": "object",
        "title": "ResolveOwnerRequest"
      },
      "RoundAnswer": {
        "properties": {
          "token": {
            "type": "string",
            "title": "Token"
          },
          "answer": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Answer"
          },
          "reaction_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reaction Ms"
          }
        },
        "type": "object",
        "required": [
          "token"
        ],
        "title": "RoundAnswer"
      },
      "RunMaintenanceRequest": {
        "properties": {
          "target_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Target Ids"
          },
          "max_items": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Items"
          },
          "request_batch_size": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Batch Size"
          },
          "scope": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scope"
          },
          "dry_run": {
            "type": "boolean",
            "title": "Dry Run",
            "default": false
          },
          "force": {
            "type": "boolean",
            "title": "Force",
            "default": false
          },
          "confirmation_token": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Confirmation Token"
          },
          "plan_fingerprint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plan Fingerprint"
          }
        },
        "type": "object",
        "title": "RunMaintenanceRequest",
        "description": "Atomic run controls. The visible values travel with the Run click."
      },
      "SavePublicationsRequest": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/PublicationSendItem"
            },
            "type": "array",
            "title": "Items"
          }
        },
        "type": "object",
        "required": [
          "items"
        ],
        "title": "SavePublicationsRequest",
        "description": "Request to save previewed publications to the database."
      },
      "SemanticPaperSearchRequest": {
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1,
            "title": "Query",
            "description": "Short semantic search query"
          },
          "scope": {
            "type": "string",
            "title": "Scope",
            "description": "Search scope: library | all",
            "default": "library"
          },
          "limit": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Limit",
            "description": "Maximum semantic results",
            "default": 20
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "SemanticPaperSearchRequest",
        "description": "Explicit semantic paper search request."
      },
      "SetIdentifiersRequest": {
        "properties": {
          "orcid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Orcid",
            "description": "ORCID iD (with or without https prefix)"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id",
            "description": "OpenAlex author ID (A1234\u2026 or full URL)"
          },
          "scholar_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scholar Id",
            "description": "Google Scholar user id"
          }
        },
        "type": "object",
        "title": "SetIdentifiersRequest",
        "description": "Manual paste of authoritative identifiers for an author who\nfailed automatic resolution. Any subset is accepted; absent fields\nare left unchanged. ORCID + OpenAlex + Scholar IDs are normalized\nserver-side (URL prefix stripped, lowercased)."
      },
      "SettingsModel": {
        "properties": {
          "backend": {
            "type": "string",
            "pattern": "^(scholar|openalex)$",
            "title": "Backend",
            "description": "Publication backend",
            "default": "openalex"
          },
          "openalex_email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Email",
            "description": "Optional contact email sent with OpenAlex requests"
          },
          "fetch_full_history": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Fetch Full History",
            "description": "Fetch full author history (OpenAlex)",
            "default": false
          },
          "from_year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "From Year",
            "description": "Fetch from this year onward; ignored if fetch_full_history is true"
          },
          "api_call_delay": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Api Call Delay",
            "description": "Legacy UI delay; kept for compatibility",
            "default": "1.0"
          },
          "database": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Database",
            "description": "Relative path to the unified scholar database"
          },
          "openalex_api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Api Key",
            "description": "OpenAlex API key (required \u2014 get one free at openalex.org/settings/api)"
          },
          "semantic_scholar_api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Semantic Scholar Api Key",
            "description": "Semantic Scholar API key (strongly recommended \u2014 avoids shared-pool 429s)"
          },
          "id_resolution_semantic_scholar_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Semantic Scholar Enabled",
            "description": "Use Semantic Scholar API for Scholar ID resolution",
            "default": true
          },
          "id_resolution_orcid_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Orcid Enabled",
            "description": "Use ORCID public API researcher links for Scholar ID resolution",
            "default": true
          },
          "id_resolution_scholar_scrape_auto_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Scholar Scrape Auto Enabled",
            "description": "Allow automatic Google Scholar scraping fallback in pipelines",
            "default": false
          },
          "id_resolution_scholar_scrape_manual_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id Resolution Scholar Scrape Manual Enabled",
            "description": "Allow manual Google Scholar scraping from the Authors UI (opt-in, off by default \u2014 D14)",
            "default": false
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "SettingsModel"
      },
      "SignalLabAuthorDirection": {
        "properties": {
          "key": {
            "type": "string",
            "title": "Key"
          },
          "label": {
            "type": "string",
            "title": "Label"
          },
          "value": {
            "type": "number",
            "title": "Value"
          }
        },
        "type": "object",
        "required": [
          "key",
          "label",
          "value"
        ],
        "title": "SignalLabAuthorDirection",
        "description": "One author the fitted head is moving, by ranker match key."
      },
      "SignalLabCoverageEvidence": {
        "properties": {
          "regions_observed": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Regions Observed"
          },
          "regions_total": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Regions Total"
          },
          "edges_observed": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Edges Observed"
          },
          "edges_total": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Edges Total"
          }
        },
        "type": "object",
        "required": [
          "regions_observed",
          "regions_total",
          "edges_observed",
          "edges_total"
        ],
        "title": "SignalLabCoverageEvidence",
        "description": "Structural super-region and adjacency coverage."
      },
      "SignalLabDirection": {
        "properties": {
          "region_id": {
            "type": "integer",
            "title": "Region Id"
          },
          "label": {
            "type": "string",
            "title": "Label"
          },
          "value": {
            "type": "number",
            "maximum": 1.0,
            "minimum": -1.0,
            "title": "Value"
          }
        },
        "type": "object",
        "required": [
          "region_id",
          "label",
          "value"
        ],
        "title": "SignalLabDirection",
        "description": "One fitted super-region movement shown on Home."
      },
      "SignalLabEffects": {
        "properties": {
          "upward": {
            "items": {
              "$ref": "#/components/schemas/SignalLabDirection"
            },
            "type": "array",
            "title": "Upward"
          },
          "downward": {
            "items": {
              "$ref": "#/components/schemas/SignalLabDirection"
            },
            "type": "array",
            "title": "Downward"
          },
          "regions_moving": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Regions Moving"
          },
          "boundary_overrides": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Boundary Overrides"
          },
          "authors_up": {
            "items": {
              "$ref": "#/components/schemas/SignalLabAuthorDirection"
            },
            "type": "array",
            "title": "Authors Up"
          },
          "authors_down": {
            "items": {
              "$ref": "#/components/schemas/SignalLabAuthorDirection"
            },
            "type": "array",
            "title": "Authors Down"
          },
          "authors_moving": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Authors Moving",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "regions_moving",
          "boundary_overrides"
        ],
        "title": "SignalLabEffects",
        "description": "Active fitted effects; empty while the feature is disabled."
      },
      "SignalLabFitEvidence": {
        "properties": {
          "ready": {
            "type": "boolean",
            "title": "Ready"
          },
          "fresh": {
            "type": "boolean",
            "title": "Fresh"
          },
          "source_rounds": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Source Rounds"
          },
          "fitted_queries": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Fitted Queries"
          },
          "fitted_observations": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Fitted Observations"
          },
          "pending_rounds": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Pending Rounds"
          },
          "utility_preferences": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Utility Preferences"
          },
          "metric_constraints": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Metric Constraints"
          }
        },
        "type": "object",
        "required": [
          "ready",
          "fresh",
          "source_rounds",
          "fitted_queries",
          "fitted_observations",
          "pending_rounds",
          "utility_preferences",
          "metric_constraints"
        ],
        "title": "SignalLabFitEvidence",
        "description": "Evidence actually consumed by the current wholesale fit."
      },
      "SignalLabRoundEvidence": {
        "properties": {
          "today": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Today"
          },
          "total": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Total"
          },
          "answered": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Answered"
          },
          "skipped": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Skipped"
          },
          "unique_queries": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Unique Queries"
          },
          "duplicate_queries": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Duplicate Queries"
          }
        },
        "type": "object",
        "required": [
          "today",
          "total",
          "answered",
          "skipped",
          "unique_queries",
          "duplicate_queries"
        ],
        "title": "SignalLabRoundEvidence",
        "description": "Recorded ledger evidence; unordered paper sets define query identity."
      },
      "SignalLabSettings": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enable Signal Lab",
            "description": "Offer games on Home and consume their retained model.",
            "default": true
          },
          "region_offset_points": {
            "type": "number",
            "maximum": 10.0,
            "minimum": 0.0,
            "title": "Region scoring nudge",
            "description": "Maximum additive Discovery/Feed points from region preference, before the evidence damper scales it down. Reaches full strength only once a region has actually been judged several times.",
            "default": 5.0
          },
          "utility_points": {
            "type": "number",
            "maximum": 10.0,
            "minimum": 0.0,
            "title": "Utility scoring nudge",
            "description": "Maximum additive Discovery/Feed points from the confidence-scaled learned utility direction.",
            "default": 5.0
          },
          "author_offset_points": {
            "type": "number",
            "maximum": 10.0,
            "minimum": 0.0,
            "title": "Author scoring nudge",
            "description": "How much affinity a fully-preferred author gains. Fitted from within-region comparisons only, and ADDED to the author signal your Library already produces \u2014 never a replacement for it.",
            "default": 5.0
          },
          "venue_offset_points": {
            "type": "number",
            "maximum": 10.0,
            "minimum": 0.0,
            "title": "Venue scoring nudge",
            "description": "How much affinity a fully-preferred journal gains. Fitted only from same-field, different-venue rounds \u2014 the one place ALMa can learn which venue you would rather read at equal topic \u2014 and ADDED to the venue signal your Library already produces.",
            "default": 5.0
          },
          "map_tint_strength": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Map taste tint",
            "description": "How strongly learned region preference bends terrain.",
            "default": 0.45
          },
          "ring_decay": {
            "type": "number",
            "maximum": 1.0,
            "exclusiveMinimum": 0.0,
            "title": "Ring decay",
            "description": "Library-outward sampling decay \u03b3.",
            "default": 0.35
          },
          "exploration_rate": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Exploration rate",
            "description": "Ring-uniform sampling fraction \u03b5.",
            "default": 0.2
          },
          "coverage_target": {
            "type": "integer",
            "maximum": 500.0,
            "minimum": 1.0,
            "title": "Coverage Target",
            "default": 20
          },
          "refit_every_rounds": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Refit Every Rounds",
            "default": 5
          },
          "holdout_percent": {
            "type": "integer",
            "maximum": 50.0,
            "minimum": 0.0,
            "title": "Holdout Percent",
            "default": 15
          },
          "override_min_votes": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Override Min Votes",
            "default": 3
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "SignalLabSettings"
      },
      "SignalLabSummaryResponse": {
        "properties": {
          "active": {
            "type": "boolean",
            "title": "Active"
          },
          "rounds": {
            "$ref": "#/components/schemas/SignalLabRoundEvidence"
          },
          "fit": {
            "$ref": "#/components/schemas/SignalLabFitEvidence"
          },
          "coverage": {
            "$ref": "#/components/schemas/SignalLabCoverageEvidence"
          },
          "effects": {
            "$ref": "#/components/schemas/SignalLabEffects"
          }
        },
        "type": "object",
        "required": [
          "active",
          "rounds",
          "fit",
          "coverage",
          "effects"
        ],
        "title": "SignalLabSummaryResponse",
        "description": "Honest Home evidence; never a combinatorial possible-triplet ratio."
      },
      "SimilarityRequest": {
        "properties": {
          "paper_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Paper Ids",
            "description": "Paper UUIDs to use as seeds"
          },
          "limit": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Limit",
            "default": 20
          },
          "force": {
            "type": "boolean",
            "title": "Force",
            "description": "Bypass cache",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "paper_ids"
        ],
        "title": "SimilarityRequest",
        "description": "Request to discover papers similar to given papers."
      },
      "StatisticsResponse": {
        "properties": {
          "total_authors": {
            "type": "integer",
            "title": "Total Authors"
          },
          "total_publications": {
            "type": "integer",
            "title": "Total Publications"
          },
          "total_citations": {
            "type": "integer",
            "title": "Total Citations"
          },
          "active_jobs": {
            "type": "integer",
            "title": "Active Jobs"
          },
          "configured_plugins": {
            "type": "integer",
            "title": "Configured Plugins"
          }
        },
        "type": "object",
        "required": [
          "total_authors",
          "total_publications",
          "total_citations",
          "active_jobs",
          "configured_plugins"
        ],
        "title": "StatisticsResponse",
        "description": "Response model for overall statistics."
      },
      "TagCreate": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "color": {
            "type": "string",
            "title": "Color",
            "default": "#6B7280"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "TagCreate",
        "description": "Request model for creating a tag."
      },
      "TagMergeRequest": {
        "properties": {
          "source_tag_id": {
            "type": "string",
            "title": "Source Tag Id"
          },
          "target_tag_id": {
            "type": "string",
            "title": "Target Tag Id"
          }
        },
        "type": "object",
        "required": [
          "source_tag_id",
          "target_tag_id"
        ],
        "title": "TagMergeRequest",
        "description": "Request body for merging tags."
      },
      "TagMergeSuggestionResponse": {
        "properties": {
          "source_tag_id": {
            "type": "string",
            "title": "Source Tag Id"
          },
          "source_tag": {
            "type": "string",
            "title": "Source Tag"
          },
          "target_tag_id": {
            "type": "string",
            "title": "Target Tag Id"
          },
          "target_tag": {
            "type": "string",
            "title": "Target Tag"
          },
          "confidence": {
            "type": "number",
            "title": "Confidence"
          },
          "reason": {
            "type": "string",
            "title": "Reason"
          }
        },
        "type": "object",
        "required": [
          "source_tag_id",
          "source_tag",
          "target_tag_id",
          "target_tag",
          "confidence",
          "reason"
        ],
        "title": "TagMergeSuggestionResponse",
        "description": "Suggested merge candidate for duplicate/overlapping tags."
      },
      "TagResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "color": {
            "type": "string",
            "title": "Color"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "color"
        ],
        "title": "TagResponse",
        "description": "Response model for a tag."
      },
      "TagSuggestionResponse": {
        "properties": {
          "paper_id": {
            "type": "string",
            "title": "Paper Id",
            "description": "Paper UUID"
          },
          "tag": {
            "type": "string",
            "title": "Tag",
            "description": "Suggested tag name"
          },
          "tag_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tag Id",
            "description": "Tag UUID (if tag already exists)"
          },
          "confidence": {
            "type": "number",
            "title": "Confidence",
            "description": "Confidence score (0-1)"
          },
          "source": {
            "type": "string",
            "title": "Source",
            "description": "Suggestion source: embedding, tfidf, topic, or rule"
          },
          "accepted": {
            "type": "boolean",
            "title": "Accepted",
            "description": "Whether the suggestion has been accepted",
            "default": false
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At",
            "description": "When the suggestion was created"
          }
        },
        "type": "object",
        "required": [
          "paper_id",
          "tag",
          "confidence",
          "source"
        ],
        "title": "TagSuggestionResponse",
        "description": "A single tag suggestion for a publication."
      },
      "TagSuggestionsResponse": {
        "properties": {
          "suggestions": {
            "items": {
              "$ref": "#/components/schemas/TagSuggestionResponse"
            },
            "type": "array",
            "title": "Suggestions",
            "description": "Tag suggestions for the requested publication"
          },
          "paper_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paper Title",
            "description": "Publication title when available"
          }
        },
        "type": "object",
        "title": "TagSuggestionsResponse",
        "description": "Wrapped response for publication tag suggestions."
      },
      "TopicAliasCreateRequest": {
        "properties": {
          "alias": {
            "type": "string",
            "minLength": 1,
            "title": "Alias"
          },
          "canonical": {
            "type": "string",
            "minLength": 1,
            "title": "Canonical"
          }
        },
        "type": "object",
        "required": [
          "alias",
          "canonical"
        ],
        "title": "TopicAliasCreateRequest"
      },
      "TopicCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "title": "Name",
            "description": "Canonical topic name"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "TopicCreateRequest"
      },
      "TopicDomainNode": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "paper_count": {
            "type": "integer",
            "title": "Paper Count"
          },
          "fields": {
            "items": {
              "$ref": "#/components/schemas/TopicFieldNode"
            },
            "type": "array",
            "title": "Fields"
          }
        },
        "type": "object",
        "required": [
          "name",
          "paper_count"
        ],
        "title": "TopicDomainNode"
      },
      "TopicFieldNode": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "paper_count": {
            "type": "integer",
            "title": "Paper Count"
          },
          "subfields": {
            "items": {
              "$ref": "#/components/schemas/TopicHierarchyNode"
            },
            "type": "array",
            "title": "Subfields"
          }
        },
        "type": "object",
        "required": [
          "name",
          "paper_count"
        ],
        "title": "TopicFieldNode"
      },
      "TopicGroupRequest": {
        "properties": {
          "source": {
            "type": "string",
            "minLength": 1,
            "title": "Source"
          },
          "target": {
            "type": "string",
            "minLength": 1,
            "title": "Target"
          }
        },
        "type": "object",
        "required": [
          "source",
          "target"
        ],
        "title": "TopicGroupRequest"
      },
      "TopicHierarchyNode": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "paper_count": {
            "type": "integer",
            "title": "Paper Count"
          }
        },
        "type": "object",
        "required": [
          "name",
          "paper_count"
        ],
        "title": "TopicHierarchyNode"
      },
      "TopicHierarchyResponse": {
        "properties": {
          "domains": {
            "items": {
              "$ref": "#/components/schemas/TopicDomainNode"
            },
            "type": "array",
            "title": "Domains"
          }
        },
        "type": "object",
        "title": "TopicHierarchyResponse"
      },
      "TopicRenameRequest": {
        "properties": {
          "new_name": {
            "type": "string",
            "minLength": 1,
            "title": "New Name"
          }
        },
        "type": "object",
        "required": [
          "new_name"
        ],
        "title": "TopicRenameRequest"
      },
      "TopicSummary": {
        "properties": {
          "canonical": {
            "type": "string",
            "title": "Canonical"
          },
          "paper_count": {
            "type": "integer",
            "title": "Paper Count",
            "default": 0
          },
          "aliases": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Aliases"
          }
        },
        "type": "object",
        "required": [
          "canonical"
        ],
        "title": "TopicSummary"
      },
      "TrackFollowSuggestionRequest": {
        "properties": {
          "openalex_id": {
            "type": "string",
            "minLength": 1,
            "title": "Openalex Id",
            "description": "OpenAlex author ID of the followed suggestion"
          },
          "suggestion_bucket": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suggestion Bucket",
            "description": "Originating rail bucket label (see RejectSuggestionRequest)."
          }
        },
        "type": "object",
        "required": [
          "openalex_id"
        ],
        "title": "TrackFollowSuggestionRequest"
      },
      "TrackRequest": {
        "properties": {
          "event_type": {
            "type": "string",
            "title": "Event Type",
            "description": "One of: external_link_click, abstract_engagement, search_query"
          },
          "paper_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paper Id",
            "description": "Paper ID (null for search queries)"
          },
          "context": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Context",
            "description": "Event-specific context data"
          }
        },
        "type": "object",
        "required": [
          "event_type"
        ],
        "title": "TrackRequest"
      },
      "UserProfileResponse": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "owner": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OwnerIdentity"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "title": "UserProfileResponse",
        "description": "Who ALMa thinks you are \u2014 the greeting name, and the author row you\nclaimed as yourself. Read by Settings so the identity set during onboarding\nstops being write-once."
      },
      "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"
      },
      "VersionResponse": {
        "properties": {
          "api_version": {
            "type": "string",
            "title": "Api Version"
          },
          "app_version": {
            "type": "string",
            "title": "App Version"
          },
          "python_version": {
            "type": "string",
            "title": "Python Version"
          }
        },
        "type": "object",
        "required": [
          "api_version",
          "app_version",
          "python_version"
        ],
        "title": "VersionResponse"
      },
      "ZoteroCollectionResponse": {
        "properties": {
          "key": {
            "type": "string",
            "title": "Key"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "num_items": {
            "type": "integer",
            "title": "Num Items",
            "default": 0
          },
          "parent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent"
          }
        },
        "type": "object",
        "required": [
          "key",
          "name"
        ],
        "title": "ZoteroCollectionResponse",
        "description": "Response model for a Zotero collection."
      },
      "ZoteroCollectionsRequest": {
        "properties": {
          "library_id": {
            "type": "string",
            "title": "Library Id"
          },
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Api Key"
          },
          "library_type": {
            "type": "string",
            "title": "Library Type",
            "default": "user"
          }
        },
        "type": "object",
        "required": [
          "library_id"
        ],
        "title": "ZoteroCollectionsRequest",
        "description": "Request model for listing Zotero collections."
      },
      "ZoteroImportRequest": {
        "properties": {
          "library_id": {
            "type": "string",
            "title": "Library Id"
          },
          "api_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Api Key"
          },
          "library_type": {
            "type": "string",
            "title": "Library Type",
            "default": "user"
          },
          "collection_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collection Key"
          },
          "collection_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Collection Name"
          }
        },
        "type": "object",
        "required": [
          "library_id"
        ],
        "title": "ZoteroImportRequest",
        "description": "Request model for importing from Zotero."
      },
      "_AddItemBody": {
        "properties": {
          "paper_id": {
            "type": "string",
            "title": "Paper Id"
          }
        },
        "type": "object",
        "required": [
          "paper_id"
        ],
        "title": "_AddItemBody"
      },
      "_AddPaperToCollectionsBody": {
        "properties": {
          "collection_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Collection Ids"
          }
        },
        "type": "object",
        "required": [
          "collection_ids"
        ],
        "title": "_AddPaperToCollectionsBody"
      },
      "_AssignTagBody": {
        "properties": {
          "paper_id": {
            "type": "string",
            "title": "Paper Id"
          },
          "tag_id": {
            "type": "string",
            "title": "Tag Id"
          }
        },
        "type": "object",
        "required": [
          "paper_id",
          "tag_id"
        ],
        "title": "_AssignTagBody"
      },
      "_BulkActionRequest": {
        "properties": {
          "paper_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 500,
            "minItems": 1,
            "title": "Paper Ids"
          }
        },
        "type": "object",
        "required": [
          "paper_ids"
        ],
        "title": "_BulkActionRequest"
      },
      "_BulkActionResponse": {
        "properties": {
          "affected": {
            "type": "integer",
            "title": "Affected"
          }
        },
        "type": "object",
        "required": [
          "affected"
        ],
        "title": "_BulkActionResponse"
      },
      "_BulkAddToCollectionRequest": {
        "properties": {
          "paper_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 500,
            "minItems": 1,
            "title": "Paper Ids"
          },
          "collection_id": {
            "type": "string",
            "title": "Collection Id"
          }
        },
        "type": "object",
        "required": [
          "paper_ids",
          "collection_id"
        ],
        "title": "_BulkAddToCollectionRequest"
      },
      "_SavePaperRequest": {
        "properties": {
          "paper_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paper Id"
          },
          "title": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "authors": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Authors"
          },
          "year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Year"
          },
          "journal": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Journal"
          },
          "abstract": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Abstract"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "doi": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Doi"
          },
          "openalex_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Openalex Id"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "rating": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 5.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating"
          },
          "added_from": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Added From",
            "description": "Optional provenance override for manual/library-side saves"
          }
        },
        "type": "object",
        "title": "_SavePaperRequest"
      }
    },
    "securitySchemes": {
      "HTTPBearer": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}
