# Research status

Source: https://musicnerd-docs.vercel.app/api-reference/knowledge/research-status

Read research progress

## GET /api/artist/{id}/research/status

Full OpenAPI specification: https://musicnerd-docs.vercel.app/spec/knowledge.json

## Authentication

This operation requires one of the security alternatives in the specification below. Security scheme definitions are included where present in the published specification.

[Authentication guide](https://musicnerd-docs.vercel.app/authentication)

## Operation and referenced schemas

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Music Nerd shared artist knowledge — draft contract",
    "version": "1.0.0",
    "description": "Shared stored-evidence reads for approved claimants and administrators. Implementation preview contract; not released. No read initiates collection. Legacy extraction coverage is explicit; durable boundary storage and historical source versions remain unavailable."
  },
  "servers": [
    {
      "url": "https://musicnerd-api.vercel.app",
      "description": "Current API project; proposed routes are NOT available yet."
    }
  ],
  "paths": {
    "/api/artist/{id}/research/status": {
      "get": {
        "operationId": "getResearchStatus",
        "summary": "Read research progress",
        "description": "Strict storage read with sanitized job fields and current evidence coverage. Does not run workers, create jobs or expose raw provider state.",
        "security": [
          {
            "privyBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Artist ID in this deployment environment. Authorize claimant/admin on each call.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records; response character/byte budgets may require an earlier continuation.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque artist/filter-bound continuation. A changed ordered corpus returns 409.",
            "schema": {
              "type": "string",
              "maxLength": 4096
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bounded stored evidence; Cache-Control: private, no-store.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResearchStatus"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid access token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not the approved claimant or an admin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Source unavailable after artist authorization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Evidence revision or ordered corpus changed; restart from current metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The stored corpus or one response exceeds the supported bounds; no partial successful corpus is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Storage unavailable; never represented as an empty successful corpus.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ResearchStatus": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "jobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Job"
            },
            "maxItems": 50
          },
          "coverage": {
            "$ref": "#/components/schemas/Coverage"
          },
          "budget": {
            "$ref": "#/components/schemas/Budget"
          }
        },
        "required": [
          "status",
          "jobs",
          "coverage",
          "budget"
        ]
      },
      "Error": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_input",
              "unauthenticated",
              "forbidden",
              "not_found",
              "revision_changed",
              "corpus_changed",
              "throttled",
              "storage_unavailable",
              "corpus_too_large",
              "response_too_large"
            ]
          }
        },
        "required": [
          "status",
          "error",
          "code"
        ]
      },
      "Job": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "kind": {
            "type": "string",
            "enum": [
              "social_ingest",
              "caption_extract",
              "lore_refresh",
              "source_search",
              "latest_refresh",
              "source_extract",
              "question_research"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "done",
              "failed"
            ]
          },
          "cursor": {
            "type": "integer",
            "minimum": 0
          },
          "total": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "errorCategory": {
            "type": [
              "string",
              "null"
            ]
          },
          "extractionOutcomes": {
            "type": "array",
            "maxItems": 20,
            "description": "Present for source_extract. Attempt results; completion does not imply readable or editorially verified evidence.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "sourceId": {
                  "type": "string",
                  "format": "uuid"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "ready",
                    "blocked",
                    "empty",
                    "unsupported",
                    "unavailable",
                    "too_large",
                    "skipped"
                  ]
                },
                "capturedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "httpStatus": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 100,
                  "maximum": 599
                },
                "storedChars": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 50000
                },
                "truncated": {
                  "type": "boolean"
                }
              },
              "required": [
                "sourceId",
                "status",
                "capturedAt",
                "httpStatus",
                "storedChars",
                "truncated"
              ]
            }
          }
        },
        "required": [
          "jobId",
          "kind",
          "status",
          "cursor",
          "total",
          "updatedAt",
          "errorCategory"
        ],
        "description": "Sanitized progress only. Do not return raw state, last_error, run/dataset credentials, provider payloads or SQL. A job being done does not establish evidence completeness."
      },
      "Coverage": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "eligibleSources": {
            "type": "integer",
            "minimum": 0
          },
          "readableSources": {
            "type": "integer",
            "minimum": 0
          },
          "searchedSources": {
            "type": "integer",
            "minimum": 0
          },
          "complete": {
            "type": "boolean"
          },
          "limitations": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "eligibleSources",
          "readableSources",
          "searchedSources",
          "complete",
          "limitations"
        ],
        "description": "Coverage of stored eligible records, not a claim that all external material or PDF pages were extracted. For non-search reads, searchedSources is zero. Legacy extraction limits must be explicit."
      },
      "Budget": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "returnedChars": {
            "type": "integer",
            "minimum": 0
          },
          "truncated": {
            "type": "boolean"
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "returnedChars",
          "truncated",
          "nextCursor"
        ]
      }
    },
    "securitySchemes": {
      "privyBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Access token",
        "description": "Existing authenticated Music Nerd user, approved artist claimant or admin. Credentials remain outside model arguments."
      }
    }
  }
}
```
