Skip to content

Latest commit

 

History

History
1375 lines (1072 loc) · 30.3 KB

File metadata and controls

1375 lines (1072 loc) · 30.3 KB

HiveShare API Reference

Verification: All curl examples in this document are tested by scripts/test-api-examples.sh. If you add or modify an endpoint or example, update the script to match and run it to verify:

./scripts/test-api-examples.sh

Table of Contents


Overview

Base URL: http://localhost:8080 (configurable via BASE_URL env var)

Authentication: All endpoints except /health, /api/v1/auth/register, /api/v1/invitations/{token}/accept, and /api/v1/auth/service-accounts/token require a Bearer token in the Authorization header. Two token formats are accepted:

Authorization: Bearer hvs_<token>   # personal user API key
Authorization: Bearer <jwt>         # service account JWT (two-dot format)

Service account JWTs are obtained by calling POST /auth/service-accounts/token with an hvsa_ service account key.

Rate limiting: Per-endpoint limits, keyed by API key (or IP for unauthenticated requests). Returns 429 when exceeded.

Endpoint group Limit
POST /auth/register, invitation accept 10 req/min by IP
Hive writes (create, update, delete, rollback, copy, snapshot ops) 20 req/min by key
POST /hives/search 30 req/min by key
All other authenticated endpoints 200 req/min by key (global safety net)

Body size limit: 1 MB max request body.

Error format: All errors return JSON:

{"error": "description of the problem"}

Health

GET /health

GET /health

Auth: None

Response: 200 OK

{
  "status": "ok",
  "db": "ok",
  "redis": "ok",
  "commit": "d61ca5d",
  "build_time": "2026-07-22T20:13:28Z"
}

Returns 503 with "status": "degraded" if Postgres or Redis is unreachable.

Example:

curl http://localhost:8080/health

Auth

POST Register

POST /api/v1/auth/register

Auth: None

Request body:

{
  "email": "user@example.com",
  "name": "Display Name"
}

Response: 201 Created

{
  "id": "uuid",
  "email": "user@example.com",
  "name": "Display Name",
  "api_key": "hvs_<48 hex chars>",
  "created_at": "2026-07-22T10:00:00Z"
}

The api_key is returned only once. It is stored as a SHA-256 hash and cannot be retrieved again.

Error responses:

  • 400 — email or name missing
  • 409 — email already registered

Example:

curl -X POST http://localhost:8080/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"alice@example.com","name":"Alice"}'

GET Whoami

GET /api/v1/auth/whoami

Auth: Required

Response: 200 OK

{
  "id": "uuid",
  "email": "user@example.com",
  "name": "Display Name",
  "created_at": "2026-07-22T10:00:00Z"
}

Error responses:

  • 401 — missing or invalid API key

Example:

curl http://localhost:8080/api/v1/auth/whoami \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

POST SA Token

POST /api/v1/auth/service-accounts/token

Auth: Bearer hvsa_<key> — service account key (not a user hvs_ key). No user session required.

Rate limit: 20 req/min by key.

Exchanges a long-lived service account key for a short-lived JWT. Use the returned JWT as a normal Bearer token for subsequent API calls. JWT lifetime is controlled by SA_TOKEN_TTL_MINUTES (default 15 minutes).

Response: 200 OK

{
  "token": "<signed-jwt>",
  "expires_in": 900,
  "role": "view"
}

Error responses:

  • 401 — missing, invalid, or unknown hvsa_ key

Example:

# Exchange service account key for a JWT
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/service-accounts/token \
  -H "Authorization: Bearer hvsa_YOUR_SA_KEY" | jq -r .token)

# Use the JWT for a search
curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/search \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query":"CI status"}'

Service Accounts

Service accounts are non-human identities for CI pipelines and automated agents. They use hvsa_ prefixed keys (SHA-256 hashed at rest) and exchange them for short-lived JWTs via POST /auth/service-accounts/token. No invite flow is required — an admin pre-creates the account.

GET Service Accounts

GET /api/v1/hiveshares/{id}/service-accounts

Auth: Required Access: role all

Response: 200 OK

[
  {
    "id": "uuid",
    "hiveshare_id": "uuid",
    "name": "ci-pipeline",
    "role": "view",
    "created_at": "2026-07-31T10:00:00Z",
    "last_used_at": "2026-07-31T14:23:00Z"
  }
]

Example:

curl http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/service-accounts \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

POST Create Service Account

POST /api/v1/hiveshares/{id}/service-accounts

Auth: Required Access: role all

Request body:

{
  "name": "ci-pipeline",
  "role": "view"
}

role is all or view. Defaults to view when omitted.

Response: 201 Created — the key field is the cleartext hvsa_ key, returned once only. Store it securely.

{
  "id": "uuid",
  "hiveshare_id": "uuid",
  "name": "ci-pipeline",
  "role": "view",
  "created_at": "2026-07-31T10:00:00Z",
  "key": "hvsa_<48 hex chars>"
}

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/service-accounts \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci-pipeline","role":"view"}'

DELETE Service Account

DELETE /api/v1/hiveshares/{id}/service-accounts/{saId}

Auth: Required Access: role all

Response: 204 No Content

Error responses:

  • 404 — service account not found

Example:

curl -X DELETE http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/service-accounts/SA_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

Hiveshares

POST Create Hiveshare

POST /api/v1/hiveshares

Auth: Required

Request body:

{
  "name": "Sprint 42",
  "description": "Shared context for sprint 42"
}

Response: 201 Created

{
  "id": "uuid",
  "name": "Sprint 42",
  "description": "Shared context for sprint 42",
  "owner_id": "uuid",
  "settings": {},
  "created_at": "2026-07-22T10:00:00Z",
  "updated_at": "2026-07-22T10:00:00Z",
  "role": "all",
  "member_count": 1
}

Error responses:

  • 400 — name missing

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Sprint 42","description":"Shared context"}'

GET List Hiveshares

GET /api/v1/hiveshares

Auth: Required

Returns all hiveshares the authenticated user is a member of.

Response: 200 OK

[
  {
    "id": "uuid",
    "name": "Sprint 42",
    "description": "...",
    "owner_id": "uuid",
    "role": "all",
    "member_count": 3,
    "created_at": "2026-07-22T10:00:00Z",
    "updated_at": "2026-07-22T10:00:00Z"
  }
]

Example:

curl http://localhost:8080/api/v1/hiveshares \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

GET Hiveshare

GET /api/v1/hiveshares/{id}

Auth: Required Access: Must be a member

Response: 200 OK

{
  "id": "uuid",
  "name": "Sprint 42",
  "description": "...",
  "owner_id": "uuid",
  "settings": {},
  "role": "all",
  "member_count": 3,
  "created_at": "2026-07-22T10:00:00Z",
  "updated_at": "2026-07-22T10:00:00Z"
}

Error responses:

  • 404 — hiveshare not found or user is not a member

Example:

curl http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

PUT Update Hiveshare

PUT /api/v1/hiveshares/{id}

Auth: Required Access: CanWrite (role all)

Request body:

{
  "name": "New Name",
  "description": "Updated description"
}

Response: 200 OK (returns the updated hiveshare)

Error responses:

  • 403 — view-only access

Example:

curl -X PUT http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Renamed","description":"Updated"}'

DELETE Hiveshare

DELETE /api/v1/hiveshares/{id}

Auth: Required Access: Owner only (owner_id must match)

Response: 204 No Content

Error responses:

  • 403 — not the owner
  • 404 — hiveshare not found

Example:

curl -X DELETE http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

POST Invite

POST /api/v1/hiveshares/{id}/invite

Auth: Required Access: CanWrite (role all)

Request body:

{
  "email": "bob@example.com",
  "role": "view"
}

role is all (read/write/invite) or view (read-only). Defaults to view when omitted or unrecognised.

Response: 201 Created

{
  "id": "uuid",
  "hiveshare_id": "uuid",
  "email": "bob@example.com",
  "invited_by": "uuid",
  "token": "48-hex-chars",
  "role": "view",
  "status": "pending",
  "created_at": "2026-07-22T10:00:00Z",
  "expires_at": "2026-07-29T10:00:00Z",
  "invite_url": "http://localhost:8080/api/v1/invitations/TOKEN/accept"
}

Invitations expire after 7 days.

Error responses:

  • 400 — email missing
  • 403 — view-only access

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/invite \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"bob@example.com","role":"view"}'

POST Accept Invite

POST /api/v1/invitations/{token}/accept

Auth: None

Request body (optional):

{
  "name": "Bob"
}

If name is omitted, the invited email is used as the display name. If the user does not exist, one is created.

Response: 200 OK

{
  "message": "Welcome to Sprint 42",
  "hiveshare_id": "uuid",
  "user": {
    "id": "uuid",
    "email": "bob@example.com",
    "name": "Bob",
    "api_key": "hvs_...",
    "created_at": "2026-07-22T10:00:00Z"
  }
}

Error responses:

  • 404 — invitation not found
  • 410 — invitation expired or already accepted

Example:

curl -X POST http://localhost:8080/api/v1/invitations/TOKEN/accept \
  -H "Content-Type: application/json" \
  -d '{"name":"Bob"}'

GET Members

GET /api/v1/hiveshares/{id}/members

Auth: Required Access: CanView

Response: 200 OK

[
  {
    "hiveshare_id": "uuid",
    "user_id": "uuid",
    "name": "Alice",
    "email": "alice@example.com",
    "role": "all",
    "joined_at": "2026-07-22T10:00:00Z"
  }
]

Error responses:

  • 403 — not a member

Example:

curl http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/members \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

DELETE Member

DELETE /api/v1/hiveshares/{id}/members/{userId}

Auth: Required Access: CanWrite to remove others; any member can remove themselves

Cannot remove the owner (owner_id).

Response: 204 No Content

Error responses:

  • 403 — view-only trying to remove someone else

Example:

curl -X DELETE http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/members/USER_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

Hives

POST Create Entry

POST /api/v1/hiveshares/{id}/hives

Auth: Required Access: CanWrite

Request body:

{
  "source_type": "jira",
  "source_ref": "PROJ-123",
  "source_url": "https://issues.example.com/PROJ-123",
  "tool": "claude",
  "content": "Analysis of the auth refactor...",
  "summary": "Auth refactor analysis",
  "tags": ["auth", "refactor"],
  "metadata": {"sprint": 42}
}
Field Required Values
source_type Yes jira, github_issue, github_pr, file, url, manual
source_ref Yes Free text (e.g. ticket ID, file path)
content Yes The memory content
tool No claude, cursor, manual (default: manual)
source_url No URL to the source
summary No Short summary
tags No Array of strings
metadata No Arbitrary JSON object
ttl_seconds No Auto-expire after N seconds from now. 0 = never
expires_at No Explicit RFC3339 expiry timestamp. Overrides ttl_seconds if both given

Expired hives (past expires_at) are automatically excluded from all reads and searches. Embedding is generated asynchronously after creation. If the embedding provider is available, the content is embedded synchronously first to check for duplicates; if a near-identical hive already exists for the same source_ref, 409 Conflict is returned instead.

Query parameters:

Param Default Description
dedup_threshold 0 (disabled) Cosine similarity threshold for duplicate detection. When set (e.g. 0.95), embeds the new content synchronously before inserting — adds 200–500ms latency per create. Opt-in only.

Response: 201 Created

{
  "id": "uuid",
  "hiveshare_id": "uuid",
  "user_id": "uuid",
  "user_name": "Alice",
  "source_type": "jira",
  "source_ref": "PROJ-123",
  "source_url": "https://issues.example.com/PROJ-123",
  "tool": "claude",
  "content": "Analysis of the auth refactor...",
  "summary": "Auth refactor analysis",
  "tags": ["auth", "refactor"],
  "metadata": {"sprint": 42},
  "views": 0,
  "reuses": 0,
  "created_at": "2026-07-22T10:00:00Z",
  "updated_at": "2026-07-22T10:00:00Z",
  "expires_at": null
}

Error responses:

  • 400 — content, source_type, or source_ref missing
  • 403 — view-only access
  • 409 — a hive with the same source_ref and similarity ≥ dedup_threshold already exists; body includes {"error":"similar hive already exists","existing":{...},"similarity":0.97}

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"source_type":"jira","source_ref":"PROJ-123","content":"Analysis...","tool":"claude","tags":["auth"]}'

GET List Entries

GET /api/v1/hiveshares/{id}/hives

Auth: Required Access: CanView

Query parameters:

Param Default Description
limit 50 Max entries to return
offset 0 Pagination offset
source_type Filter by source type
source_ref Filter by source reference
tag Filter by tag
tool Filter by tool

List responses omit content to keep payloads small. Use the GET single entry endpoint for full content.

Response: 200 OK

[
  {
    "id": "uuid",
    "hiveshare_id": "uuid",
    "user_id": "uuid",
    "user_name": "Alice",
    "source_type": "jira",
    "source_ref": "PROJ-123",
    "summary": "Auth refactor analysis",
    "tags": ["auth"],
    "views": 5,
    "reuses": 2,
    "created_at": "2026-07-22T10:00:00Z"
  }
]

Example:

curl "http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives?source_type=jira&limit=10" \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

GET Entry

GET /api/v1/hiveshares/{id}/hives/{entryId}

Auth: Required Access: CanView

Returns the full entry including content. Increments view counter.

Response: 200 OK

{
  "id": "uuid",
  "hiveshare_id": "uuid",
  "user_id": "uuid",
  "user_name": "Alice",
  "source_type": "jira",
  "source_ref": "PROJ-123",
  "source_url": "https://...",
  "tool": "claude",
  "content": "Full content text...",
  "summary": "Auth refactor analysis",
  "tags": ["auth"],
  "metadata": {"sprint": 42},
  "views": 6,
  "reuses": 2,
  "created_at": "2026-07-22T10:00:00Z",
  "updated_at": "2026-07-22T10:00:00Z",
  "expires_at": null
}

Error responses:

  • 404 — entry not found

Example:

curl http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/ENTRY_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

PUT Update Entry

PUT /api/v1/hiveshares/{id}/hives/{entryId}

Auth: Required Access: CanWrite

Request body:

{
  "content": "Updated analysis...",
  "summary": "Updated summary",
  "tags": ["auth", "updated"],
  "ttl_seconds": 86400,
  "expires_at": "2026-08-31T00:00:00Z"
}

All fields are optional. Updating content triggers re-embedding. Pass ttl_seconds or expires_at to set or change expiry; omit both to leave the existing expiry unchanged.

Response: 200 OK (returns the updated entry)

Error responses:

  • 403 — view-only access

Example:

curl -X PUT http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/ENTRY_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"Updated analysis...","tags":["auth","updated"]}'

DELETE Entry

DELETE /api/v1/hiveshares/{id}/hives/{entryId}

Auth: Required Access: CanWrite

Response: 204 No Content

Example:

curl -X DELETE http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/ENTRY_ID \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

POST Search

POST /api/v1/hiveshares/{id}/hives/search

Auth: Required Access: CanView

Uses hybrid search when embeddings are enabled: blends cosine similarity and BM25 full-text scores weighted by alpha. Falls back to PostgreSQL full-text when no embedder is configured or embedding fails.

Request body:

{
  "query": "auth refactor approach",
  "source_type": "jira",
  "limit": 10,
  "alpha": 0.7
}
Field Required Default Description
query Yes Search query text
source_type No Filter results by source type
limit No 10 Max results
alpha No 0.7 Blend ratio: 1.0 = pure vector, 0.0 = pure full-text
max_age_seconds No 0 Exclude hives not updated within N seconds. 0 = no filter. Use for volatile state like CI status

Response: 200 OK

{
  "results": [
    {
      "id": "uuid",
      "hiveshare_id": "uuid",
      "user_id": "uuid",
      "user_name": "Alice",
      "source_type": "jira",
      "source_ref": "PROJ-123",
      "content": "Full content...",
      "summary": "...",
      "tags": ["auth"],
      "views": 5,
      "reuses": 2,
      "score": 0.87,
      "created_at": "2026-07-22T10:00:00Z"
    }
  ],
  "count": 1,
  "query": "auth refactor approach",
  "type": "hybrid"
}

The type field is "hybrid" when vector + full-text blending was used, or "fulltext" when falling back.

Error responses:

  • 400 — query missing

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/search \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"auth refactor","limit":5,"alpha":0.7}'

POST Copy Entries

POST /api/v1/hiveshares/{id}/hives/copy

Auth: Required Access: CanWrite on target hiveshare; CanView on source hiveshare(s)

Copies hives (including embeddings) from any accessible hiveshare into the target. Used for rollforward merges after a snapshot restore.

Request body:

{
  "entry_ids": ["uuid-1", "uuid-2"]
}

Response: 201 Created

[
  {
    "id": "new-uuid",
    "hiveshare_id": "target-hiveshare-uuid",
    "content": "Copied content...",
    "source_type": "jira",
    "source_ref": "PROJ-123",
    ...
  }
]

Entries with NULL embeddings are queued for re-embedding.

Error responses:

  • 400 — entry_ids missing or empty

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/TARGET_ID/hives/copy \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"entry_ids":["ENTRY_UUID_1","ENTRY_UUID_2"]}'

History

GET History

GET /api/v1/hiveshares/{id}/hives/{entryId}/history

Auth: Required Access: CanView

Returns version history for a hive, including deleted entries.

Query parameters:

Param Default Description
limit 20 Max versions
offset 0 Pagination offset

Response: 200 OK

[
  {
    "history_id": 42,
    "entry_id": "uuid",
    "hiveshare_id": "uuid",
    "user_id": "uuid",
    "action": "update",
    "content": "Updated content...",
    "summary": "Updated",
    "has_embedding": true,
    "tags": ["auth"],
    "source_type": "jira",
    "source_ref": "PROJ-123",
    "tool": "claude",
    "recorded_at": "2026-07-22T10:05:00Z"
  },
  {
    "history_id": 41,
    "entry_id": "uuid",
    "action": "insert",
    "content": "Original content...",
    "has_embedding": true,
    "recorded_at": "2026-07-22T10:00:00Z"
  }
]

action is one of: insert, update, delete.

Example:

curl "http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/ENTRY_ID/history?limit=10" \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

POST Rollback

POST /api/v1/hiveshares/{id}/hives/{entryId}/rollback

Auth: Required Access: CanWrite

Restores a hive to a prior version. If the history version has an embedding, it is restored directly. If not, a re-embed job is enqueued.

Request body:

{
  "history_id": 41
}

Response: 200 OK (returns the restored entry)

Error responses:

  • 400 — history_id missing
  • 404 — entry or history version not found

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/ENTRY_ID/rollback \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"history_id":41}'

POST Undelete

POST /api/v1/hiveshares/{id}/hives/undelete

Auth: Required Access: CanWrite

Restores a deleted hive from its history record. The history version must have action: "delete".

Request body:

{
  "history_id": 43
}

Response: 201 Created (returns the restored entry with its original ID)

Error responses:

  • 400 — history_id missing
  • 404 — history version not found or not a delete action

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/hives/undelete \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"history_id":43}'

Snapshots

POST Create Snapshot

POST /api/v1/hiveshares/{id}/snapshots

Auth: Required Access: CanWrite

Creates a point-in-time snapshot of all hives in the hiveshare, including their embeddings.

Request body:

{
  "name": "before-cleanup",
  "description": "Snapshot before removing stale entries"
}
Field Required Description
name Yes Snapshot name
description No Description

Response: 201 Created

{
  "snapshot_id": 1,
  "hiveshare_id": "uuid",
  "created_by": "uuid",
  "name": "before-cleanup",
  "description": "Snapshot before removing stale entries",
  "entry_count": 15,
  "created_at": "2026-07-22T10:00:00Z"
}

Error responses:

  • 400 — name missing

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/snapshots \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"before-cleanup","description":"Snapshot before removing stale entries"}'

GET List Snapshots

GET /api/v1/hiveshares/{id}/snapshots

Auth: Required Access: CanView

Response: 200 OK

[
  {
    "snapshot_id": 1,
    "hiveshare_id": "uuid",
    "created_by": "uuid",
    "name": "before-cleanup",
    "entry_count": 15,
    "created_at": "2026-07-22T10:00:00Z"
  }
]

Example:

curl http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/snapshots \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

GET Snapshot

GET /api/v1/hiveshares/{id}/snapshots/{snapshotId}

Auth: Required Access: CanView

Returns snapshot metadata and the list of frozen entries.

Response: 200 OK

{
  "snapshot": {
    "snapshot_id": 1,
    "hiveshare_id": "uuid",
    "created_by": "uuid",
    "name": "before-cleanup",
    "entry_count": 15,
    "created_at": "2026-07-22T10:00:00Z"
  },
  "entries": [
    {
      "entry_id": "uuid",
      "content": "...",
      "summary": "...",
      "has_embedding": true,
      "tags": ["auth"],
      "source_type": "jira",
      "source_ref": "PROJ-123",
      "tool": "claude"
    }
  ]
}

Error responses:

  • 404 — snapshot not found

Example:

curl http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/snapshots/1 \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

POST Restore Snapshot

POST /api/v1/hiveshares/{id}/snapshots/{snapshotId}/restore

Auth: Required Access: CanWrite

Creates a new hiveshare from the snapshot. The original hiveshare is not modified. Entries with embeddings are copied as-is; entries without embeddings are queued for re-embedding.

Request body (optional):

{
  "name": "Sprint 42 (restored)"
}

If name is omitted, defaults to "(restored)".

Response: 201 Created

{
  "hiveshare": {
    "id": "new-uuid",
    "name": "Sprint 42 (restored)",
    "owner_id": "uuid",
    "role": "all",
    "member_count": 1,
    ...
  },
  "entries_restored": 15
}

Example:

curl -X POST http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/snapshots/1/restore \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Sprint 42 (restored)"}'

DELETE Snapshot

DELETE /api/v1/hiveshares/{id}/snapshots/{snapshotId}

Auth: Required Access: CanWrite

Deletes the snapshot and all its frozen entries.

Response: 204 No Content

Example:

curl -X DELETE http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/snapshots/1 \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

Metrics

GET Hiveshare Metrics

GET /api/v1/hiveshares/{id}/metrics

Auth: Required Access: CanView

Response: 200 OK

{
  "hiveshare": {
    "name": "Sprint 42",
    "description": "...",
    "member_count": 3
  },
  "memory": {
    "total_entries": 25,
    "by_source_type": {"jira": 15, "github_pr": 8, "manual": 2},
    "by_tool": {"claude": 20, "cursor": 3, "manual": 2},
    "unique_sources": 12
  },
  "collaboration": {
    "total_views": 150,
    "total_reuses": 45,
    "reuse_rate": 0.3,
    "top_contributors": [
      {"user_id": "uuid", "name": "Alice", "entries": 15, "reuses_received": 30}
    ]
  },
  "coverage": {
    "jira_refs_with_memory": 10,
    "github_refs_with_memory": 5
  },
  "activity": {
    "last_7d_adds": 8,
    "last_7d_searches": 25,
    "active_users_7d": 3
  }
}

Example:

curl http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/metrics \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

GET User Metrics

GET /api/v1/metrics/me

Auth: Required

Response: 200 OK

{
  "total_entries": 42,
  "total_searches": 120,
  "hiveshares_owned": 3,
  "hiveshares_joined": 5,
  "total_reuses_given": 30
}

Example:

curl http://localhost:8080/api/v1/metrics/me \
  -H "Authorization: Bearer hvs_YOUR_API_KEY"

SSE Stream

GET Stream

GET /api/v1/hiveshares/{id}/stream

Auth: Required Access: CanView

Opens a long-lived Server-Sent Events connection. Events are published via Redis pub/sub and fanned out to all connected clients.

Headers:

Accept: text/event-stream
Cache-Control: no-cache

Event types:

Event Payload When
connected {"hiveshare_id": "uuid"} Initial connection
hive_added Full hive Entry created
hive_updated Full hive Entry updated
hive_rolled_back Full hive Entry rolled back
hive_undeleted Full hive Entry restored from deletion

Keepalive comments (: keepalive) are sent every 25 seconds.

Example:

curl -N http://localhost:8080/api/v1/hiveshares/HIVESHARE_ID/stream \
  -H "Authorization: Bearer hvs_YOUR_API_KEY" \
  -H "Accept: text/event-stream"