# Find related learning resources

Find explicitly or structurally related resources from a stable contentRef, such as course-to-practice and prediction-to-question relationships. Resource discovery and full reads remain owned by each resource Domain.

- Capability ID: `resources.related`
- Operation: `ielts_resources_related`
- Category: 资源与文件
- Endpoint: `POST /api/v1/agent/capabilities/ielts_resources_related`
- Authentication: Bearer Token（通过 /api/v1/agent-bindings 绑定账号）
- Required scopes: resources:read
- Side effect: read
- Human documentation: https://ieltsbuddy.igopx.cn/developers/api/ielts_resources_related

## Request parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `contentRef` | unknown | 是 | Stable contentRef returned by the owning resource Domain. |
| `limit` | number | 否 | limit |
| `relationTypes` | unknown[] | 否 | Optional relation types to include. |

## Request example

```bash
curl -X POST \
  'https://work.ieltsbuddy.igopx.cn/api/v1/agent/capabilities/ielts_resources_related' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer $IELTS_BUDDY_TOKEN' \
  --data '{"contentRef":"<contentRef>","limit":12,"relationTypes":[]}'
```

## Request schema

```json
{
  "type": "object",
  "properties": {
    "contentRef": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "kind": {
              "type": "string",
              "const": "question_part"
            },
            "partId": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "kind",
            "partId"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "type": "string",
              "const": "mock_paper"
            },
            "paperId": {
              "type": "string",
              "minLength": 1,
              "maxLength": 160
            }
          },
          "required": [
            "kind",
            "paperId"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "courseId": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            },
            "kind": {
              "type": "string",
              "const": "course_section"
            },
            "sectionId": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "courseId",
            "kind",
            "sectionId"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "type": "string",
              "const": "listening_dictation"
            },
            "partId": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "kind",
            "partId"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "type": "string",
              "const": "prep_guide"
            },
            "slug": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "required": [
            "kind",
            "slug"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "hitId": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            },
            "kind": {
              "type": "string",
              "const": "prediction_hit"
            }
          },
          "required": [
            "hitId",
            "kind"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "type": "string",
              "const": "speaking_material"
            },
            "materialId": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            }
          },
          "required": [
            "kind",
            "materialId"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "assetId": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991
            },
            "kind": {
              "type": "string",
              "const": "asset"
            }
          },
          "required": [
            "assetId",
            "kind"
          ],
          "additionalProperties": false
        }
      ],
      "description": "Stable contentRef returned by the owning resource Domain."
    },
    "limit": {
      "default": 12,
      "type": "integer",
      "minimum": 1,
      "maximum": 30
    },
    "relationTypes": {
      "default": [],
      "description": "Optional relation types to include.",
      "maxItems": 12,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 80
      }
    }
  },
  "required": [
    "contentRef",
    "limit",
    "relationTypes"
  ],
  "additionalProperties": false
}
```

## Response envelope

```json
{
  "code": 0,
  "data": {},
  "message": "ok"
}
```

## Errors

| HTTP | Code | Meaning |
| --- | --- | --- |
| 400 | `40001` | 请求参数不符合接口契约 |
| 401 | `40101` | 缺少或使用了无效的访问令牌 |
| 403 | `40301` | 访问令牌不包含接口所需权限 |
| 404 | `40401` | 接口或目标资源不存在 |
