API Reference
The Surchin REST API lets you deposit, query, and reinforce insights programmatically.
Base URL
https://getsurch.in/api/v1Authentication
All endpoints except /health require an API key in the Authorization header:
Authorization: Bearer sk_your_api_keyError Format
{
"error": {
"code": "string",
"message": "string"
}
}/health
Health check endpoint. No authentication required.
Response
{
"status": "ok",
"service": "surchin",
"version": "0.1.0",
"timestamp": "2026-03-01T00:00:00.000Z"
}/sense
Query the knowledge substrate. Required scope: sense
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Natural-language search query |
file_context | string[] | No | Files being worked on (boosts locality) |
symbol_context | string[] | No | Symbols being worked on |
tag_context | string[] | No | Tags to filter/boost |
error_signature | string | No | Raw error text for fingerprint matching |
kinds | InsightKind[] | No | Filter to specific kinds |
limit | number | No | Max results (default 3, max 10) |
repo_id | string | No | Repository identifier |
session_id | string | No | Session ID for session-scoped queries |
depth | integer (0-2) | No | Retrieval depth: 0=topic summaries, 1=top insight per cluster, 2=full results (default 2) |
cluster_id | string | No | Filter results to a specific topic cluster |
group_ids | string[] | No | Filter results to specific groups by ID |
Response
{
"results": [
{
"insight_id": "uuid",
"kind": "SOLUTION",
"status": "promoted",
"summary": "One-line summary",
"content": "Full insight content...",
"effective_strength": 42.5,
"rank_score": 0.87,
"semantic_similarity": 0.92,
"locality_score": 0.75,
"trust_factor": 1.0,
"age_days": 3.2,
"file_patterns": ["src/auth/validator.ts"],
"tags": ["auth", "jwt"]
}
],
"formatted_context": "Human-readable summary of results",
"query_time_ms": 45,
"candidate_count": 12
}/deposit
Deposit an insight into the knowledge substrate. Required scope: deposit
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
kind | InsightKind | Yes | SOLUTION, PATTERN, PITFALL, CONTEXT, WORKFLOW, DEPENDENCY |
content | string | Yes | Full text of the knowledge |
summary | string | No | One-line summary (auto-generated if omitted) |
error_signature | string | No | Raw error text for fingerprinting |
file_patterns | string[] | No | File paths to anchor to |
symbol_names | string[] | No | Symbol names to anchor to |
tags | string[] | No | Categorization tags |
idempotency_key | string | No | Client-provided dedup key |
repo_id | string | No | Repository identifier |
session_id | string | No | Session ID to associate the deposit with |
group_id | string (UUID) | No | Scope deposit to a specific group |
Response (201 Created / 200 Deduplicated)
{
"insight_id": "uuid",
"kind": "SOLUTION",
"status": "draft",
"strength_raw": 10.0,
"error_signature_hash": "sha256_hash_or_null",
"anchors_created": 3,
"created": "2026-03-01T00:00:00.000Z",
"deduplicated": false,
"merged_into": null
}/reinforce
Rate an insight as helpful or unhelpful. Required scope: reinforce
Request Body
Provide either insight_id (single) or insight_ids (batch), plus the signal type.
| Field | Type | Required | Description |
|---|---|---|---|
insight_id | string | One of* | ID of a single insight to rate |
insight_ids | string[] | One of* | IDs of multiple insights to rate |
signal_type | string | Yes | POSITIVE, NEGATIVE, HUMAN_UPVOTE, HUMAN_DOWNVOTE, AUTO_DECAY, SENSE_RETURN |
context | string | No | Optional context about why this rating was given |
session_id | string | No | Session context |
sense_batch_id | string | No | Link reinforcement to a specific query batch |
skill_id | string | No | Skill being rated |
skill_feedback | string | No | "followed" or "dismissed" |
repo_id | string | No | Repository context |
* Provide either insight_id or insight_ids, not both.
Response
{
"insight_id": "uuid",
"signal_id": "uuid",
"signal_type": "POSITIVE",
"deposit_amount": 10,
"new_strength": 52.5,
"previous_strength": 42.5,
"status_changed": false,
"new_status": "promoted"
}/friction
Get a friction report showing recurring errors and module hotspots. Required scope: sense
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
error_text | string | Yes | Error text to analyze |
file_path | string | No | Scope report to a specific file |
repo_id | string | No | Repository identifier |
time_range_days | number | No | Lookback window (default 7) |
Response
{
"time_range_days": 7,
"top_errors": [...],
"module_heatmap": [...],
"formatted_report": "Human-readable friction report",
"total_sessions": 42,
"total_friction_episodes": 8
}Auto-Capture
Hook-based event ingestion and session lifecycle endpoints. These are called automatically by Claude Code hooks during a session.
/auto-capture
Lightweight event ingestion for hook-based auto-capture. Events are stored in session_events (not as insights) and may be promoted to insights during session finalization. Required scope: deposit
Target response time: <100ms. Returns 202 Accepted on success.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
tool_name | string | Yes | Name of the tool that produced this event |
event_type | string | Yes | One of: edit, write, test, build, git, migration, error |
summary | string | Yes | Short description of the event (max 2000 chars) |
content_hash | string | Yes | Client-provided hash for deduplication within a session |
session_id | string | Yes | Client session identifier. Session is auto-created if it does not exist. |
file_paths | string[] | No | File paths associated with the event |
raw_input | string | No | Raw tool input (max 500 chars) |
raw_output | string | No | Raw tool output (max 500 chars) |
repo_id | string | No | Repository identifier |
Response (202 Accepted)
{
"status": "captured",
"event_id": "uuid"
}If a duplicate content_hash is detected within the same session, returns 200 with "status": "deduplicated".
/sessions/turn-summary
Generate a heuristic summary from accumulated session events since the last turn summary. Called by the Stop hook. Summary is template-based (no AI call) for speed and cost.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
session_id | string | Yes | Client session identifier |
repo_id | string | No | Repository identifier |
Response
{
"status": "created",
"turn_number": 3,
"summary": "Modified: src/auth.ts, src/api.ts. edit: 5. Tests: 2 passed, 0 failed",
"events_processed": 8
}Returns "status": "no_events" if no new events have been captured since the last turn summary.
/sessions/finalize
Finalize a session: aggregate turn summaries into a session summary, identify high-signal events for automatic promotion to draft insights, and mark the session as ended. Called by the SessionEnd hook.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
session_id | string | Yes | Client session identifier |
repo_id | string | No | Repository identifier |
Response
{
"status": "finalized",
"summary": "Session lasted 45 minutes. 3 turn(s)...",
"events_count": 24,
"turns_count": 3,
"promotions": 2,
"promoted_insight_ids": ["uuid1", "uuid2"]
}Promotion Heuristics
Finalization runs three heuristics to auto-promote session events to draft insights (capped at 5 per session):
| Heuristic | Insight Kind | Trigger |
|---|---|---|
| iterative_edits | PATTERN | File edited N+ times in one session |
| test_fix | SOLUTION | Test failure followed by edits followed by test pass |
| recurring_error | PITFALL | Same error hit N+ times in one session |
Thresholds are configurable per-org via the /admin/tune-capture endpoint. Returns "status": "already_finalized" if the session has already been finalized.
/session-context
Lightweight endpoint for the SessionStart hook. Returns user preferences, top-reinforced insights, last session summary, team activity, auto-promoted insights, and trending insights — all without a vector search. Required scope: sense
Target response time: <200ms.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
repo_id | string | No | Repository identifier for scoping insights |
Response
{
"preferences_context": "## User Preferences\n...",
"recent_patterns": [
{ "kind": "PATTERN", "summary": "...", "strength": 85.0 }
],
"active_pitfalls": [
{ "kind": "PITFALL", "summary": "...", "strength": 60.0 }
],
"last_session": {
"title": "Feature implementation",
"summary": "Session lasted 30 minutes...",
"handoff_note": "Still need to write tests for...",
"started_at": "2026-03-29T10:00:00Z",
"ended_at": "2026-03-29T10:30:00Z",
"sense_count": 5,
"deposit_count": 2
},
"trending": [
{ "id": "uuid", "kind": "SOLUTION", "summary": "...", "signal_count": 4 }
],
"team_activity": {
"deposits_this_week": 12,
"active_contributors": 3,
"top_insight": "..."
},
"auto_promoted": [
{ "kind": "PATTERN", "summary": "..." }
]
}Groups
Team-scoped access control for insights and skills. Requires Team tier or above.
/groups
List all groups for the authenticated user's organization. A default group is auto-provisioned if none exist.
Response
{
"groups": [
{
"id": "uuid",
"name": "Engineering",
"slug": "engineering",
"description": "Core engineering team",
"is_default": false,
"is_private": false,
"color": "#3b82f6",
"member_count": 5
}
]
}/groups
Create a new group. Requires admin scope and org admin/owner role.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Group name (max 100 chars) |
slug | string | No | URL-safe slug (auto-generated from name if omitted) |
description | string | No | Group description (max 500 chars) |
is_private | boolean | No | Whether the group is private |
color | string | No | Display color (max 20 chars) |
Response (201 Created)
{
"group": {
"id": "uuid",
"name": "Engineering",
"slug": "engineering",
...
}
}Returns 409 Conflict if a group with the same slug already exists.
/groups/:id
Get a single group with its members.
Response
{
"group": {
"id": "uuid",
"name": "Engineering",
"slug": "engineering",
"members": [
{ "user_id": "uuid", "permission": "admin" }
],
...
}
}/groups/:id
Update a group. Requires admin scope and group admin permission.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Updated group name |
description | string | No | Updated description |
is_private | boolean | No | Updated privacy setting |
color | string | No | Updated display color |
/groups/:id
Delete a group. Requires admin scope and group admin permission. Default groups cannot be deleted.
Response
{
"deleted": true
}Admin
Administrative endpoints for org owners and admins.
/admin/tune-capture
Fetch heuristic effectiveness metrics, compute optimized capture thresholds, and save them to the org settings. The thresholds control how aggressively session finalization promotes events to insights. Requires admin or owner role.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
days | number | No | Lookback window for effectiveness metrics (default 30, max 365) |
Response
{
"effectiveness": [
{
"heuristic_name": "iterative_edits",
"promoted_count": 12,
"helpful_count": 8,
"unhelpful_count": 1,
"ignored_count": 3,
"effectiveness": 0.67
}
],
"old_thresholds": { ... },
"new_thresholds": { ... },
"days": 30
}/provision
Returns setup commands and org information for the authenticated user. Used by the dashboard Getting Started flow. Authenticated via browser session (not API key).
Response
{
"commands": {
"init": "npx @surchin/surchin init",
"plugin": "claude plugin install @surchin/surchin"
},
"org": {
"name": "My Org",
"slug": "my-org"
}
}Dashboard
Internal API routes used by the Surchin dashboard. Authenticated via browser session (Supabase Auth), not API key.
/dashboard/sessions/:id
Returns full session detail including metadata, events, turn summaries, and any insights promoted from session events.
Response
{
"session": {
"id": "uuid",
"session_id": "client-session-id",
"title": "Feature work",
"summary": "Session lasted 45 minutes...",
"handoff_note": "Need to finish tests...",
"started_at": "2026-03-29T10:00:00Z",
"ended_at": "2026-03-29T10:45:00Z",
"event_count": 24,
"turn_count": 3,
"sensed_count": 5,
"deposited_count": 2,
"repo_id": "owner/repo"
},
"events": [
{
"id": "uuid",
"event_type": "edit",
"tool_name": "Edit",
"file_paths": ["src/auth.ts"],
"summary": "Updated auth validator",
"created_at": "2026-03-29T10:05:00Z",
"promoted_to": null
}
],
"turns": [
{
"turn_number": 1,
"summary": "Modified: src/auth.ts. edit: 3",
"events_count": 5,
"files_modified": ["src/auth.ts"],
"tests_run": false,
"tests_passed": null,
"tests_failed": null,
"created_at": "2026-03-29T10:15:00Z"
}
],
"promoted_insights": [
{
"id": "uuid",
"kind": "SOLUTION",
"summary": "Test failure resolved...",
"strength_raw": 10.0,
"status": "draft"
}
]
}/dashboard/sessions/:id/promote
Manually promote a session event to a full insight via the deposit pipeline. The user supplies edited content, kind, and optional metadata.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
event_id | string | Yes | UUID of the session event to promote |
content | string | Yes | Edited content for the insight (max 5000 chars) |
kind | string | Yes | SOLUTION, PATTERN, PITFALL, CONTEXT, WORKFLOW, DEPENDENCY |
file_patterns | string[] | No | File path patterns to anchor to |
tags | string[] | No | Categorization tags |
error_signature | string | No | Error message for fingerprinting |
Response
{
"insight": {
"id": "uuid",
"kind": "SOLUTION",
"status": "draft",
"strength_raw": 10.0
}
}Returns 409 if the event has already been promoted to an insight.
/dashboard/roi
Returns impact metrics for the organization. Powered by a server-side RPC.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
days | number | No | Lookback window in days (default 7, max 90) |
Response
Returns the result of the get_roi_metrics RPC. Shape depends on the database function implementation.
Enterprise Bulk Ingestion API
Import knowledge from existing documentation, runbooks, incident reports, and post-mortems. Bulk ingest thousands of entries with automatic deduplication and tagging.
Coming soon on Enterprise plans.