{"components":{"schemas":{"CatalogCheckout":{"additionalProperties":false,"properties":{"actor_id":{"type":"string"},"definitions_etag":{"type":"string"},"entities":{"items":{"$ref":"#/components/schemas/Entity"},"type":"array"},"relations":{"items":{"$ref":"#/components/schemas/Relation"},"type":"array"}},"type":"object"},"CatalogCommit":{"additionalProperties":false,"properties":{"definitions_etag":{"type":"string"},"edit_note":{"type":"string"},"id":{"format":"uuid","type":"string"},"operations":{"items":{"$ref":"#/components/schemas/CommitOperation"},"maxItems":100,"minItems":1,"type":"array"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"required":["id","definitions_etag","edit_note","sources","operations"],"type":"object"},"CheckoutRequest":{"additionalProperties":false,"properties":{"entity_ids":{"items":{"type":"string"},"type":"array"},"relation_ids":{"items":{"type":"string"},"type":"array"}},"type":"object"},"CommitConflict":{"additionalProperties":false,"properties":{"base_version":{"type":"integer"},"current_version":{"type":"integer"},"id":{"type":"string"},"operation":{"type":"integer"},"paths":{"items":{"type":"string"},"type":"array"}},"type":"object"},"CommitItem":{"additionalProperties":false,"properties":{"changed":{"type":"boolean"},"id":{"type":"string"},"merged":{"type":"boolean"},"target":{"type":"string"},"version":{"type":"integer"}},"type":"object"},"CommitOperation":{"additionalProperties":false,"oneOf":[{"properties":{"action":{"const":"create"},"target":{"const":"entity"}},"required":["ref","document","reviewed_candidate_ids"]},{"properties":{"action":{"const":"create"},"target":{"const":"relation"}},"required":["ref","document"]},{"properties":{"action":{"const":"update"}},"required":["id","base_version","patch"]}],"properties":{"action":{"enum":["create","update"],"type":"string"},"base_version":{"type":"integer"},"document":{"additionalProperties":true,"type":"object"},"id":{"type":"string"},"patch":{"items":{"$ref":"#/components/schemas/CommitPatch"},"maxItems":200,"minItems":1,"type":"array"},"ref":{"type":"string"},"reviewed_candidate_ids":{"items":{"type":"string"},"maxItems":1000,"type":"array"},"target":{"enum":["entity","relation"],"type":"string"}},"required":["target","action"],"type":"object"},"CommitPatch":{"additionalProperties":false,"oneOf":[{"properties":{"remove":{"const":false}},"required":["value"]},{"not":{"required":["value"]},"properties":{"remove":{"const":true}},"required":["remove"]}],"properties":{"path":{"type":"string"},"remove":{"type":"boolean"},"value":{}},"required":["path"],"type":"object"},"CommitReceipt":{"additionalProperties":false,"properties":{"applied":{"type":"boolean"},"id":{"type":"string"},"items":{"items":{"$ref":"#/components/schemas/CommitItem"},"type":"array"},"refs":{"additionalProperties":{"type":"string"},"type":"object"}},"type":"object"},"CompositionItem":{"additionalProperties":false,"properties":{"entity":{"$ref":"#/components/schemas/Entity"},"relation":{"$ref":"#/components/schemas/Relation"}},"type":"object"},"ContributionDiffEntry":{"additionalProperties":false,"properties":{"new":{},"old":{}},"type":"object"},"ContributionItem":{"additionalProperties":false,"properties":{"created_at":{"format":"date-time","type":"string"},"diff":{"additionalProperties":{"$ref":"#/components/schemas/ContributionDiffEntry"},"type":"object"},"edit_note":{"type":"string"},"edit_type":{"type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"},"status":{"type":"string"},"tab":{"type":"string"},"target_id":{"type":"string"},"title":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"version":{"type":"integer"}},"type":"object"},"DanglingReference":{"additionalProperties":false,"properties":{"field":{"type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"reason":{"type":"string"},"relation_type":{"type":"string"},"scope":{"type":"string"},"value":{"type":"string"}},"type":"object"},"DefinitionConfig":{"additionalProperties":false,"properties":{"document":{"$ref":"#/components/schemas/Definitions"},"etag":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"DefinitionImpact":{"additionalProperties":false,"properties":{"dangling_references":{"items":{"$ref":"#/components/schemas/DanglingReference"},"type":"array"},"issues":{"items":{"type":"string"},"type":"array"}},"type":"object"},"DefinitionImpactRequest":{"properties":{"document":{"$ref":"#/components/schemas/Definitions"}},"required":["document"],"type":"object"},"DefinitionSave":{"properties":{"document":{"$ref":"#/components/schemas/Definitions"},"edit_note":{"type":"string"},"expected_etag":{"type":"string"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"required":["document","expected_etag","edit_note","sources"],"type":"object"},"Definitions":{"additionalProperties":false,"properties":{"fields":{"additionalProperties":{"$ref":"#/components/schemas/Field"},"type":"object"},"relations":{"additionalProperties":{"$ref":"#/components/schemas/RelationDefinition"},"type":"object"},"schemes":{"additionalProperties":{"$ref":"#/components/schemas/Scheme"},"type":"object"},"structure":{"additionalProperties":{"$ref":"#/components/schemas/StructureRule"},"type":"object"},"templates":{"additionalProperties":{"$ref":"#/components/schemas/Template"},"type":"object"},"vocabularies":{"additionalProperties":{"$ref":"#/components/schemas/Vocabulary"},"type":"object"}},"type":"object"},"Edit":{"additionalProperties":false,"properties":{"edit_note":{"type":"string"},"entity":{"$ref":"#/components/schemas/Entity"},"expected_version":{"type":"integer"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"type":"object"},"Entity":{"additionalProperties":false,"properties":{"attributes":{"additionalProperties":{},"type":"object"},"content_unit_id":{"type":"string"},"contents":{"items":{"$ref":"#/components/schemas/Inclusion"},"type":"array"},"created_by":{"type":"string"},"external_ids":{"additionalProperties":{"type":"string"},"type":"object"},"id":{"type":"string"},"kind":{"type":"string"},"medium_id":{"type":"string"},"number":{"type":"string"},"original_language":{"type":"string"},"parent_id":{"type":"string"},"pictures":{"items":{"$ref":"#/components/schemas/Picture"},"type":"array"},"position":{"type":"integer"},"redirect_id":{"type":"string"},"release_id":{"type":"string"},"status":{"type":"string"},"subjects":{"items":{"$ref":"#/components/schemas/Subject"},"type":"array"},"title":{"type":"string"},"translations":{"additionalProperties":{"$ref":"#/components/schemas/Translation"},"type":"object"},"updated_at":{"format":"date-time","type":"string"},"version":{"type":"integer"},"work_id":{"type":"string"}},"type":"object"},"EntityLink":{"additionalProperties":false,"properties":{"attributes":{"additionalProperties":{},"type":"object"},"class":{"type":"string"},"direction":{"type":"string"},"field":{"type":"string"},"key":{"type":"string"},"locator":{"additionalProperties":{},"type":"object"},"position":{"type":"integer"},"references":{"items":{"$ref":"#/components/schemas/RelationshipReference"},"type":"array"},"role":{"type":"string"},"rule_code":{"type":"string"},"source_id":{"type":"string"},"target_id":{"type":"string"},"via":{"items":{"type":"string"},"type":"array"}},"type":"object"},"EntityLinksPage":{"additionalProperties":false,"properties":{"definition_etag":{"type":"string"},"entities":{"additionalProperties":{"$ref":"#/components/schemas/Entity"},"type":"object"},"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/EntityLink"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"},"subject_id":{"type":"string"}},"type":"object"},"EntitySearchPage":{"additionalProperties":false,"properties":{"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/Entity"},"type":"array"},"next_cursor":{"type":"string"},"total":{"type":"integer"},"total_relation":{"type":"string"}},"type":"object"},"EntityStatusCounts":{"additionalProperties":false,"properties":{"statuses":{"additionalProperties":false,"description":"Every status of the catalog.entities.status constraint, zero-filled: a missing key is not the same statement as a real zero","properties":{"deleted":{"minimum":0,"type":"integer"},"draft":{"minimum":0,"type":"integer"},"merged":{"minimum":0,"type":"integer"},"pending_review":{"minimum":0,"type":"integer"},"published":{"minimum":0,"type":"integer"}},"type":"object"},"total":{"minimum":0,"type":"integer"}},"type":"object"},"ExpressionComposition":{"additionalProperties":false,"properties":{"definition_etag":{"type":"string"},"expression":{"$ref":"#/components/schemas/Entity"},"parts":{"items":{"$ref":"#/components/schemas/CompositionItem"},"type":"array"},"wholes":{"items":{"$ref":"#/components/schemas/CompositionItem"},"type":"array"}},"type":"object"},"ExternalDatabase":{"additionalProperties":false,"properties":{"category":{"type":"string"},"code":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"icon_url":{"type":"string"},"is_enabled":{"type":"boolean"},"is_system":{"type":"boolean"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"sort_order":{"type":"integer"},"url_pattern":{"type":"string"},"validation_regex":{"type":"string"}},"type":"object"},"Field":{"additionalProperties":false,"properties":{"anchor_key":{"type":"string"},"applicable_kinds":{"items":{"type":"string"},"type":"array"},"comparable":{"type":"boolean"},"enabled":{"type":"boolean"},"fields":{"additionalProperties":{"$ref":"#/components/schemas/Field"},"type":"object"},"hidden":{"type":"boolean"},"items":{"$ref":"#/components/schemas/Field"},"kinds":{"items":{"type":"string"},"type":"array"},"max":{"type":"number"},"min":{"type":"number"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"range_start":{"type":"string"},"required":{"type":"boolean"},"searchable":{"type":"boolean"},"semantics":{"type":"string"},"type":{"type":"string"},"unit":{"additionalProperties":{"type":"string"},"type":"object"},"vocabulary":{"type":"string"}},"type":"object"},"HomePreferences":{"additionalProperties":false,"properties":{"hidden":{"items":{"type":"string"},"type":"array"},"order":{"items":{"type":"string"},"type":"array"},"sections":{"items":{"$ref":"#/components/schemas/HomeSection"},"type":"array"}},"type":"object"},"HomeSection":{"additionalProperties":false,"properties":{"icon":{"type":"string"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"query":{"$ref":"#/components/schemas/ShelfQuery"},"slug":{"type":"string"},"sort":{"type":"string"}},"type":"object"},"IdentityAttributeCriterion":{"additionalProperties":false,"properties":{"key":{"type":"string"},"value":{"type":"string"}},"type":"object"},"IdentityCandidateEntity":{"additionalProperties":false,"properties":{"attributes":{"additionalProperties":{},"type":"object"},"content_unit_id":{"type":"string"},"external_ids":{"additionalProperties":{"type":"string"},"type":"object"},"id":{"type":"string"},"kind":{"type":"string"},"medium_id":{"type":"string"},"parent_id":{"type":"string"},"release_id":{"type":"string"},"status":{"type":"string"},"title":{"type":"string"},"translations":{"additionalProperties":{"$ref":"#/components/schemas/Translation"},"type":"object"},"version":{"type":"integer"},"work_id":{"type":"string"}},"type":"object"},"IdentityCandidateMatch":{"additionalProperties":false,"properties":{"canonical":{"$ref":"#/components/schemas/IdentityCandidateEntity"},"matched":{"$ref":"#/components/schemas/IdentityCandidateEntity"},"resolution_error":{"type":"string"}},"type":"object"},"IdentityCandidateQuery":{"additionalProperties":false,"properties":{"attributes":{"items":{"$ref":"#/components/schemas/IdentityAttributeCriterion"},"type":"array"},"external_ids":{"items":{"$ref":"#/components/schemas/IdentityExternalCriterion"},"type":"array"},"kind":{"enum":["agent","collection","work","content_unit","expression","release","medium","track"],"type":"string"},"limit":{"default":1000,"maximum":1000,"minimum":1,"type":"integer"},"medium_id":{"type":"string"},"release_id":{"type":"string"},"titles":{"items":{"type":"string"},"type":"array"},"work_id":{"type":"string"}},"required":["kind"],"type":"object"},"IdentityCandidateResponse":{"additionalProperties":false,"properties":{"basis":{"type":"string"},"complete":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/IdentityCandidateMatch"},"type":"array"},"total":{"type":"integer"}},"type":"object"},"IdentityExternalCriterion":{"additionalProperties":false,"properties":{"provider":{"type":"string"},"value":{"type":"string"}},"type":"object"},"ImporterArtistPreview":{"additionalProperties":false,"properties":{"aliases":{"items":{"type":"string"},"type":"array"},"avatar_url":{"type":"string"},"biography":{"type":"string"},"character_name":{"type":"string"},"country":{"type":"string"},"disambiguation":{"type":"string"},"entity_type":{"type":"string"},"external_ids":{"additionalProperties":{},"type":"object"},"id":{"type":"string"},"language":{"type":"string"},"matched_artist":{},"name":{"type":"string"},"original_name":{"type":"string"},"relation_role":{"type":"string"},"relation_type":{"type":"string"},"role":{"type":"string"},"translations":{"items":{"$ref":"#/components/schemas/ImporterTranslationItem"},"type":"array"}},"type":"object"},"ImporterCanonicalEntryPreview":{"additionalProperties":false,"properties":{"attributes":{"additionalProperties":{},"type":"object"},"duration_seconds":{"type":"number"},"entry_kind":{"type":"string"},"entry_role":{"type":"string"},"expression_id":{"type":"string"},"external_ids":{"additionalProperties":{},"type":"object"},"number":{"type":"string"},"original_language":{"type":"string"},"parent_index":{"type":"integer"},"position":{"type":"integer"},"title":{"type":"string"},"translations":{}},"type":"object"},"ImporterImportRequest":{"additionalProperties":false,"properties":{"artist":{"$ref":"#/components/schemas/ImporterArtistPreview"},"artists":{"items":{"$ref":"#/components/schemas/ImporterArtistPreview"},"type":"array"},"canonical_entries":{"items":{"$ref":"#/components/schemas/ImporterCanonicalEntryPreview"},"type":"array"},"download_cover":{"type":"boolean"},"edit_note":{"type":"string"},"entity_type":{"type":"string"},"external_id":{"type":"string"},"has_release":{"type":"boolean"},"link_mode":{"type":"string"},"media_type_hint":{"type":"string"},"mediums":{"items":{"$ref":"#/components/schemas/ImporterMediumPreview"},"type":"array"},"relation_type":{"type":"string"},"release":{"$ref":"#/components/schemas/ImporterReleasePreview"},"source":{"type":"string"},"source_urls":{"items":{"type":"string"},"type":"array"},"staff_associations":{"items":{"$ref":"#/components/schemas/ImporterStaffAssociation"},"type":"array"},"target_work_id":{"type":"string"},"url_or_id":{"type":"string"},"work":{"$ref":"#/components/schemas/ImporterWorkPreview"}},"type":"object"},"ImporterImportResponse":{"additionalProperties":false,"properties":{"artist":{"$ref":"#/components/schemas/Entity"},"artist_id":{"type":"string"},"entity_type":{"type":"string"},"imported_counts":{"$ref":"#/components/schemas/ImporterImportedCounts"},"redirect_url":{"type":"string"},"release":{"$ref":"#/components/schemas/Entity"},"release_id":{"type":"string"},"success":{"type":"boolean"},"work":{"$ref":"#/components/schemas/Entity"},"work_id":{"type":"string"}},"type":"object"},"ImporterImportedCounts":{"additionalProperties":false,"properties":{"artists":{"type":"integer"},"content_units":{"type":"integer"},"mediums":{"type":"integer"},"relations":{"type":"integer"},"skipped_relations":{"type":"integer"},"tracks":{"type":"integer"}},"type":"object"},"ImporterMediumPreview":{"additionalProperties":false,"properties":{"format":{"type":"string"},"name":{"type":"string"},"number":{"type":"string"},"original_language":{"type":"string"},"position":{"type":"integer"},"role":{"type":"string"},"tracks":{"items":{"$ref":"#/components/schemas/ImporterTrackPreview"},"type":"array"},"translations":{}},"type":"object"},"ImporterPreviewRequest":{"additionalProperties":false,"properties":{"entity_type":{"type":"string"},"source":{"type":"string"},"url_or_id":{"type":"string"}},"type":"object"},"ImporterPreviewResponse":{"additionalProperties":false,"properties":{"artist":{"$ref":"#/components/schemas/ImporterArtistPreview"},"artists":{"items":{"$ref":"#/components/schemas/ImporterArtistPreview"},"type":"array"},"canonical_entries":{"items":{"$ref":"#/components/schemas/ImporterCanonicalEntryPreview"},"type":"array"},"entity_type":{"type":"string"},"external_id":{"type":"string"},"external_url":{"type":"string"},"has_release":{"type":"boolean"},"media_type":{"type":"string"},"mediums":{"items":{"$ref":"#/components/schemas/ImporterMediumPreview"},"type":"array"},"release":{"$ref":"#/components/schemas/ImporterReleasePreview"},"source":{"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"warnings":{"items":{"type":"string"},"type":"array"},"work":{"$ref":"#/components/schemas/ImporterWorkPreview"}},"type":"object"},"ImporterReleasePreview":{"additionalProperties":false,"properties":{"barcode":{"type":"string"},"catalog_metadata":{},"catalog_number":{"type":"string"},"country":{"type":"string"},"cover_aspect":{"type":"string"},"cover_image_url":{"type":"string"},"distribution_channel":{"type":"string"},"edition_batch":{"type":"string"},"edition_date":{"type":"string"},"edition_name":{"type":"string"},"edition_type":{"type":"string"},"language":{"type":"string"},"notes":{"type":"string"},"original_language":{"type":"string"},"packaging":{"type":"string"},"publisher":{"type":"string"},"translations":{}},"type":"object"},"ImporterSource":{"additionalProperties":false,"properties":{"category":{"type":"string"},"description":{"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"url_pattern":{"type":"string"}},"type":"object"},"ImporterSourceList":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/ImporterSource"},"type":"array"}},"type":"object"},"ImporterStaffAssociation":{"additionalProperties":false,"properties":{"action":{"type":"string"},"avatar_url":{"type":"string"},"biography":{"type":"string"},"character_name":{"type":"string"},"country":{"type":"string"},"entity_type":{"type":"string"},"external_ids":{"additionalProperties":{},"type":"object"},"language":{"type":"string"},"parsed_name":{"type":"string"},"parsed_original":{"type":"string"},"parsed_role":{"type":"string"},"relation_role":{"type":"string"},"relation_type":{"type":"string"},"target_artist_id":{"type":"string"},"translations":{"items":{"$ref":"#/components/schemas/ImporterTranslationItem"},"type":"array"}},"type":"object"},"ImporterTrackPreview":{"additionalProperties":false,"properties":{"artist_credit":{"type":"string"},"duration_seconds":{"type":"number"},"entry_index":{"type":"integer"},"expression_id":{"type":"string"},"isrc":{"type":"string"},"position":{"type":"integer"},"recording_mbid":{"type":"string"},"title":{"type":"string"}},"type":"object"},"ImporterTranslationItem":{"additionalProperties":false,"properties":{"aliases":{"items":{"type":"string"},"type":"array"},"locale":{"type":"string"},"summary":{"type":"string"},"title":{"type":"string"}},"type":"object"},"ImporterWorkPreview":{"additionalProperties":false,"properties":{"aliases":{"items":{"type":"string"},"type":"array"},"begin_date":{"type":"string"},"catalog_metadata":{},"content_rating":{"type":"string"},"country":{"type":"string"},"cover_aspect":{"type":"string"},"cover_image_url":{"type":"string"},"fields":{"additionalProperties":{},"type":"object"},"infobox":{"items":{"additionalProperties":{},"type":"object"},"type":"array"},"language":{"type":"string"},"original_language":{"type":"string"},"original_title":{"type":"string"},"release_date":{"type":"string"},"summary":{"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"title":{"type":"string"},"translations":{"items":{"$ref":"#/components/schemas/ImporterTranslationItem"},"type":"array"}},"type":"object"},"Inclusion":{"additionalProperties":false,"properties":{"attributes":{"additionalProperties":{},"type":"object"},"expression_id":{"type":"string"},"locator":{"additionalProperties":{},"type":"object"},"position":{"type":"integer"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"type":"object"},"KindRecord":{"additionalProperties":false,"properties":{"names":{"additionalProperties":{"type":"string"},"type":"object"}},"type":"object"},"LifecycleEdit":{"additionalProperties":false,"properties":{"edit_note":{"type":"string"},"expected_version":{"type":"integer"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"},"target_id":{"type":"string"}},"type":"object"},"Notification":{"additionalProperties":false,"properties":{"actor_id":{"type":"string"},"actor_name":{"type":"string"},"count":{"type":"integer"},"created_at":{"format":"date-time","type":"string"},"id":{"type":"string"},"payload":{"additionalProperties":{},"type":"object"},"read":{"type":"boolean"},"subject_id":{"type":"string"},"subject_type":{"type":"string"},"type":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"NotificationDelivery":{"additionalProperties":false,"properties":{"dedupe_key":{"description":"Aggregation key (at most 300 chars); defaults to type:subject_id. Events sharing (recipient_id, dedupe_key) merge into one row: count increments, read_at resets to unread and updated_at is bumped","type":"string"},"event_id":{"description":"Stable identity of this event (at most 200 chars), so that an upstream retry is idempotent: delivering the same event_id again on the same (recipient_id, dedupe_key) leaves count, read_at and updated_at untouched. Omitted means a new event every call","type":"string"},"payload":{"additionalProperties":true,"description":"Per-type display payload; unknown keys are stored as-is and returned to the recipient","type":"object"},"recipient_id":{"description":"Recipient user id (UUID) as resolved by the calling service","type":"string"},"subject_id":{"description":"Clickable target id (at most 200 chars)","type":"string"},"subject_type":{"description":"topic | entity | import (free-form, at most 64 chars)","type":"string"},"type":{"description":"Notification type code; an unknown code is 400 invalid_notification_type","enum":["comment.replied","entity.included","entity.review_approved","entity.review_rejected","import.completed"],"type":"string"}},"required":["recipient_id","type"],"type":"object"},"NotificationList":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/Notification"},"type":"array"},"total":{"type":"integer"},"unread":{"type":"integer"}},"type":"object"},"NotificationReadResult":{"additionalProperties":false,"properties":{"ok":{"type":"boolean"},"unread":{"type":"integer"},"updated":{"type":"integer"}},"type":"object"},"NotificationUnread":{"additionalProperties":false,"properties":{"unread":{"type":"integer"}},"type":"object"},"Picture":{"additionalProperties":false,"properties":{"asset_id":{"type":"string"},"caption":{"additionalProperties":{"type":"string"},"type":"object"},"role":{"type":"string"},"source":{"$ref":"#/components/schemas/Source"},"taken_at":{"type":"string"},"url":{"type":"string"},"usage_period":{"$ref":"#/components/schemas/TimeSpan"},"version_label":{"additionalProperties":{"type":"string"},"type":"object"}},"type":"object"},"PublishedDefinitions":{"additionalProperties":false,"properties":{"document":{"$ref":"#/components/schemas/Definitions"},"etag":{"type":"string"},"kinds":{"additionalProperties":{"$ref":"#/components/schemas/KindRecord"},"type":"object"},"relationship_rules":{"items":{"$ref":"#/components/schemas/RelationshipRule"},"type":"array"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"RateLimitConfig":{"additionalProperties":false,"properties":{"etag":{"type":"string"},"policy":{"$ref":"#/components/schemas/RateLimitPolicy"},"updated_at":{"format":"date-time","type":"string"}},"type":"object"},"RateLimitPolicy":{"additionalProperties":false,"properties":{"accounts":{"additionalProperties":{"$ref":"#/components/schemas/RateLimitRule"},"type":"object"},"default_per_minute":{"type":"integer"},"default_unlimited":{"type":"boolean"},"groups":{"additionalProperties":{"$ref":"#/components/schemas/RateLimitRule"},"type":"object"}},"type":"object"},"RateLimitRule":{"additionalProperties":false,"properties":{"per_minute":{"type":"integer"},"unlimited":{"type":"boolean"}},"type":"object"},"RateLimitSave":{"additionalProperties":false,"properties":{"edit_note":{"type":"string"},"expected_etag":{"type":"string"},"policy":{"$ref":"#/components/schemas/RateLimitPolicy"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"type":"object"},"Relation":{"additionalProperties":false,"properties":{"attributes":{"additionalProperties":{},"type":"object"},"id":{"type":"string"},"position":{"type":"integer"},"source_id":{"type":"string"},"target_id":{"type":"string"},"type":{"type":"string"},"version":{"type":"integer"},"via":{"type":"string"}},"type":"object"},"RelationDefinition":{"additionalProperties":false,"properties":{"acyclic":{"type":"boolean"},"aggregate":{"type":"boolean"},"counts_as_credit":{"type":"boolean"},"cycle_group":{"type":"string"},"enabled":{"type":"boolean"},"fields":{"items":{"type":"string"},"type":"array"},"group":{"type":"string"},"group_names":{"additionalProperties":{"type":"string"},"type":"object"},"max_incoming":{"type":"integer"},"max_outgoing":{"type":"integer"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"participant_slot":{"type":"string"},"reference_scopes":{"additionalProperties":{"type":"string"},"type":"object"},"reverse_names":{"additionalProperties":{"type":"string"},"type":"object"},"scope":{"type":"string"},"source_kinds":{"items":{"type":"string"},"type":"array"},"symmetric":{"type":"boolean"},"target_kinds":{"items":{"type":"string"},"type":"array"},"unique_position":{"type":"boolean"},"usage":{"type":"string"}},"type":"object"},"RelationEdit":{"additionalProperties":false,"properties":{"edit_note":{"type":"string"},"expected_version":{"type":"integer"},"relation":{"$ref":"#/components/schemas/Relation"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"type":"object"},"RelationshipEntity":{"additionalProperties":false,"properties":{"id":{"type":"string"},"kind":{"type":"string"},"original_language":{"type":"string"},"title":{"type":"string"},"translations":{"additionalProperties":{"$ref":"#/components/schemas/Translation"},"type":"object"},"version":{"type":"integer"}},"type":"object"},"RelationshipQueryPage":{"additionalProperties":false,"properties":{"has_more":{"type":"boolean"},"items":{"items":{"$ref":"#/components/schemas/EntityLink"},"type":"array"},"limit":{"type":"integer"},"offset":{"type":"integer"},"subject_id":{"type":"string"}},"required":["subject_id","items","limit","offset","has_more"],"type":"object"},"RelationshipQueryRequest":{"additionalProperties":false,"properties":{"direction":{"default":"both","enum":["both","outgoing","incoming"],"type":"string"},"ids":{"description":"Canonicalized and deduplicated in request order","items":{"format":"uuid","type":"string"},"maxItems":20,"minItems":1,"type":"array"},"limit":{"default":25,"maximum":100,"minimum":1,"type":"integer"},"offset":{"default":0,"minimum":0,"type":"integer"},"peer_kinds":{"description":"Other endpoint kinds; empty means any kind","items":{"enum":["agent","collection","work","content_unit","expression","release","medium","track"],"type":"string"},"type":"array"},"rule_codes":{"description":"Codes from the live relationship registry; empty means any rule","items":{"type":"string"},"type":"array"}},"required":["ids"],"type":"object"},"RelationshipQueryResponse":{"additionalProperties":false,"properties":{"definition_etag":{"type":"string"},"entities":{"additionalProperties":{"$ref":"#/components/schemas/RelationshipEntity"},"type":"object"},"pages":{"items":{"$ref":"#/components/schemas/RelationshipQueryPage"},"type":"array"},"unavailable_ids":{"items":{"type":"string"},"type":"array"}},"required":["definition_etag","pages","entities","unavailable_ids"],"type":"object"},"RelationshipReference":{"additionalProperties":false,"properties":{"entity_id":{"type":"string"},"field":{"type":"string"}},"type":"object"},"RelationshipRule":{"additionalProperties":false,"properties":{"class":{"type":"string"},"code":{"type":"string"},"enabled":{"type":"boolean"},"max_incoming":{"type":"integer"},"max_outgoing":{"type":"integer"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"ordered":{"type":"boolean"},"read_only":{"type":"boolean"},"reverse_names":{"additionalProperties":{"type":"string"},"type":"object"},"scope":{"type":"string"},"source_kinds":{"items":{"type":"string"},"type":"array"},"target_kinds":{"items":{"type":"string"},"type":"array"}},"type":"object"},"ReleaseEditions":{"additionalProperties":false,"properties":{"definition_etag":{"type":"string"},"editions":{"items":{"$ref":"#/components/schemas/Entity"},"type":"array"},"group":{"$ref":"#/components/schemas/Entity"},"release":{"$ref":"#/components/schemas/Entity"}},"type":"object"},"ReleaseTOC":{"additionalProperties":false,"properties":{"definition_etag":{"type":"string"},"expressions":{"additionalProperties":{"$ref":"#/components/schemas/Entity"},"type":"object"},"media":{"items":{"$ref":"#/components/schemas/ReleaseTOCMedium"},"type":"array"},"release":{"$ref":"#/components/schemas/Entity"}},"type":"object"},"ReleaseTOCMedium":{"additionalProperties":false,"properties":{"medium":{"$ref":"#/components/schemas/Entity"},"tracks":{"items":{"$ref":"#/components/schemas/Entity"},"type":"array"}},"type":"object"},"Result":{"additionalProperties":true,"type":"object"},"Scheme":{"additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"fields":{"items":{"type":"string"},"type":"array"},"kinds":{"items":{"type":"string"},"type":"array"},"medium_formats":{"items":{"type":"string"},"type":"array"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"require_range":{"type":"boolean"},"required":{"items":{"type":"string"},"type":"array"},"slot":{"type":"string"}},"type":"object"},"Section":{"additionalProperties":false,"properties":{"fields":{"items":{"type":"string"},"type":"array"},"names":{"additionalProperties":{"type":"string"},"type":"object"}},"type":"object"},"Shelf":{"additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"icon":{"type":"string"},"id":{"type":"integer"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"query":{"$ref":"#/components/schemas/ShelfQuery"},"slug":{"type":"string"},"sort":{"type":"string"},"sort_order":{"type":"integer"},"source":{"type":"string"}},"type":"object"},"ShelfQuery":{"additionalProperties":false,"properties":{"fields":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object"},"relations":{"items":{"type":"string"},"type":"array"},"tags":{"items":{"type":"string"},"type":"array"},"vocab_terms":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object"}},"type":"object"},"Source":{"additionalProperties":false,"properties":{"citation":{"type":"string"},"kind":{"type":"string"},"url":{"type":"string"}},"type":"object"},"StructureField":{"additionalProperties":false,"properties":{"code":{"type":"string"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"required":{"type":"boolean"},"reverse_names":{"additionalProperties":{"type":"string"},"type":"object"},"scoped_by":{"type":"string"},"target_kinds":{"items":{"type":"string"},"type":"array"}},"type":"object"},"StructureRule":{"additionalProperties":false,"properties":{"content_names":{"additionalProperties":{"type":"string"},"type":"object"},"content_reverse_names":{"additionalProperties":{"type":"string"},"type":"object"},"contents":{"type":"boolean"},"fields":{"items":{"$ref":"#/components/schemas/StructureField"},"type":"array"},"resources":{"type":"boolean"},"subject_names":{"additionalProperties":{"type":"string"},"type":"object"},"subject_reverse_names":{"additionalProperties":{"type":"string"},"type":"object"},"subjects":{"type":"boolean"}},"type":"object"},"Subject":{"additionalProperties":false,"properties":{"attributes":{"additionalProperties":{},"type":"object"},"position":{"type":"integer"},"role":{"type":"string"},"work_id":{"type":"string"}},"type":"object"},"Template":{"additionalProperties":false,"properties":{"badge_fields":{"items":{"type":"string"},"type":"array"},"blocks":{"items":{"type":"string"},"type":"array"},"columns":{"items":{"type":"string"},"type":"array"},"directory":{"type":"string"},"facet_fields":{"items":{"type":"string"},"type":"array"},"kinds":{"items":{"type":"string"},"type":"array"},"match":{"items":{"$ref":"#/components/schemas/TemplateCondition"},"type":"array"},"names":{"additionalProperties":{"type":"string"},"type":"object"},"primary_date_field":{"type":"string"},"priority":{"type":"integer"},"relation_groups":{"items":{"type":"string"},"type":"array"},"sections":{"items":{"$ref":"#/components/schemas/Section"},"type":"array"}},"type":"object"},"TemplateCondition":{"additionalProperties":false,"properties":{"field":{"type":"string"},"operator":{"type":"string"},"value":{}},"type":"object"},"Term":{"additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"is_bonus":{"type":"boolean"},"names":{"additionalProperties":{"type":"string"},"type":"object"}},"type":"object"},"TimeSpan":{"additionalProperties":false,"properties":{"begin":{"type":"string"},"end":{"type":"string"}},"type":"object"},"TrackContentEdit":{"additionalProperties":false,"properties":{"edit_note":{"type":"string"},"expected_version":{"type":"integer"},"inclusion":{"$ref":"#/components/schemas/Inclusion"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"type":"object"},"TrackStatusEdit":{"additionalProperties":false,"properties":{"edit_note":{"minLength":1,"type":"string"},"expected_version":{"minimum":1,"type":"integer"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"minItems":1,"type":"array"},"status":{"enum":["draft","pending_review","published"],"type":"string"}},"required":["status","expected_version","edit_note","sources"],"type":"object"},"Translation":{"additionalProperties":false,"properties":{"aliases":{"items":{"type":"string"},"type":"array"},"summary":{"type":"string"},"title":{"type":"string"}},"type":"object"},"UnpublishEdit":{"additionalProperties":false,"properties":{"edit_note":{"type":"string"},"expected_version":{"type":"integer"},"sources":{"items":{"$ref":"#/components/schemas/Source"},"type":"array"}},"type":"object"},"UserContributionStats":{"additionalProperties":false,"properties":{"artists_created":{"type":"integer"},"audit_actions":{"type":"integer"},"releases_created":{"type":"integer"},"revisions_count":{"type":"integer"},"works_created":{"type":"integer"}},"type":"object"},"UserContributions":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/ContributionItem"},"type":"array"},"page":{"type":"integer"},"page_size":{"type":"integer"},"stats":{"$ref":"#/components/schemas/UserContributionStats"},"total":{"type":"integer"}},"type":"object"},"VersionInfo":{"additionalProperties":false,"properties":{"build_time":{"type":"string"},"git_sha":{"type":"string"},"service":{"type":"string"},"started_at":{"type":"string"},"version":{"type":"string"}},"type":"object"},"Vocabulary":{"additionalProperties":false,"properties":{"names":{"additionalProperties":{"type":"string"},"type":"object"},"terms":{"additionalProperties":{"$ref":"#/components/schemas/Term"},"type":"object"}},"type":"object"}},"securitySchemes":{"bearer":{"scheme":"bearer","type":"http"},"session":{"in":"cookie","name":"mf_session","type":"apiKey"}}},"info":{"description":"MetaFusion 元数据目录服务 API：固定实体骨架（Work / Expression / Release / Medium / Track / ContentUnit / Agent / Collection）、动态类型与属性扩展、多版本发行对比、外部库导入与实例间导入导出。账号（/auth、/oauth、/oidc）与收藏（/favorites）已由独立子系统提供，不在本服务。","title":"MetaFusion API","version":"1.0.0"},"openapi":"3.0.3","paths":{"/admin/catalog-definitions":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefinitionConfig"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Read the single live definition configuration (requires catalog.definitions.manage)","tags":["Definitions"]},"put":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefinitionSave"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefinitionConfig"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Replace the live definition document after impact validation; expected_etag prevents stale edits (requires catalog.definitions.manage)","tags":["Definitions"]}},"/admin/catalog-definitions/impact":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefinitionImpactRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefinitionImpact"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Replay a proposed definition document against current data without saving it (requires catalog.definitions.manage)","tags":["Definitions"]}},"/admin/external-databases":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"List external authority databases (requires catalog.definitions.manage)","tags":["ExternalDatabases"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalDatabase"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Create external authority database (requires catalog.definitions.manage); names must carry zh-CN, zh-TW, en-US and ja or ja-JP (four_locale_names_required)","tags":["ExternalDatabases"]}},"/admin/external-databases/{code}":{"delete":{"parameters":[{"in":"path","name":"code","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Delete external authority database (requires catalog.definitions.manage)","tags":["ExternalDatabases"]},"put":{"parameters":[{"in":"path","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalDatabase"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Update external authority database (requires catalog.definitions.manage); names must carry zh-CN, zh-TW, en-US and ja or ja-JP (four_locale_names_required)","tags":["ExternalDatabases"]}},"/admin/rate-limits":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitConfig"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Read the live API rate-limit policy (requires catalog.definitions.manage). One process-wide document drives every throttled route; it lives outside /catalog/definitions on purpose, so changing a quota never invalidates the metadata contract or replays it over the catalog. Budgets resolve per request in this order: accounts (matched against the token subject, then preferred_username) → groups (the most permissive match wins, since groups only grant) → default_per_minute → the route's built-in budget. The reserved group code anonymous applies to requests with no token, whose subject is the client IP. A rule with unlimited=true skips counting entirely for that subject (no X-RateLimit-* headers are sent, because there is no window to report); an empty document means 'inherit every built-in budget', which is exactly the behaviour before this endpoint existed","tags":["RateLimits"]},"put":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitSave"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitConfig"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Replace the live API rate-limit policy; expected_etag prevents stale edits (requires catalog.definitions.manage). The whole policy object is replaced, never merged: removing a group or account entry is how a previous override is withdrawn, and a partial merge would make deletion impossible to express. Errors: 409 version_conflict when expected_etag is missing or stale, 400 invalid_rate_limit for a negative or above-ceiling per_minute (over 1000000 is a typo, not generosity), a blank, whitespace-padded or over-long subject key, more than 200 group entries or 2000 account entries, and evidence_required / invalid_source for the edit_note and sources that every catalog write carries. unlimited and per_minute may both be set, and unlimited wins; the effective budgets are visible in GET /admin/rate-limits without waiting for a restart","tags":["RateLimits"]}},"/admin/shelves":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"List shelf rules (requires catalog.shelves.manage)","tags":["Catalog"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shelf"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Create shelf rule (requires catalog.shelves.manage); names must carry zh-CN, zh-TW, en-US and ja or ja-JP (four_locale_names_required); sort accepts updated (default) | created | title, other values are rejected with invalid_sort; query rejects blank codes with invalid_tags / invalid_relations and malformed field codes or blank values with invalid_fields / invalid_vocab_terms (the same shape check user homepage sections use); source is output-only and only set by /catalog/shelves/feed","tags":["Catalog"]}},"/admin/shelves/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Delete shelf rule (requires catalog.shelves.manage)","tags":["Catalog"]},"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Read shelf rule (requires catalog.shelves.manage)","tags":["Catalog"]},"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shelf"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Update shelf rule (requires catalog.shelves.manage); names must carry zh-CN, zh-TW, en-US and ja or ja-JP (four_locale_names_required); sort accepts updated (default) | created | title, other values are rejected with invalid_sort; query rejects blank codes with invalid_tags / invalid_relations and malformed field codes or blank values with invalid_fields / invalid_vocab_terms","tags":["Catalog"]}},"/catalog/checkout":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogCheckout"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Read versioned entities and relations in one repeatable-read snapshot (0..100 IDs total). Includes definitions_etag, visibility-filtered Track contents; this is a working copy, not an identity query. Authentication required","tags":["Catalog"]}},"/catalog/commits":{"post":{"description":"Structural and relation writes run concurrently under SERIALIZABLE, without a global graph lock. Only confirmed database rollbacks (40001/40P01/55P03) restart the whole transaction, up to 16 attempts within the deadline. Local release/identity/row coordination remains. Connection errors or uncertain COMMITs are never automatically replayed.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogCommit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitReceipt"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"},"503":{"content":{"application/json":{"schema":{"properties":{"applied":{"enum":[false],"type":"boolean"},"error":{"enum":["transaction_busy"],"type":"string"}},"required":["error","applied"],"type":"object"}}},"description":"transaction_busy: this request rolled back after bounded attempts; Retry-After: 1. Retain the same commit ID/payload. This response cannot resolve uncertainty about an earlier same-ID request; recover its receipt first.","headers":{"Retry-After":{"schema":{"minimum":1,"type":"integer"}}}}},"security":[{"session":[]},{"bearer":[]}],"summary":"Atomically push up to 100 ordered entity/relation create/update operations with evidence and definitions_etag. Entity creates require reviewed_candidate_ids (empty array allowed): formal/localized titles plus external IDs are rechecked within Work/Release/Medium scope under sorted identity-term locks; changed candidate sets return 409 identity_candidates_changed. @local:ref can identify a previously created candidate in this batch. This is caller-visible identity review, not global semantic uniqueness across other write APIs. Canonical UUID commit id is a durable idempotency key: same owner+payload replays receipt; changed payload returns 409 idempotency_conflict. Updates carry authoritative base_version and granular JSON Pointer set/remove patches: disjoint edits merge, identical edits are no-ops, overlapping divergent edits return 409 commit_conflict with operation/id/versions/paths and applied=false. Arrays are atomic; server-owned fields and scopes cannot be patched. Hidden Track contents require specialized content endpoints. Any validation/conflict rolls back the entire batch. Schema changes return 409 definitions_conflict. Deadlines 15s, lock waits 3s; default 60 pushes/min. A lost response is recovered with GET /catalog/commits/{id}, not a new commit id","tags":["Catalog"]}},"/catalog/commits/preview":{"post":{"description":"Structural and relation writes run concurrently under SERIALIZABLE, without a global graph lock. Only confirmed database rollbacks (40001/40P01/55P03) restart the whole transaction, up to 16 attempts within the deadline. Local release/identity/row coordination remains. Connection errors or uncertain COMMITs are never automatically replayed.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogCommit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitReceipt"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"},"503":{"content":{"application/json":{"schema":{"properties":{"applied":{"enum":[false],"type":"boolean"},"error":{"enum":["transaction_busy"],"type":"string"}},"required":["error","applied"],"type":"object"}}},"description":"transaction_busy: this request rolled back after bounded attempts; Retry-After: 1. Retain the same commit ID/payload. This response cannot resolve uncertainty about an earlier same-ID request; recover its receipt first.","headers":{"Retry-After":{"schema":{"minimum":1,"type":"integer"}}}}},"security":[{"session":[]},{"bearer":[]}],"summary":"Validate an atomic commit through the real write path, then roll back every fact, revision, notification and outbox event. Up to 100 ordered create/update operations; use explicit local references {\"$ref\":\"name\"}. Preview IDs are provisional. No durable receipt. Default 30/min","tags":["Catalog"]}},"/catalog/commits/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitReceipt"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Read durable push receipt by UUID, only for its original actor; 404 if no committed receipt or not owned. A 404 during an in-flight push is not proof of failure; retry the same immutable payload/id to reconcile","tags":["Catalog"]}},"/catalog/compare":{"get":{"parameters":[{"description":"Two to six comma-separated entity UUIDs of any kinds","in":"query","name":"ids","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Compare two to six entities of any kinds (throttled to a 10/min default budget, per account when signed in and otherwise per client IP; override per group or per account via /admin/rate-limits); releases/mediums include their containment tree","tags":["Catalog"]}},"/catalog/definitions":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishedDefinitions"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Published dynamic definitions, fixed entity-skeleton names, and a relationship registry. Structural endpoints are database-constrained; their forward and reverse display names are editable in definitions.structure","tags":["Definitions"]}},"/catalog/developer/request-logs":{"get":{"parameters":[{"description":"Filter by credential name (PAT name, exact); empty returns all","in":"query","name":"credential","required":false,"schema":{"type":"string"}},{"description":"Page size, default 50, max 100","in":"query","name":"limit","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Own API request log, newest first (authenticated calls only; route is the gin template path without entity ids or query strings; 30-day retention)","tags":["Catalog"]}},"/catalog/entities":{"get":{"parameters":[{"description":"Single entity kind filter","in":"query","name":"kind","schema":{"type":"string"}},{"description":"Multi-value kind filter (repeat or comma-separated, OR)","in":"query","name":"kinds","schema":{"type":"string"}},{"description":"Entity status filter","in":"query","name":"status","schema":{"type":"string"}},{"description":"Attribute filter: a published field code (dotted path allowed only when every level is searchable and enabled); the seed definitions make top-level codes such as tags, duration, edition_date and barcode usable","in":"query","name":"field","schema":{"type":"string"}},{"description":"Exact value compared with field (text equality via -\u003e\u003e)","in":"query","name":"value","schema":{"type":"string"}},{"description":"Expressions/content_units of the work + releases declaring it","in":"query","name":"work_id","schema":{"type":"string"}},{"description":"Expressions under the content unit","in":"query","name":"content_unit_id","schema":{"type":"string"}},{"description":"Mediums under the release","in":"query","name":"release_id","schema":{"type":"string"}},{"description":"Tracks under the medium","in":"query","name":"medium_id","schema":{"type":"string"}},{"description":"Child content_units/mediums/tracks","in":"query","name":"parent_id","schema":{"type":"string"}},{"description":"Multi-value tag filter (repeat or comma-separated, container match @\u003e); matching is controlled by tags_mode","in":"query","name":"tags","schema":{"type":"string"}},{"description":"Tag matching: any (default) includes entities with at least one selected tag; all requires every selected tag. Other values return 400 invalid_query_param. Applies to browsing and text search.","in":"query","name":"tags_mode","schema":{"type":"string"}},{"description":"Exact match on document original_language (all eight kinds share it, e.g. ja)","in":"query","name":"original_language","schema":{"type":"string"}},{"description":"Only entities with a non-empty pictures array when 1; missing key or non-array counts as no cover","in":"query","name":"has_pictures","schema":{"type":"string"}},{"description":"Sort key, whitelisted: updated_at (column, default), created_at (entity ids are time-ordered UUIDv7, so id order is creation order), title (the displayed title: requested locale -\u003e original_language -\u003e en-US -\u003e base title). An unknown key is 400 invalid_sort rather than being silently ignored","in":"query","name":"sort","schema":{"type":"string"}},{"description":"Sort direction, asc or desc; defaults to desc for the time keys and asc for title. Anything else is 400 invalid_order","in":"query","name":"order","schema":{"type":"string"}},{"description":"Locale used only by sort=title to pick which translation is compared (BCP-47-like, ignored when malformed)","in":"query","name":"locale","schema":{"type":"string"}},{"description":"Page size, default 50, max 100. A non-integer, 0, a negative value or anything above 100 is 400 invalid_limit (an empty value counts as absent) — the old behaviour silently replaced it with the default, so a caller could not tell its page size never applied","in":"query","name":"limit","schema":{"type":"string"}},{"description":"For q, offset+limit must not exceed 10000 (400 search_window_exceeded); follow next_cursor for deeper pages. Page offset, default 0; must be an integer \u003e= 0, otherwise 400 invalid_offset. Mutually exclusive with page: passing both is 400 pagination_conflict rather than letting one of them quietly win","in":"query","name":"offset","schema":{"type":"string"}},{"description":"For q, the derived offset+limit must not exceed 10000. 1-based page number, sugar for offset=(page-1)*limit (limit defaults to 50); must be an integer \u003e= 1, otherwise 400 invalid_page. A page past the end answers 200 with an empty items and the real total still filled in, so the caller can tell 'nothing left' from 'nothing found'","in":"query","name":"page","schema":{"type":"string"}},{"description":"OpenSearch search across titles, translations, aliases, summaries, tags and external IDs. Matching and pagination use an index snapshot; PostgreSQL rechecks current visibility and exact filters and supplies entity content. No PostgreSQL text-search fallback: an unavailable or unready index returns 503 search_unavailable. Query text is limited to 256 bytes and must contain valid UTF-8 with no control characters other than TAB. Response total describes the index snapshot (total_relation=index_snapshot); items can be shorter after current visibility/filter rechecks. Follow next_cursor while has_more even if items is empty.","in":"query","name":"q","schema":{"type":"string"}},{"description":"Opaque one-minute PIT search cursor, only with q. Keep the query, filters, sort, locale and limit unchanged. Mutually exclusive with offset/page. Deep pagination continues beyond 10,000 hits. Malformed or mismatched cursor: 400 invalid_search_cursor; expired PIT: 400 search_cursor_expired. Restart the search after expiry.","in":"query","name":"cursor","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitySearchPage"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Entity search (kind/kinds/q/status/work_id/content_unit_id/release_id/medium_id/parent_id/field/value/tags/original_language/has_pictures; field takes a published field code; a dotted path works only when every level is searchable and enabled, so the seed definitions expose top-level codes such as tags, duration, edition_date and barcode; items + total (browse: exact PostgreSQL count; text search: OpenSearch snapshot with total_relation=index_snapshot, has_more and next_cursor), plus 400 invalid_sort / invalid_order for a sort key or direction outside the whitelist, and 400 invalid_query_param / query_too_long / invalid_limit / invalid_offset / invalid_page / pagination_conflict for parameters that cannot be sent as given (see each parameter). Throttled to a 120-request-per-minute default budget, counted per account for a signed-in caller and per client IP otherwise; the live policy (group presets and per-account overrides, including unlimited) is readable at GET /admin/rate-limits. Every throttled response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (seconds until the window resets), and an exhausted budget answers 429 rate_limited with Retry-After; a subject marked unlimited is not counted at all and therefore carries none of those headers, because there is no window to report)","tags":["Catalog"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Edit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Create entity with evidence (supports Idempotency-Key, 24h)","tags":["Catalog"]}},"/catalog/entities/candidates":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityCandidateQuery"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityCandidateResponse"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read-only identity candidates from the authoritative PostgreSQL index in one repeatable-read snapshot, including canonical resolution. Required kind plus at least one criterion: titles (base/localized title and aliases; case/whitespace normalized), external_ids [{provider,value}] or attributes [{key,value}] (exact scalar or scalar-list value). Criteria are OR, optional work_id restricts expression/content_unit, release_id restricts medium and medium_id restricts track scope. At most 20 criteria per category, values up to 256 bytes. limit=1000, max=1000; total is the exact matched-original count in this snapshot, complete=false when truncated. Never treat partial or unresolved canonical candidates as absence; narrow broad criteria instead of blindly retrying. Current caller visibility only, deleted originals excluded. items contain matched and canonical summaries; summaries must not be used for entity PUT. This read does not reserve identity or lock a later creation. Invalid kind/criteria/work_id/limit return 400; strict JSON; default budget 120/min. No OpenSearch dependency or offset pagination","tags":["Catalog"]}},"/catalog/entities/identity":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Batch identity resolution for cross-service alias aggregation (files/comments/favorites); JSON body {ids:[...]} up to 500, unresolvable identities (missing, invisible or redirect cycles) listed in missing; database, cancellation and timeout failures abort the entire request with a server error rather than returning partial items","tags":["Catalog"]}},"/catalog/entities/stats":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityStatusCounts"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Entity counts grouped by status over the whole catalog.entities table, plus the real table total (requires catalog.lifecycle.manage; throttled to a 120/min default budget, per account when signed in and otherwise per client IP). The list endpoint's shared filter always excludes deleted and merged rows — that visibility rule is deliberate and unchanged — so this aggregate is the only source for the tombstone count. statuses always carries all five codes (draft, pending_review, published, deleted, merged), zero-filled when a status has no rows, and total equals count(*) of the table, so a key that is present with 0 is a fact while an absent key means the count was not obtained","tags":["Catalog"]}},"/catalog/entities/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read visible entity","tags":["Catalog"]},"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Edit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Replace entity with optimistic version check. Track reads omit inclusions of expressions the reader cannot see; a whole-entity PUT that removes or changes such hidden historical inclusions is forbidden unless the editor has catalog.lifecycle.manage, so a filtered read cannot erase uninspected facts. Whole-entity replacement, pictures included: the pictures array is ordered and **array order is the display order**, so pictures[0] is the manually selected current cover (the server never re-sorts). taken_at is image creation/publication metadata. Optional version_label (localized names), usage_period {begin,end} describes a historically or concurrently valid image version; dates accept YYYY, YYYY-MM, YYYY-MM-DD or RFC3339 and a definitely reversed period is rejected with invalid_picture_period. Open/overlapping periods are allowed and never auto-select the cover. Optional role must be an enabled code of the picture_role vocabulary (empty = undeclared), asset_id must be a storage-service asset UUID (self-hosted cover bound with binding_role=cover_image). Writes are refused with duplicate_picture (same URL twice on one entity), too_many_pictures (over 40, because every picture is copied into each revision snapshot) and invalid_term (or unknown_vocabulary when the picture_role vocabulary itself is gone) for a role code outside the vocabulary","tags":["Catalog"]}},"/catalog/entities/{id}/identity":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Resolve canonical identity plus historical aliases (X01 identity contract: canonical_id, aliases, entity; read-only, rewrites nothing)","tags":["Catalog"]}},"/catalog/entities/{id}/lifecycle":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LifecycleEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Merge or retire (requires catalog.lifecycle.manage)","tags":["Catalog"]}},"/catalog/entities/{id}/links":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Page size, default 50, max 100; invalid values return 400","in":"query","name":"limit","required":false,"schema":{"type":"string"}},{"description":"Page offset, default 0; mutually exclusive with page","in":"query","name":"offset","required":false,"schema":{"type":"string"}},{"description":"1-based page number; mutually exclusive with offset","in":"query","name":"page","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityLinksPage"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read visible direct structural and semantic links from their canonical stores; each link has a direction relative to subject_id. The returned window includes endpoint entities, the live definitions ETag, and has_more. Fixed links are edited only through their owning entities. Pagination follows endpoint visibility and historical semantic attribute filtering (throttled to a 120/min default budget, per account when signed in and otherwise per client IP; override per group or per account via /admin/rate-limits); this first version does not claim per-edge evidence or historical rule versions","tags":["Catalog"]}},"/catalog/entities/{id}/occurrences":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read own reverse inclusions, scoped by entity kind (expression=itself, content_unit=its expressions, work=its expressions); an inclusion is returned only when its expression, release, medium and track are visible, and returned track contents omit hidden expressions","tags":["Catalog"]}},"/catalog/entities/{id}/relations":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read contextual forward and reverse relations; the response carries subject_id (the queried entity) and entities covering both ends of every returned relation — including the subject itself, so callers can render either side without an extra lookup","tags":["Catalog"]}},"/catalog/entities/{id}/resolve":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Resolve merged identity","tags":["Catalog"]}},"/catalog/entities/{id}/revisions":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read visible revision history; historical track contents are filtered by current expression visibility, while stored revision snapshots remain unchanged","tags":["Catalog"]}},"/catalog/entities/{id}/unpublish":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnpublishEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Demote a published entity back to draft, the only way back from published (requires catalog.lifecycle.manage; Save refuses demotion with use_lifecycle_endpoint). Request body is UnpublishEdit: expected_version, edit_note and at least one source, validated like every other write. Only published -\u003e draft is accepted: draft/pending_review have nothing to unpublish and deleted/merged are terminal, so all four answer 400 invalid_status (never 500); a stale expected_version is 409 version_conflict. The transition is recorded in the existing revision trail as a revision row plus an entity.unpublished outbox event, so GET /catalog/entities/{id}/revisions lists it while the contribution stats keep their calibration (audit_actions still counts only entity.deleted / entity.merged)","tags":["Catalog"]}},"/catalog/expressions/details":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Batch expression details (entity + own inclusions + same-content-unit siblings + credit) for release pages; JSON body {ids:[...]}. Own and sibling inclusions require visible expressions and carrier chains; hidden expression IDs, locators and inclusion attributes are omitted","tags":["Catalog"]}},"/catalog/expressions/{id}/composition":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpressionComposition"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read ordered direct parts and containing expressions from relations declaring expression_composition usage. Hidden or retired peers are omitted.","tags":["Catalog"]}},"/catalog/external-databases":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"List active external authority database definitions","tags":["ExternalDatabases"]}},"/catalog/me/home-preferences":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Read caller homepage section preferences (order, hidden and sections); all three are arrays","tags":["Catalog"]},"put":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HomePreferences"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Replace caller homepage section preferences; sections is the caller's full 'override + private' list of at most 20 entries, each entry having slug (lowercase code [a-z0-9][a-z0-9_-]{1,63}; a slug equal to a system shelf slug overrides that shelf for this caller only, it is not a conflict), names (zh-CN required and non-empty, other locales optional), query (same shape rules as shelf rules), sort (updated | created | title, empty means updated) and icon; a duplicate slug keeps the first declaration. Errors: invalid_slug, invalid_name, invalid_sort, invalid_tags, invalid_fields, invalid_vocab_terms, invalid_relations, too_many_sections. Unknown slugs in order/hidden are accepted and ignored instead of rejected (an administrator deleting a shelf must not block saving), and order/hidden are deduplicated","tags":["Catalog"]}},"/catalog/relations":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Relation"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Create contextual relation (requires catalog.relation.edit; supports Idempotency-Key, persistent: same key replays the first result across restarts/replicas, same key with a different payload returns 409 idempotency_conflict)","tags":["Catalog"]}},"/catalog/relations/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LifecycleEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Remove relation with evidence (requires catalog.relation.edit)","tags":["Catalog"]},"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Relation"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Replace relation context (requires catalog.relation.edit)","tags":["Catalog"]}},"/catalog/relationships/query":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationshipQueryRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationshipQueryResponse"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"},"429":{"description":"rate_limited; Retry-After reports seconds until another request is allowed"}},"summary":"Query direct structural, semantic and definitions-declared nested attribute-reference neighbors for 1-20 entity UUIDs (deduplicated in request order) in one read-only repeatable-read snapshot with the definitions ETag. direction=both/outgoing/incoming; self-links are outgoing. rule_codes are validated against /catalog/definitions relationship_rules, including disabled historical rules; peer_kinds filter the other endpoint. Visibility and attribute-reference checks precede per-subject pagination (limit=25, max=100; offset\u003e=0). Unavailable subjects have no page and are listed in unavailable_ids without distinguishing hidden from missing. attribute: rules carry field paths; references identify third-party typed entity references and via marks a third-party subject. entities contains only deduplicated RelationshipEntity summaries for visible subjects, returned endpoints and references, never full editable entities or recursive expansion. Strict JSON; invalid_ids/invalid_id/invalid_direction/invalid_rule_code/invalid_peer_kind/invalid_limit/invalid_offset return 400. Default throttle 60/min per account or client IP, overridable through the shared rate-limit policy; exhausted budgets return 429 with Retry-After","tags":["Catalog"]}},"/catalog/releases/{id}/editions":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEditions"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read explicitly grouped editions in one visible snapshot. Shared release subjects do not imply a group; ungrouped releases return group=null and editions=[].","tags":["Catalog"]}},"/catalog/releases/{id}/toc":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseTOC"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Read a visible release with ordered media and tracks plus deduplicated visible expressions in one consistent snapshot (throttled to a 120/min default budget, per account when signed in and otherwise per client IP; override per group or per account via /admin/rate-limits). Hidden child entities and their inclusions are omitted; each entity carries its own version and definition_etag identifies the live field contract. Errors: 400 invalid_id / not_release, 404 not_found","tags":["Catalog"]}},"/catalog/shelves":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"List enabled shelf rules (shared by homepage and admin)","tags":["Catalog"]}},"/catalog/shelves/feed":{"get":{"parameters":[{"description":"Items per shelf, default 12, max 100","in":"query","name":"per_shelf","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Evaluate shelf rules with their items, ordered by caller preferences; each shelf's items follow its own sort key: updated (default) | created | title. For a signed-in caller the shelf list is merged before ordering: a preferences section whose slug matches a system shelf overrides that shelf for this caller only (names merged per locale, query/sort replaced, blank icon keeps the system icon), other sections are appended as caller-private shelves, order interleaves system and custom slugs, and hidden removes both kinds; every entry's shelf carries source: system (possibly overridden) or custom, so the client knows whether the row can be deleted; anonymous callers always see source: system and no sections. Each entry also returns total: the full count of matching entities for that caller (not capped by per_shelf), while items is capped for display","tags":["Catalog"]}},"/catalog/tags":{"get":{"parameters":[{"description":"Substring filter on tag name","in":"query","name":"q","required":false,"schema":{"type":"string"}},{"description":"Max tags, default 200, max 500","in":"query","name":"limit","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Result"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Tag frequency aggregation over published entities' attributes.tags (q filter, limit\u003c=500)","tags":["Catalog"]}},"/catalog/tracks/{id}/contents":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackContentEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Add one inclusion with Track expected_version and edit evidence; returns the visible updated Track. No other inclusion is replaced.","tags":["Catalog"]}},"/catalog/tracks/{id}/contents/{position}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"position","required":true,"schema":{"minimum":0,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackContentEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Delete one visible inclusion with Track expected_version and edit evidence in the request body. Hidden records are preserved.","tags":["Catalog"]},"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"position","required":true,"schema":{"minimum":0,"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackContentEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Replace one inclusion identified by its previous position; inclusion.position may reorder it. Track expected_version prevents stale edits.","tags":["Catalog"]}},"/catalog/tracks/{id}/status":{"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackStatusEdit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Change only Track status, version and updated_at from current database facts; never replace contents, structural rows or other document keys. Strict TrackStatusEdit body: status, expected_version, edit_note and sources; unknown keys, including contents, return 400 invalid_payload. Accepts draft/pending_review/published with the same editing and publication permissions as whole-entity Save; anonymous callers get 401, unauthorized callers 403. Published requires translations and all references (including unchanged contents) to be anonymously visible; invalid references are rejected. deleted/merged and unknown statuses return 400 invalid_status; demotion from published must use the unpublish endpoint (400 use_lifecycle_endpoint). Non-Track targets return 400 not_track, stale expected_version returns 409 version_conflict. Full facts are recorded in revisions and entity.saved outbox in the same transaction, and the response applies current content visibility.","tags":["Catalog"]}},"/exchange/entities/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Export an entity snapshot for another instance, respecting caller visibility and current expression visibility in track contents; missing or invisible entities return 404, while database and internal decoding failures return a generic server error","tags":["Catalog"]}},"/exchange/proposals":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Edit"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entity"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Submit an external edit proposal (always lands in pending_review)","tags":["Catalog"]}},"/importer/import":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterImportRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterImportResponse"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Import previewed entry with evidence (requires catalog.import.submit; validated with zero writes before the first save: attribute values, unknown field codes, original_language, translation rows and date fields are checked against the published definitions with the same rules as entity saves; media/release original_language and translation rows are written to the medium/release entity; payload objects with no write path for the requested entity_type (canonical_entries/mediums/release on entity_type != work) are rejected with unsupported_field_for_entity_type instead of being ignored; download_cover=false skips remote cover refs; is_master_verified and media_type_hint are rejected; has_release=true without mediums, and a release object that declares data while mediums is empty (null or {} counts as absent, like an omitted field), are rejected with invalid_payload (mediums is the write instruction for the release chain in new_work/create_relation; a carrier-less release is only reachable through link_mode=append_release_to_work); link_mode merge_translations is rejected; an invalid entity_type is rejected with invalid_entity_type for every source (no silent fallback to work; Bangumi Preview uses the same validation, whereas DLsite/DMM Preview returns work without validating the requested type); release.cover_image_url is honoured as a Picture on the release entity (remote URL reference only, first picture wins when an existing release is reused); payload fields with no model slot are rejected with unsupported_field_for_entity_type instead of being silently dropped: mediums[*].media_category (no such field in the model, and the preview response always reports it empty), release.cover_aspect (Picture has no aspect; ratios are a display hint), release.notes and release.catalog_metadata (no such field on the release entity) and release.language (the release type declares no language field; use original_language/translations); source accepts concrete adapter ids advertised by GET /importer/sources plus the auto alias. Empty source and auto default to bangumi here, without Preview's URL/ID-based detection: clients importing a preview should submit its concrete response source. The normalized source determines the dedup key, external_ids key name and evidence note; sources without an implemented adapter return 400 not_supported)","tags":["Catalog"]}},"/importer/preview":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterPreviewRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterPreviewResponse"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Preview external catalog entry via an outbound fetch (requires catalog.import.submit; throttled to a 10/min default budget, per account when signed in and otherwise per client IP, overridable per group or per account via /admin/rate-limits). Supported concrete sources are advertised by GET /importer/sources. Empty source or auto detects the adapter from the URL/ID, falling back to bangumi when the source cannot be recognized; an explicit source takes precedence. The response source is the concrete adapter id and should be submitted to /importer/import. For Bangumi, entity_type accepts work/artist/organization/character and an invalid value returns invalid_entity_type; a bare numeric ID resolves along that type (artist/organization to the person resource, character to the character resource, otherwise the subject resource), while an explicit URL decides the resource and the response entity_type reports the resolved kind. DLsite and DMM product previews ignore the requested entity_type and always return entity_type=work; they do not perform Bangumi person/character routing or its entity_type validation. Metadata and associated-credit coverage depend on the adapter and upstream response. Only source/url_or_id/entity_type are accepted request fields; unknown fields such as media_type_hint return invalid_payload","tags":["Catalog"]}},"/importer/sources":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImporterSourceList"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"List the import sources that really have an adapter (requires catalog.import.submit, the same code /importer/preview and /importer/import use). Each item is {id, names, category, icon, description, url_pattern}: id is the adapter's source id as accepted by the two import endpoints, while names/category/icon/description/url_pattern come from the external authority database registry (the same rows GET /catalog/external-databases serves), so renaming or re-scoping a registry row changes this list without any frontend copy. Only concrete sources with an implemented adapter appear, and auto is deliberately absent: it is a resolution alias rather than a source (the import dialog keeps it as an explicit option). Preview detects empty source/auto from the URL/ID and falls back to bangumi when unrecognized; Import defaults empty source/auto to bangumi without detection, so clients should carry Preview's concrete response source into Import. A registry row added by an administrator never appears here on its own — the adapter set is code, and the admin list's importer marker reports exactly that difference","tags":["Catalog"]}},"/notifications":{"get":{"parameters":[{"description":"Page size, default 20, max 100; out-of-range values are clamped (never rejected)","in":"query","name":"limit","required":false,"schema":{"type":"string"}},{"description":"Page offset, default 0; negative values are clamped to 0","in":"query","name":"offset","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationList"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Read the caller's own notification inbox, newest activity first (requires authentication; no recipient parameter exists — the recipient is always the token holder, so another user's inbox is not addressable). Returns items + total + unread in one response: the list page needs all three consistent, and splitting them would leave a window where the badge says 3 while the list renders fully read. limit defaults to 20 and is silently clamped to 100, offset defaults to 0 and is clamped to \u003e= 0. Ordering is by updated_at (latest activity) desc, so a notification that aggregated a new event floats back to the top instead of staying at its first event's position. Notification types: comment.replied (someone replied to a post/topic the caller wrote, delivered by the community service), entity.included (the caller's work was declared as a subject of a release or included in a collection), entity.review_approved / entity.review_rejected (an editor or reviewer published or rejected one of the caller's entities), import.completed (a receipt for the caller's own import job). Each item carries type, actor_id/actor_name (possibly empty for system events), subject_type/subject_id for the click target, a per-type payload for rendering, count (how many events were merged into this row) and read. Retention is planned at 180 days but no cleanup job runs in this round","tags":["Notifications"]}},"/notifications/internal":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationDelivery"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationReadResult"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Service-to-service notification delivery (community -\u003e catalog). Requires X-Internal-Token (INTERNAL_API_TOKEN); disabled with 503 internal_api_disabled when unset. The caller supplies actor_id/actor_name as the event author snapshot in the request body; no end-user bearer token is accepted or required. Validates recipient_id, type, subject and dedupe fields before writing; delivery failures are logged by the caller without failing the original community action","tags":["Notifications"]}},"/notifications/read-all":{"post":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationReadResult"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Mark every unread notification of the caller as read (requires authentication; writes an audit row with action notification.all_read). The recipient condition is part of the UPDATE predicate, so this can only ever touch the caller's own rows. Returns ok, updated (how many rows this call marked) and unread (read back from the database after the update, not assumed to be 0). No 'until' parameter: the inbox is per-recipient, so 'all currently unread' is the whole semantics","tags":["Notifications"]}},"/notifications/unread-count":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationUnread"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Unread badge count for the caller (requires authentication). Deliberately the lightest endpoint of the feature: one COUNT over the partial index catalog.notifications_unread(recipient_id) WHERE read_at IS NULL, no rows read, no JOIN, no payload decoding, no aggregation — it exists to be polled by the top bar badge. Throttled to a 300-request-per-minute default budget (per account when signed in, otherwise per client IP — a single NAT can hold dozens of open tabs; overridable per group or per account via /admin/rate-limits). Answers a single unread field; 0 is a real zero from the count, never a placeholder","tags":["Notifications"]}},"/notifications/{id}/read":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationReadResult"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"security":[{"session":[]},{"bearer":[]}],"summary":"Mark one notification as read (requires authentication; writes an audit row with action notification.read). The recipient is part of the UPDATE predicate — a notification belonging to somebody else and a notification that does not exist are both 404 not_found, because answering 403 for the former and 404 for the latter would let a caller probe whether a given id exists in another user's inbox. read_at keeps its first value (COALESCE), so re-reading does not rewrite history; the response carries the caller's remaining unread count","tags":["Notifications"]}},"/users/{id}/contributions":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"all (default) | revisions | works | releases | artists","in":"query","name":"tab","required":false,"schema":{"type":"string"}},{"description":"Page number, default 1; values below 1 are clamped","in":"query","name":"page","required":false,"schema":{"type":"string"}},{"description":"Items per page, default 20, max 100; out-of-range values fall back to 20","in":"query","name":"page_size","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContributions"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"User contribution feed for the profile page: tab=all (default) mixes the entities the user created (works/releases/artists, judged by the version=1 revision actor snapshot) with their later edits (revision rows above version 1), revisions lists their entity revision rows with a field-level diff (diff keys follow the entity fields, attributes/translations drilled one level; ignored: id/version/created_by/created_at/updated_at), works/releases/artists list the entities the user created (artists maps to the agent kind); anonymous readable and filtered by the same visibility rules as entity lists (deleted/merged targets are invisible to everyone; unpublished targets only to their creator and catalog.lifecycle.manage holders), so items and stats never expose drafts; page defaults to 1 and page_size to 20 (both clamped, never rejected); an unknown tab is 400 invalid_tab, while an id that is not a UUID is 404 not_found — the same status and code the account profile (GET /users/{id}) and the community stats (GET /users/{id}/stats) answer with, so the profile page degrades all three sources alike instead of showing a parameter error; the directory never reads the account tables, so an unknown user and a user without contributions are both a 200 with zero counts; stats carry five counts derived from the revision actor snapshot columns without joining the account tables: works_created/releases_created/artists_created count first revisions (version 1) on visible targets, revisions_count counts revision rows on visible targets, while audit_actions counts lifecycle management actions (entity.deleted / entity.merged events) the user performed regardless of the target's current state, because deleting or merging removes the target from the visible set","tags":["Catalog"]}},"/version":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionInfo"}}},"description":"Success"},"400":{"description":"Invalid payload, source, definition or structural constraint"},"401":{"description":"Authentication required"},"403":{"description":"Insufficient edit or review permission"},"404":{"description":"Not found or not visible"},"409":{"description":"Version conflict; read current data before retrying"}},"summary":"Build identity of the running catalog process: the version and git SHA injected at build time, the build timestamp, and when this process started (all UTC, RFC 3339). Anonymous and read-only — it exists so that a deploy, a cutover or a rollback can be answered with 'which commit is actually running' instead of guessing from behaviour. Deliberately free of configuration, credentials, host names and database or object-storage details; anything the build did not inject comes back as the literal string unknown (an empty field would be indistinguishable from a broken build)","tags":["Catalog"]}}},"servers":[{"description":"标准统一主干 API","url":"/api"}],"tags":[{"description":"核心实体编目与查询 (Work, Release, Medium, Track, ContentUnit, Agent, Collection)","name":"Catalog"},{"description":"无代码动态元数据类型、属性与关系定义管理","name":"Definitions"},{"description":"站内通知：本人收件箱、未读数角标、标记已读，以及服务间投递（互动服务 → 目录）","name":"Notifications"},{"description":"外部权威数据库与官方渠道配置","name":"ExternalDatabases"},{"description":"API 限流策略：全局默认、按用户组预设与按账号覆盖（解除限制或指定每分钟额度）","name":"RateLimits"}]}