# Query document details

Read the current snapshot and segments of a source document. Before editing segments, read `data.etag` as the precondition for a write.

```text
GET https://api.moi.matrixorigin.cn/v5/semantic-models/{model_id}/sources/{source_row_id}/document
```

## Preparation before calling

First [query the data source list](list-data-sources.md) to obtain the source record ID. Prepare a personal access token and target workspace ID that has access to the target workspace.

The example below uses:

- `$AI_STUDIO_API_KEY`: The actual personal access token, passed through the `X-API-Key` Header.
- `$WORKSPACE_ID`: Target workspace ID, passed through `X-Workspace-ID` Header.
- `$MODEL_ID`: Knowledge Base ID.
- `$SOURCE_ROW_ID`: Source record ID.

## Request example

```bash
curl "https://api.moi.matrixorigin.cn/v5/semantic-models/$MODEL_ID/sources/$SOURCE_ROW_ID/document?page_size=20" \
  -H "X-API-Key: $AI_STUDIO_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID"
```

## Path parameters

| Parameters | Type | Description |
| --- | --- | --- |
| `model_id` | integer | Knowledge base ID. |
| `source_row_id` | string | Source record ID. |

## Query parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `page_size` | integer | No | Segments per page. Must be positive; defaults to 20 and is capped at 100. |
| `cursor` | string | No | `data.segment_status.next_cursor` from the previous page; omit on the first request. |

## Successful response

Returns `200` with the current source, preview, segment status, and this page of segments. The response example is an excerpt.

When `data.segment_status.next_cursor` is nonempty, pass it as `cursor` to fetch the next page. Stop when the field is absent or empty. Do not decode or modify the cursor.

```bash
curl --get "https://api.moi.matrixorigin.cn/v5/semantic-models/$MODEL_ID/sources/$SOURCE_ROW_ID/document" \
  -H "X-API-Key: $AI_STUDIO_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  --data-urlencode "page_size=20" \
  --data-urlencode "cursor=$NEXT_CURSOR"
```

```json
{
  "code": "OK",
  "msg": "OK",
  "data": {
    "source": {
      "row_id": "src_01",
      "model_id": 401,
      "source_type": "file",
      "ingest_status": "ready"
    },
    "preview": {
      "available": true
    },
    "file_info": {
      "tags": ["product"],
      "enabled": true,
      "expires_at": null,
      "expired": false,
      "effective_enabled": true,
      "force_enabled_after_expiry": false
    },
    "segment_status": {
      "available": true,
      "total": 1
    },
    "etag": "<DOCUMENT_ETAG>",
    "segments": [
      {
        "segment_id": "seg_01",
        "level": "chunk",
        "content": "产品说明",
        "word_count": 4,
        "recall_count": 0,
        "enabled": true
      }
    ]
  }
}
```

The response fields are as follows.

| Field | Type | Description |
| --- | --- | --- |
| `code` | string | `OK` on success. |
| `msg` | string | `OK` on success. |
| `data.source` | object | Source record. |
| `data.source.source_id` | string | Source ID, returned when nonempty. |
| `data.source.source_resource_id` | string | Original resource ID, returned when available. |
| `data.source.kb_resource_id` | string | Knowledge-base resource ID, returned when available. |
| `data.source.source_file_id` | string | Original file ID, returned when available. |
| `data.source.kb_file_id` | string | Knowledge-base file ID, returned when available. |
| `data.source.source_table_id` | integer | Original table ID, returned when available. |
| `data.source.kb_table_id` | integer | Knowledge-base table ID, returned when available. |
| `data.source.source_path` | string | Original source path, returned when available. |
| `data.source.tags` | array of string | Source tags, returned when nonempty. |
| `data.source.created_by` | string | Creator ID, returned when available. |
| `data.source.updated_by` | string | Last updater ID, returned when available. |
| `data.source.governance_status` | string | Governance status, returned when nonempty. |
| `data.source.legacy_origin` | string | Legacy source marker, returned when available. |
| `data.preview.available` | boolean | Whether preview content is available. |
| `data.preview.content` | string | Preview content when available. |
| `data.preview.reason` | string | Reason the preview is unavailable, when applicable. |
| `data.file_info` | object | File tags, expiration and activation information. |
| `data.file_info.tags` | array of string or null | File tags; `null` when empty. |
| `data.file_info.expires_at` | integer or null | File expiration timestamp, or `null` when unset. |
| `data.file_info.enabled` | boolean or null | Explicit activation setting, or `null` when unset. |
| `data.file_info.expired` | boolean | Whether the file has expired. |
| `data.file_info.effective_enabled` | boolean | Current actual effective status. |
| `data.file_info.force_enabled_after_expiry` | boolean | Whether activation is forced after expiration. |
| `data.segment_status.available` | boolean | Whether segments are available. |
| `data.segment_status.total` | integer | Number of segments. |
| `data.segment_status.next_cursor` | string | Next-page cursor, returned when more segments are available. |
| `data.etag` | string | Current snapshot precondition; returned when available. Pass it as `if_match` when editing segments. |
| `data.segments` | array of object | This page of segments in the current snapshot. |
| `data.segments[].segment_id` | string | Segment ID. |
| `data.segments[].start_ms` | integer | Start time or position, returned when available. |
| `data.segments[].end_ms` | integer | End time or position, returned when available. |
| `data.segments[].level` | string | Segment level. |
| `data.segments[].chunk_index` | integer | Segment index, returned when available. |
| `data.segments[].chunk_id` | string | Chunk ID, returned when available. |
| `data.segments[].content` | string | Segment content, returned when available. |
| `data.segments[].ocr_text` | string | OCR text, returned when available. |
| `data.segments[].image_description` | string | Image description, returned when available. |
| `data.segments[].image_file_id` | string | Image file ID, returned when available. |
| `data.segments[].page_image_file_id` | string | Page image file ID, returned when available. |
| `data.segments[].word_count` | integer | Unicode character count of joined content, OCR text and image description, including separating newlines. |
| `data.segments[].recall_count` | integer | Recall count. |
| `data.segments[].enabled` | boolean | Whether the segment is enabled. |
| `data.segments[].metadata` | object | Source volume metadata, returned when `volume_id` is present. Other input metadata is not echoed in full. |

In field paths, `[]` means each item in an array. For example, `data.segments[].segment_id` is the `segment_id` field of each item in `data.segments`.

## Error response

```json
{
  "code": "ErrNotFound",
  "msg": "Not Found"
}
```

### Common HTTP errors

```{list-table}
:header-rows: 1
:widths: 12 22 32 34

* - HTTP status code
  - error code
  - Common causes
  - Recommended actions
* - `400`
  - `ErrParamInvalid`
  - `model_id` is invalid or `source_row_id` is empty.
  - Get the path ID from the source list.
* - `401`
  - `ErrUnauthorized`
  - The API Key is invalid or has expired.
  - Check API Key.
* - `403`
  - `ErrForbidden`
  - The caller does not have permission to read the source document.
  - Check workspace and object authorization.
* - `404`
  - `ErrNotFound`
  - The knowledge base or source does not exist or is not visible to the current caller.
  - Reconfirm the path ID.
* - `500`
  - `ErrServer`
  - The service failed to read the document or segment.
  - Keep the desensitized response information and try again.
```

## Follow-up operations

To add content, [create a segment](create-segment.md); to edit an existing segment, [update it](update-segment.md). Pass `data.etag` as `if_match` in the write body or as the `If-Match` header. After a successful write, use the new snapshot's ETag. On a precondition conflict, read the document again and review the intended change before submitting it.
