Research Task API Contract
Status: active mainline contract
Scope: research task collection, task detail, task-scoped analysis/crawler/report resources, and compatibility with legacy task routes.
1. Purpose
/api/research-tasks is the resource-oriented entry for the research-task main workflow.
This path is intended to become the frontend's default task API surface:
- research task collection and active task snapshot
- list-oriented task view summaries for task center style pages
- task detail
- activate task
- task-scoped analysis resource
- task-scoped crawler resource
- task-scoped report resource
The legacy /api/research/tasks/... routes remain available as compatibility aliases during migration.
2. Shared Conventions
2.1 Response envelope
All documented routes return a JSON object with a top-level success field.
Typical success shape:
{
"success": true
}
Typical not-found shape:
{
"success": false,
"message": "Research task not found."
}
2.2 Research task identifiers
- Canonical task identifier field in route params:
task_id - Response payloads generally expose both:
- resource-style
id - compatibility field
task_id
- resource-style
2.3 Linked sub-resources
Task-scoped child resources are read conservatively:
-
/crawleronly exposes the crawler job linked bycrawler_job_id -
/analysis*usesanalysis_run_idwhen available, otherwise falls back to the latest persisted analysis run where the current service explicitly supports it -
/reportonly exposes the report job linked byreport_job_id
The task-scoped endpoints do not fall back to unrelated global runtime jobs.
3. Collection And Detail
3.1 GET /api/research-tasks
Returns the current research-task snapshot.
Response fields:
-
active_task: current active task ornull -
tasks: recent task list
Example:
{
"success": true,
"active_task": {
"id": "venue-20260420101010-ab12cd",
"task_id": "venue-20260420101010-ab12cd",
"title": "Alias Venue",
"status": "draft",
"generated_query": "..."
},
"tasks": [
{
"id": "venue-20260420101010-ab12cd",
"task_id": "venue-20260420101010-ab12cd",
"title": "Alias Venue",
"status": "draft"
}
]
}
3.2 POST /api/research-tasks
Creates or updates a research task.
Common request fields:
venue_namecityresearch_focusvenue_typetime_rangebenchmark_venuesnotes
Response fields:
-
task: saved task -
active_task: current active task after save -
tasks: recent task list after save
3.3 GET /api/research-tasks/task-views
Returns a list-oriented summary payload for pages that need task-centered list cards without activating each task first.
Response fields:
-
active_task_id: current active task id ornull -
task_views: list of task view entries
Each task_views[] item includes:
task_idtaskcrawlerreport
Notes:
-
taskreuses the standard research task response item -
crawlerreuses the task-scoped crawler resource payload shape -
reportreuses the task-scoped report resource payload shape - the route is intentionally list-oriented and read-only; it does not activate or mutate tasks
3.4 GET /api/research-tasks/{id}
Returns a single research task resource.
Response fields:
task
3.5 POST /api/research-tasks/{id}/activate
Switches the active research task.
Response fields:
active_tasktasks
4. Task-Scoped Analysis Resources
4.1 GET /api/research-tasks/{id}/analysis-run
Returns the latest analysis-run snapshot for the task.
Response fields:
task_idanalysis_run_idanalysis_run
Minimal example:
{
"success": true,
"task_id": "task-1",
"analysis_run_id": null,
"analysis_run": null
}
4.2 GET /api/research-tasks/{id}/analysis-runs
Returns persisted analysis-run history for the task.
Response fields:
task_idanalysis_run_idanalysis_runs
4.3 GET /api/research-tasks/{id}/analysis
Returns the task-scoped analysis resource view.
Response fields:
task_idanalysis
Typical analysis payload includes:
statussummaryhistorystatscurrent_run
4.4 Related write path
The write-side trigger for analysis is still:
POST /api/search
When called with research_task_id, the application layer resolves the task query and starts analysis dispatch for that task.
5. Task-Scoped Crawler Resource
5.1 GET /api/research-tasks/{id}/crawler
Returns the task-scoped crawler resource.
Response fields:
task_idcrawler
Typical crawler payload includes:
crawler_job_idstatustask_statuscurrent_jobjobssummaryhistory
Notes:
- If the task has no linked crawler job, the endpoint still returns a valid resource payload with linked fields empty.
- The resource does not borrow the global current crawler job from another task.
5.2 Related write paths
Crawler writes still live under the crawler API:
POST /api/crawler/startPOST /api/crawler/stop
When the frontend starts crawler work for a task, it should include research_task_id so that crawler_job_id can be synced back to the task.
6. Task-Scoped Report Resource
6.1 GET /api/research-tasks/{id}/report
Returns the task-scoped report resource.
Response fields:
task_idreport
Typical report payload includes:
report_job_idstatustask_statuscurrent_jobjobssummaryhistory
Notes:
- If the task has no linked report job, the endpoint returns an empty-but-valid task-scoped resource.
- The resource does not fall back to the latest unrelated global report task.
6.2 Related write path
The write-side trigger for report generation is still:
POST /api/report/generate
To keep the task workflow linked, callers should pass research_task_id.
That allows the backend to sync report_job_id back to the research task and expose the same job through /api/research-tasks/{id}/report.
7. Compatibility Mapping
The following legacy routes remain supported and currently delegate to the same application-layer payload builders:
| Resource-oriented path | Legacy compatibility path |
|---|---|
GET /api/research-tasks |
GET /api/research/tasks |
POST /api/research-tasks |
POST /api/research/tasks |
GET /api/research-tasks/task-views |
no legacy alias |
GET /api/research-tasks/{id} |
no exact legacy detail route |
POST /api/research-tasks/{id}/activate |
POST /api/research/tasks/{id}/activate |
GET /api/research-tasks/{id}/analysis-run |
GET /api/research/tasks/{id}/analysis-run |
GET /api/research-tasks/{id}/analysis-runs |
GET /api/research/tasks/{id}/analysis-runs |
GET /api/research-tasks/{id}/analysis |
GET /api/research/tasks/{id}/analysis |
GET /api/research-tasks/{id}/crawler |
GET /api/research/tasks/{id}/crawler |
GET /api/research-tasks/{id}/report |
GET /api/research/tasks/{id}/report |
Migration guidance:
- New frontend code should prefer
/api/research-tasks/... - Existing callers may continue using
/api/research/tasks/...during migration - New task-centric documentation should treat
/api/research-tasks/...as the primary path
8. Verification References
The following tests currently lock this contract:
tests/integration/test_web_api_smoke.pytests/integration/test_web_api_factory_smoke.pytests/unit/backend/test_crawler_routes.pytests/unit/application/test_analysis_service.pytests/unit/application/test_report_query_service.pytests/unit/application/test_report_service.py