> ## Documentation Index
> Fetch the complete documentation index at: https://dev.marginnote.com.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 获取文档同步状态

> 核对该文档的数据库引用、云端范围、本地与云端映射、下载队列与陈旧映射。

结论以 `state` 为准，该字段是整体判断。数据库一侧出现查询错误时，
响应里会列出这些错误，此时结论只是部分证据。外部文件提供方都报未核实。

带 `verifyHash=1` 才计算内容 hash。默认不算；打开之后要扫描整份已实体化的文件，大文档很慢。




## OpenAPI

````yaml /openapi/plugin-api.yaml get /documents/{bookmd5}/sync-status
openapi: 3.1.0
info:
  title: 场景插件 API
  summary: 场景插件在网页面板里可以调用的接口。
  description: >
    场景插件的面板是一个网页。页面里向 `/bridge/v1` 发请求，就能读写 MarginNote 里的数据。

    请求由 MarginNote 处理，与外部命令行工具共用同一套处理代码。外部工具要带令牌，面板不必带。

    面板页面从 `mnpanel://panel/index.html` 加载，因此 `fetch('/bridge/v1' + path)`
    属于同源请求。


    面板调用受这些条件约束：


    - 请求不带令牌，本文件也不声明安全方案。

    - 页面能调用哪些接口，取决于两份名单。模板里的 `plugins` 名单和沉浸态决定面板能不能建好，
      网页面板白名单决定页面能调哪些接口。不在白名单里的请求返回 `403`，
      错误码为 `IN_PROCESS_NOT_ALLOWED`。
    - `GET /capabilities` 里的 `requiresMax` 只约束外部 Agent。面板的请求在 MarginNote 进程内处理，
      不受令牌、订阅状态与跨设备批准的限制，能否调用只看该路径是否在白名单内。
    - 写操作里的 `addon`，MarginNote 会改写为当前面板所属插件的 id；`confirm` 由 MarginNote 补上。
      页面填的值不会生效。

    用 `mn.api(path, opts)` 读取数据。该方法始终将 Response Body 按 JSON 解析，相当于

    `fetch('/bridge/v1' + path, opts).then(r => r.json())`。


    响应的内容不是 JSON 的接口，改用 `fetch`：


    - `GET /guide` 返回 Markdown 正文。

    - `GET /notes/{noteid}/render` 返回卡片长图或 PDF。

    - `GET /documents/{bookmd5}/pages/{index}/content/{contentId}` 返回图片。

    - `GET /bundles/{bundleId}/files` 带 `?path=` 时返回该文件的原始字节。


    调用失败时 Promise 不会进入 reject。MarginNote 把错误对象

    `{"error":{"code":"…","message":"…"}}` 当作 Response Body 返回，因此结果落在 resolve 里。

    判断调用结果看响应里是否带 `error`，写操作另看响应里的 `persisted`。


    接口清单、各项上限与 Request Body 结构随 MarginNote 的版本变化，运行时以 `GET /capabilities` 与

    `GET /guide` 返回的内容为准。
  version: '0.91'
servers: []
security: []
tags:
  - name: 能力与状态
    description: 读取 MarginNote 的能力、版本与当前上下文。调用其他接口之前先读这组。
  - name: 卡片与摘录
    description: 卡片的读取与写入、摘录的创建、批注、标签、元数据与留白。
  - name: 手写会话
    description: 手写层、作答纸、练习准备清单与会话记录的读取与提交。
  - name: 学习集与卡组
    description: 学习集结构、脑图树、子脑图、色板、快照与复习卡组。
  - name: 文档与页面
    description: 文档目录、页文本、页内注释面、摘录清单与同步诊断。
  - name: 导出与 Anki
    description: 文档导出计划、导出文件、Anki 导出能力、作业与产物。
  - name: 查找
    description: 跨库搜索、文件夹列表与学习集列表。
  - name: 界面与模板
    description: 读取当前界面状态与沉浸模板。
  - name: 插件辅助
    description: 面板辅助脚本、已配对设备与本机 helper 信息。
  - name: 任务包与同步诊断
    description: 拆书任务包与旧 CloudKit 同步诊断。
paths:
  /documents/{bookmd5}/sync-status:
    get:
      tags:
        - 文档与页面
      summary: 获取文档同步状态
      description: |
        核对该文档的数据库引用、云端范围、本地与云端映射、下载队列与陈旧映射。

        结论以 `state` 为准，该字段是整体判断。数据库一侧出现查询错误时，
        响应里会列出这些错误，此时结论只是部分证据。外部文件提供方都报未核实。

        带 `verifyHash=1` 才计算内容 hash。默认不算；打开之后要扫描整份已实体化的文件，大文档很慢。
      operationId: getDocumentsBookmd5SyncStatus
      parameters:
        - $ref: '#/components/parameters/Bookmd5'
        - $ref: '#/components/parameters/VerifyHash'
      responses:
        '200':
          description: 核对结果。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SyncStatusResponse'
              examples:
                assembled:
                  summary: 构造示例，未实测
                  value:
                    state: available_and_published
                    database:
                      hasLearningData: true
                    databaseQueryErrors: []
                    originalDocument:
                      expectedByCurrentSettings: true
                    remainingUnverifiedMaterializedMappingCount: 0
                    activeDirectNoteReferenceCount: 12
                    studySetWithActiveNotesCount: 1
                measured:
                  summary: 实测于 2026-10-07，App 0.91
                  value:
                    schema: 1
                    originalDocument:
                      errors: []
                      expectedByCurrentSettings: false
                      mappingCount: 1
                      locations:
                        - kind: managed_local
                          placeholder: false
                          materialized: true
                          queuedForDownload: false
                          index: 0
                      uploadErrorCount: 0
                      iCloudDriveMappingCount: 0
                      expectedByLegacySyncScope: false
                      staleMappingCount: 0
                      placeholderCount: 0
                      virtualDocumentEmbeddedInCloudKit: false
                      materializedMappingCount: 1
                      externalFileProviderMappingCount: 0
                      queuedForDownloadCount: 0
                      reportedUploadedCount: 0
                      uploadingCount: 0
                      managedLocalMappingCount: 1
                    interpretation:
                      databaseAndOriginalDocumentAreIndependent: true
                      diagnoseLearningDataAndOriginalDocumentSeparately: true
                      learningDataEvidenceDoesNotProveCompleteness: true
                      learningDataMayArriveBeforeOriginalDocument: true
                    bookmd5: >-
                      ec280b8dbd77594d16b090165fdd4c07ec280b8dbd77594d16b090165fdd4c07
                    nextAction: none
                    database:
                      hasAnyRecord: true
                      bookRecordCount: 1
                      activeDirectNoteReferenceCount: 56
                      manualScopeUnverifiedStudySetCount: 0
                      bookConfigRecordCount: 1
                      hasLearningData: true
                      studySetReferenceCount: 4
                      studySetWithAnyNoteRecordCount: 3
                      duplicateBookConfigRecordRisk: false
                      tombstoneOrBackupDirectNoteCount: 0
                      definiteCloudKitScopeStudySetCount: 0
                      localOnlyStudySetCount: 3
                      studySetWithActiveNotesCount: 3
                      duplicateBookRecordRisk: false
                      directNoteReferenceCount: 56
                      bookConfigUSNProperties: 0
                      studySetWithOnlyResidualNotesCount: 0
                      bookConfigUSN: 775141815
                    contentVerification:
                      status: verified_match
                      scope: one_materialized_mapping
                      coordinatedRead: true
                      remainingUnverifiedMaterializedMappingCount: 0
                      fileSizeBytes: 59624
                      matchesDatabaseIdentity: true
                      verifiedMappingCount: 1
                    privacy:
                      containsAccountIdentifiers: false
                      containsDocumentNames: false
                      containsFilePaths: false
                      containsNoteContent: false
                      externalFileProviderReopened: false
                    bridgeApiVersion: '0.91'
                    state: available_local_only
        '500':
          $ref: '#/components/responses/InternalError'
      x-codeSamples:
        - lang: javascript
          label: 核对一份文档
          source: |
            const r = await mn.api('/documents/' + bookmd5 + '/sync-status');
            if (r.error && r.error.code === 'SYNC_DIAGNOSTIC_QUERY_FAILED') {
              // 数据库侧查询全失败，不代表文档或笔记不存在
            }
            mn.log(r.state);
components:
  parameters:
    Bookmd5:
      name: bookmd5
      in: path
      required: true
      description: >-
        文档的内容标识。取自 `GET /study-sets/{topicid}/documents` 响应里各项的 `bookmd5`、`GET
        /ui-state` 的 `state.bookmd5`，或 `GET /search?scope=documents`。
      schema:
        type: string
    VerifyHash:
      name: verifyHash
      in: query
      required: false
      description: 计算内容 hash。默认不算。开启后要扫描整份已实体化的文件，大文档很慢。
      schema:
        type: integer
        enum:
          - 1
  schemas:
    SyncStatusResponse:
      type: object
      description: 单个文档的同步核对。
      properties:
        state:
          type: string
          description: >-
            核对结论。`available_local_only` 与 `available_and_published` 表示可用；
            `waiting_for_icloud_download` 与 `mapped_but_not_materialized`
            表示内容尚未取得； 其余表示映射缺失、内容不一致或提供方未核实。
          enum:
            - database_reference_without_document_mapping
            - waiting_for_icloud_download
            - library_record_without_document_mapping
            - available_local_only
            - available_and_published
            - verified_mismatch
            - icloud_error
            - mapped_but_not_materialized
            - unverified_external_provider
        database:
          type: object
          properties:
            hasLearningData:
              type: boolean
        databaseQueryErrors:
          type: array
          description: 非空表示数据库一侧的结论只是部分证据。
          items:
            type: string
        originalDocument:
          type: object
          properties:
            expectedByCurrentSettings:
              type: boolean
        remainingUnverifiedMaterializedMappingCount:
          type: number
          description: 不为零时，该结论不能推广到其他映射上。
        activeDirectNoteReferenceCount:
          type: number
        studySetWithActiveNotesCount:
          type: number
    ErrorEnvelope:
      type: object
      description: >-
        失败时的 Response Body。MarginNote 将其当作正常 Response Body 返回，因此落在 resolve 里而不是
        reject 里。
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/ErrorObject'
    ErrorObject:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: 错误码。判断写入是否发生看该字段，不看 HTTP 状态码。
        message:
          type: string
          description: 人可读的说明。文案随 MarginNote 的版本变化，不要用该字段做分支判断。
        retryable:
          type: boolean
          description: >-
            是否明确可以稍后再试。只有外部调用的响应带该字段，面板本地调用的响应只有 `code` 与
            `message`。该布尔值表达不了结果未定，这类情况按各接口的说明处理，例如手写会话族看响应里的
            `layerLeaseUnresolved`。
        details:
          type: object
          description: >-
            附加事实。例如 `SCAN_BUSY` 带 `retryAfterSeconds`，`HASHTAG_ROUTE_REQUIRED` 带
            `writeRoute`。
          additionalProperties: true
  responses:
    InternalError:
      description: 写入后重新读取核对不通过，或写入过程报错。返回该响应表示写入未成功。
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          examples:
            saveFailed:
              summary: 写入磁盘后重新读取不一致
              value:
                error:
                  code: SAVE_FAILED
                  message: 写入之后重新读取核对不通过，碰过的卡已整体恢复。
                  retryable: false

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.