---
title: "Get Indexer Status"
method: GET
path: "/api/v1/resources/{resource_id}/indexer-status"
tags: ["resource-indexer"]
---

# Get Indexer Status

`GET /api/v1/resources/{resource_id}/indexer-status`

## Request

- Base URL: `https://memory.kagura-ai.com` (the document declares no server; this is the origin it was published from)
- URL: `https://memory.kagura-ai.com/api/v1/resources/{resource_id}/indexer-status`
- Auth: none declared

Return indexer state and recent ingest events for a resource.

The ``resource_id`` URL path parameter accepts the human-readable slug
(e.g. ``my-github-repo``), not an internal UUID. The slug is resolved to
the caller's workspace-scoped resource via
``PermissionService.resolve_resource_by_slug``. This backward-compatible
contract is maintained so existing integrations continue to work without
modification after the v0.12.0 UUID FK migration.

Owner-only (#389): ``WorkspaceOwner`` rejects non-owners with 403
(``resource_token`` write-scoped credentials are rejected by the same
dependency — pinned by isolation tests); ``resolve_resource_by_slug``
returns 404 (CWE-639 / OWASP A01) on cross-workspace probes so
existence does not leak.

## Path parameters

- `resource_id` string, required

## Headers

- `authorization` string, nullable

## Response `200`

Successful Response

- IndexerStatusResponse: Response body for ``GET /api/v1/resources/{resource_id}/indexer-status``.
  - `resource_id` string, required: Echo of the requested slug
  - `state` IndexerState: Indexer state snapshot for one resource/context.
    - `job_status` 'idle' | 'queued' | 'running' | 'failed', required
    - `last_run_at` string, nullable: ISO-8601 UTC timestamp of the most recent run
    - `next_run_at` string, nullable: ISO-8601 UTC timestamp of the next scheduled run
    - `active_version` integer, required: Active Qdrant collection version (blue/green); used for rollout coordination.
    - `last_offset` integer, required: Highest resource_events.id processed so far. Monotonically increasing; compare against ResourceEvent.id to estimate lag.
    - `lag_seconds` number, nullable: Server-computed (now - last_run_at). ``None`` when the indexer has never run. The UI uses this for health thresholds only — display a human relative time from ``last_run_at`` directly to avoid value drift while the tab is open.
    - `metrics` IndexerStateMetrics, required: Per-run indexer metrics, flattened from the JSONB column.
      - `applied_upserts` integer: Upsert events applied in the last run
      - `applied_deletes` integer: Delete events applied in the last run
      - `errors` integer: Errors observed in the last run
      - `skipped_reason` 'no_pending_events' | 'schema_not_found' | 'context_not_found' | 'empty_valid_points' | 'resource_entity_missing' | 'memories_per_day_exceeded' | 'plan_suspended' | 'memory_limit_exceeded', nullable: Present only when the last run was skipped. Surfacing a stale reason after a successful run is a UI bug we explicitly avoid.
  - `recent_events` ResourceEventItem[]: Latest ingest events, newest first. Capped server-side at 5 — there is no client-tunable limit on this endpoint by design; a cursor-paginated timeline belongs on a dedicated endpoint.
    - `id` integer, required: Event sequence id (stable ordering)
    - `op` 'upsert' | 'delete', required: Event operation
    - `doc_id` string, required: Document identifier (stable across versions)
    - `version` integer, nullable: Document version. NULL is a legitimate value for a delete-all-versions op (Issue #262).
    - `created_at` string, nullable: ISO-8601 UTC creation timestamp

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/kagura-ai/apis/kagura-memory-cloud.md) · [All operations](https://skmtc.dev/kagura-ai/apis/kagura-memory-cloud/llms.txt) · [OpenAPI document](https://skmtc.dev/kagura-ai/apis/kagura-memory-cloud/revisions/09f17f5ada29?raw)
