# Get the research schedule

> The knowledge.research.get operation: GET /api/v1/tax/knowledge/research in the REST API and the knowledge_research_get tool in the MCP server.

Returns the research plan of the Jurisdiction Knowledge Base and what is due today (UTC): the research
`waves` of `waves.yaml` with their status (`merged` once the wave's pull request is merged), dependency
`state` and report; the `recurring` waves (rate sweeps, quarterly Tier 1 re-research, overdue reviews) with
their current occurrence and whether it is `due`; the jurisdictions with records past `nextReviewBy`
(`overdue`); and the wave `reports`. Each due item has a `prompt` to paste into a Claude Code session
opened in the Ownrecord repository: research runs there, never in the platform (spec §42.6).

Waves and reports come from the research data compiled with the app (`artifact`); overdue records and wave
scopes from the knowledge loaded in the database (`loaded`). Demand-based promotions need the demand index
and aren't evaluated yet. Platform staff only.

## At a glance

- **REST:** `GET /api/v1/tax/knowledge/research`
- **MCP tool:** `knowledge_research_get`
- **Operation ID:** `knowledge.research.get`
- **Scope:** Platform
- **Permission:** `tax_knowledge:read`
- **Risk tier:** `read`
- **Dry run:** Not supported
- **Idempotency:** Not needed (read only)
- **Modes:** Test and live
- **Authentication:** API key with the `tax_knowledge:read` scope
- **Since:** M3

## Request

### Query parameters

This operation takes no query parameters.

## Response

`200 OK` with a JSON object:

| Field                              | Type                                                                    | Description |
| ---------------------------------- | ----------------------------------------------------------------------- | ----------- |
| `object`                           | `"knowledge_research"`                                                  |             |
| `today`                            | string                                                                  |             |
| `artifact`                         | object                                                                  |             |
| `artifact.available`               | boolean                                                                 |             |
| `artifact.commit`                  | string or null                                                          |             |
| `artifact.problem`                 | string or null                                                          |             |
| `loaded`                           | object or null                                                          |             |
| `waves`                            | array of object                                                         |             |
| `waves[].id`                       | string                                                                  |             |
| `waves[].kind`                     | one of `research`, `review`                                             |             |
| `waves[].status`                   | one of `planned`, `merged`                                              |             |
| `waves[].when`                     | string or null                                                          |             |
| `waves[].state`                    | one of `merged`, `ready`, `blocked`                                     |             |
| `waves[].dependencies`             | array of object                                                         |             |
| `waves[].dependencies[].id`        | string                                                                  |             |
| `waves[].dependencies[].status`    | one of `planned`, `merged`, `unknown`                                   |             |
| `waves[].runs`                     | integer (at least 0)                                                    |             |
| `waves[].jurisdictions`            | integer (at least 0)                                                    |             |
| `waves[].foldersPresent`           | integer (at least 0)                                                    |             |
| `waves[].done`                     | integer (at least 0)                                                    |             |
| `waves[].branch`                   | string                                                                  |             |
| `waves[].report`                   | object or null                                                          |             |
| `waves[].prompt`                   | string                                                                  |             |
| `recurring`                        | array of object                                                         |             |
| `recurring[].id`                   | string                                                                  |             |
| `recurring[].kind`                 | one of `research_diff`, `plan`                                          |             |
| `recurring[].schedule`             | array of string or one of `weekly`, `monthly`, `quarterly`              |             |
| `recurring[].scheduleLabel`        | string                                                                  |             |
| `recurring[].scope`                | object or null                                                          |             |
| `recurring[].occurrence`           | string                                                                  |             |
| `recurring[].next`                 | string                                                                  |             |
| `recurring[].due`                  | boolean                                                                 |             |
| `recurring[].evaluated`            | boolean                                                                 |             |
| `recurring[].reason`               | string                                                                  |             |
| `recurring[].inScope`              | array of string                                                         |             |
| `recurring[].report`               | object                                                                  |             |
| `recurring[].report.file`          | string                                                                  |             |
| `recurring[].report.exists`        | boolean                                                                 |             |
| `recurring[].prompt`               | string                                                                  |             |
| `overdue`                          | array of object                                                         |             |
| `overdue[].jurisdictionId`         | string                                                                  |             |
| `overdue[].name`                   | string or null                                                          |             |
| `overdue[].tier`                   | `1` or `2` or `3` or null                                               |             |
| `overdue[].earliest`               | string                                                                  |             |
| `overdue[].records`                | array of object                                                         |             |
| `overdue[].records[].ref`          | string                                                                  |             |
| `overdue[].records[].nextReviewBy` | string                                                                  |             |
| `overdue[].records[].status`       | one of `researched`, `cross_checked`, `reviewed`, `verified`, `retired` |             |
| `overdue[].prompt`                 | string                                                                  |             |
| `reports`                          | array of object                                                         |             |
| `reports[].id`                     | string                                                                  |             |
| `reports[].title`                  | string                                                                  |             |

## Examples

### A quarterly Tier 1 re-research is due

```http
GET /api/v1/tax/knowledge/research
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "knowledge_research",
  "today": "2026-10-13",
  "artifact": {
    "available": true,
    "commit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1",
    "problem": null
  },
  "loaded": {
    "root": "knowledge",
    "commit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
  },
  "waves": [
    {
      "id": "t1-w2-eu-members",
      "kind": "research",
      "status": "merged",
      "when": "development M2",
      "state": "merged",
      "dependencies": [
        {
          "id": "t1-w1-foundations",
          "status": "merged"
        }
      ],
      "runs": 4,
      "jurisdictions": 27,
      "foldersPresent": 27,
      "done": 27,
      "branch": "knowledge/t1-w2-eu-members",
      "report": {
        "id": "t1-w2-eu-members",
        "title": "Wave report — t1-w2-eu-members"
      },
      "prompt": "Run research wave `t1-w2-eu-members` per spec §42.6"
    },
    {
      "id": "t1-w3-crosscheck",
      "kind": "review",
      "status": "planned",
      "when": "development M2–M3",
      "state": "ready",
      "dependencies": [
        {
          "id": "t1-w2-eu-members",
          "status": "merged"
        }
      ],
      "runs": 82,
      "jurisdictions": 82,
      "foldersPresent": 82,
      "done": 12,
      "branch": "knowledge/t1-w3-crosscheck",
      "report": null,
      "prompt": "Run research wave `t1-w3-crosscheck` per spec §42.6"
    }
  ],
  "recurring": [
    {
      "id": "tier1-quarterly",
      "kind": "research_diff",
      "schedule": "quarterly",
      "scheduleLabel": "Quarterly",
      "scope": {
        "tiers": [1]
      },
      "occurrence": "2026-10-01",
      "next": "2027-01-01",
      "due": true,
      "evaluated": true,
      "reason": "31 jurisdictions in scope.",
      "inScope": ["AT", "BE", "HR"],
      "report": {
        "file": "reports/tier1-quarterly-2026-10-01.md",
        "exists": false
      },
      "prompt": "Run research wave `tier1-quarterly` per spec §42.6 (occurrence 2026-10-01). `pnpm knowledge:wave plan tier1-quarterly --today 2026-10-13` lists its runs and prompts; the wave report goes to data/tax/knowledge/reports/tier1-quarterly-2026-10-01.md."
    }
  ],
  "overdue": [],
  "reports": [
    {
      "id": "t1-w2-eu-members",
      "title": "Wave report — t1-w2-eu-members"
    }
  ]
}
```

## Errors

| Code                                                                                   | HTTP status | When                                                                                            | What to do                                                                      |
| -------------------------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied) | 403         | You aren't platform staff (organizations read the knowledge itself, not the research schedule). | Ask an organization owner or admin for a role or scope that allows this action. |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed), [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found), [`dry_run_not_supported`](https://ownrecord.io/docs/reference/errors.md#dry_run_not_supported), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
