Skip to main content

API Reference

The Surchin REST API lets you deposit, query, and reinforce insights programmatically.

Base URL

https://getsurch.in/api/v1

Authentication

All endpoints except /health require an API key in the Authorization header:

Authorization: Bearer sk_your_api_key

Error Format

{
  "error": {
    "code": "string",
    "message": "string"
  }
}
GET

/health

Health check endpoint. No authentication required.

Response

{
  "status": "ok",
  "service": "surchin",
  "version": "0.1.0",
  "timestamp": "2026-03-01T00:00:00.000Z"
}
POST

/sense

Query the knowledge substrate. Required scope: sense

Request Body

FieldTypeRequiredDescription
querystringYesNatural-language search query
file_contextstring[]NoFiles being worked on (boosts locality)
symbol_contextstring[]NoSymbols being worked on
tag_contextstring[]NoTags to filter/boost
error_signaturestringNoRaw error text for fingerprint matching
kindsInsightKind[]NoFilter to specific kinds
limitnumberNoMax results (default 3, max 10)
repo_idstringNoRepository identifier
session_idstringNoSession ID for session-scoped queries
depthinteger (0-2)NoRetrieval depth: 0=topic summaries, 1=top insight per cluster, 2=full results (default 2)
cluster_idstringNoFilter results to a specific topic cluster
group_idsstring[]NoFilter 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
}
POST

/deposit

Deposit an insight into the knowledge substrate. Required scope: deposit

Request Body

FieldTypeRequiredDescription
kindInsightKindYesSOLUTION, PATTERN, PITFALL, CONTEXT, WORKFLOW, DEPENDENCY
contentstringYesFull text of the knowledge
summarystringNoOne-line summary (auto-generated if omitted)
error_signaturestringNoRaw error text for fingerprinting
file_patternsstring[]NoFile paths to anchor to
symbol_namesstring[]NoSymbol names to anchor to
tagsstring[]NoCategorization tags
idempotency_keystringNoClient-provided dedup key
repo_idstringNoRepository identifier
session_idstringNoSession ID to associate the deposit with
group_idstring (UUID)NoScope 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
}
POST

/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.

FieldTypeRequiredDescription
insight_idstringOne of*ID of a single insight to rate
insight_idsstring[]One of*IDs of multiple insights to rate
signal_typestringYesPOSITIVE, NEGATIVE, HUMAN_UPVOTE, HUMAN_DOWNVOTE, AUTO_DECAY, SENSE_RETURN
contextstringNoOptional context about why this rating was given
session_idstringNoSession context
sense_batch_idstringNoLink reinforcement to a specific query batch
skill_idstringNoSkill being rated
skill_feedbackstringNo"followed" or "dismissed"
repo_idstringNoRepository 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"
}
POST

/friction

Get a friction report showing recurring errors and module hotspots. Required scope: sense

Request Body

FieldTypeRequiredDescription
error_textstringYesError text to analyze
file_pathstringNoScope report to a specific file
repo_idstringNoRepository identifier
time_range_daysnumberNoLookback 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.

POST

/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

FieldTypeRequiredDescription
tool_namestringYesName of the tool that produced this event
event_typestringYesOne of: edit, write, test, build, git, migration, error
summarystringYesShort description of the event (max 2000 chars)
content_hashstringYesClient-provided hash for deduplication within a session
session_idstringYesClient session identifier. Session is auto-created if it does not exist.
file_pathsstring[]NoFile paths associated with the event
raw_inputstringNoRaw tool input (max 500 chars)
raw_outputstringNoRaw tool output (max 500 chars)
repo_idstringNoRepository 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".

POST

/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

FieldTypeRequiredDescription
session_idstringYesClient session identifier
repo_idstringNoRepository 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.

POST

/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

FieldTypeRequiredDescription
session_idstringYesClient session identifier
repo_idstringNoRepository 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):

HeuristicInsight KindTrigger
iterative_editsPATTERNFile edited N+ times in one session
test_fixSOLUTIONTest failure followed by edits followed by test pass
recurring_errorPITFALLSame 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.

GET

/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

ParamTypeRequiredDescription
repo_idstringNoRepository 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.

GET

/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
    }
  ]
}
POST

/groups

Create a new group. Requires admin scope and org admin/owner role.

Request Body

FieldTypeRequiredDescription
namestringYesGroup name (max 100 chars)
slugstringNoURL-safe slug (auto-generated from name if omitted)
descriptionstringNoGroup description (max 500 chars)
is_privatebooleanNoWhether the group is private
colorstringNoDisplay 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.

GET

/groups/:id

Get a single group with its members.

Response

{
  "group": {
    "id": "uuid",
    "name": "Engineering",
    "slug": "engineering",
    "members": [
      { "user_id": "uuid", "permission": "admin" }
    ],
    ...
  }
}
PATCH

/groups/:id

Update a group. Requires admin scope and group admin permission.

Request Body

FieldTypeRequiredDescription
namestringNoUpdated group name
descriptionstringNoUpdated description
is_privatebooleanNoUpdated privacy setting
colorstringNoUpdated display color
DELETE

/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.

POST

/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

FieldTypeRequiredDescription
daysnumberNoLookback 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
}
GET

/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.

GET

/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"
    }
  ]
}
POST

/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

FieldTypeRequiredDescription
event_idstringYesUUID of the session event to promote
contentstringYesEdited content for the insight (max 5000 chars)
kindstringYesSOLUTION, PATTERN, PITFALL, CONTEXT, WORKFLOW, DEPENDENCY
file_patternsstring[]NoFile path patterns to anchor to
tagsstring[]NoCategorization tags
error_signaturestringNoError 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.

GET

/dashboard/roi

Returns impact metrics for the organization. Powered by a server-side RPC.

Query Parameters

ParamTypeRequiredDescription
daysnumberNoLookback 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.