GET /api/v1/process/status/
Returns a Server-Sent Events stream with progress updates and the final analysis result.
Request
http
GET /api/v1/process/status/{task_id}
Authorization: Bearer YOUR_KEY
Accept: text/event-streamEvent Types
Each event is a JSON object on a data: {...} line.
PROGRESS
json
{
"state": "PROGRESS",
"progress": 45,
"details": {
"step": "analysis_internal",
"message": "Computing TF-IDF vectors"
}
}SUCCESS
json
{
"state": "SUCCESS",
"progress": 100,
"result": {
"Umbrella Analysis": [...],
"Block Comparison": [...],
"N-grams Analysis": [...],
"Anchors Analysis": [...],
"Triplets Analysis": {...}
},
"page_status": {
"parsed": [{"url": "https://example.com/page", "is_own_page": true}],
"failed": [{"url": "https://competitor.example/page", "is_own_page": false}]
}
}FAILURE
json
{
"state": "FAILURE",
"error": { "code": 1001, "message": "The analysis could not be completed." }
}Result Structure
| Key | Always | Description |
|---|---|---|
"Umbrella Analysis" | ✅ | Semantic proximity gaps — words to add |
"Block Comparison" | ✅ | TF-IDF word density comparison |
"N-grams Analysis" | ✅ | 2–3 word phrase patterns |
"Anchors Analysis" | ✅ | Anchor texts with href URLs |
"Triplets Analysis" | ⚡ extended | Knowledge Graph (only with triplet_analysis: true) |
"Umbrella Analysis" item
json
{
"lemma": "warranty",
"competitor_avg_score": 1.84,
"own_score": 0.0,
"gap": 1.84,
"coverage_percent": 75.0,
"recommendation": "Add to H2/H3",
"context_snippet": "12-month warranty included"
}"Block Comparison" item
json
{
"word": "mattress",
"lemma": "mattress",
"frequency": 8.3,
"frequency_own_page": 2,
"pct_target_comp_avg": -45.2,
"action_needed": "increase",
"present_on_own_page": true
}"N-grams Analysis" item
json
{
"ngram": "free shipping",
"ngram_type": "bigrams",
"pages_count": 4,
"frequency_avg": 2.5,
"present_on_own_page": false
}"Anchors Analysis" item
json
{
"anchor": "shop now",
"frequency_own": 0,
"frequency_comp_avg": 3.2,
"pages_count": 3,
"links": ["https://comp1.com/shop", "https://comp2.com/store"]
}page_status
page_status is returned next to result, not inside the analysis result. parsed lists pages included in the analysis. failed lists requested pages that were not included. These lists expose only the URL and page role.
json
{
"parsed": [
{"url": "https://example.com/page", "is_own_page": true}
],
"failed": [
{"url": "https://competitor.example/page", "is_own_page": false}
]
}"Triplets Analysis"
json
{
"entities": [
{
"subject": "Mattress",
"tier": "core",
"triplets_count": 12,
"sources_count": 4,
"triplets": [
{
"predicate": "filler material",
"object": "independent springs",
"sources": ["comp1.com", "comp2.com"]
}
]
}
],
"missing_triplets": {
"critical": [...],
"important": [...],
"unique": [...]
},
"stats": {
"total_triplets": 87,
"sources_with_content": 5,
"gaps_critical": 3,
"gaps_important": 8,
"gaps_unique": 21,
"gaps_total": 32
}
}Python Example
python
import requests, json
BASE = "https://unihra.ru/api/v1"
HEADERS = {"Authorization": "Bearer YOUR_KEY"}
with requests.get(
f"{BASE}/process/status/{task_id}", headers=HEADERS, stream=True
) as resp:
for line in resp.iter_lines():
if not line or not line.startswith(b"data: "):
continue
event = json.loads(line[6:])
state = event["state"]
if state == "PROGRESS":
print(f"[{event['progress']}%] {event.get('details', {}).get('message', '')}")
elif state == "SUCCESS":
result = event["result"]
gaps = result.get("Umbrella Analysis", [])
for g in gaps[:5]:
print(f"{g['lemma']:20s} gap={g['gap']:.2f} → {g['recommendation']}")
break
elif state == "FAILURE":
err = event.get("error", {})
raise RuntimeError(f"[{err.get('code')}] {err.get('message')}")