handoff-it

REST API

Everything the panel reads, the API reads: projects, sessions, messages and memories. Base URL: https://handoff-it.com/api — JSON in and out.

Authentication

Use an API key in the header (create one at Dashboard → API & MCP):

Authorization: Bearer hof_your_key_here

Example: search and read a conversation

# 1. Find the moment curl "https://handoff-it.com/api/search/conversations?query=stripe+webhook" -H "Authorization: Bearer hof_YOUR_KEY" # 2. Open the surrounding messages (hit carries sessionId + srcOffset) curl "https://handoff-it.com/api/sessions/SESSION_ID/messages?fromOffset=OFFSET&direction=newer" -H "Authorization: Bearer hof_YOUR_KEY"

Endpoints

MethodRouteDescription
POST/api/ingest/sessionsUpserts one conversation (unique per user+tool+externalId) and answers the resume offset — the server is the source of truth for how far a session is archived.
{ "tool": "claude_code", "externalId": "…", "title?": "…", "cwd?": "…", "gitOriginUrl?": "…" }
POST/api/ingest/sessions/:id/chunksUploads one raw gzip chunk (body = gzip bytes; metadata in x-src-byte-start/-end, x-payload-sha256, x-line-count headers). Idempotent: identical re-uploads answer 200 duplicate; a grown same-start span is prefix-merged; a rewritten file gets 409 divergent_chunk.
GET/api/projectsLists projects with session/memory counts and last activity.
GET/api/projects/:id/sessionsThe project's sessions, newest first (cursor pagination).
GET/api/sessions/:id/messagesParsed messages of one session, paged by srcOffset (?fromOffset&direction=older|newer&limit).
GET/api/chunks/:idThe raw (redacted) transcript text of one stored chunk — the deepest drill-down.
GET/api/search/conversationsFull-text search over parsed messages (?query&projectId&tool&limit).
GET/api/memoriesLists/searches saved memories (?q&tag&kind&projectId&limit&cursor).
POST/api/memoriesCreates a memory (note or checkpoint) with optional project/session provenance.
{ "title": "…", "content": "…", "kind?": "checkpoint", "projectId?": "…", "tags?": ["…"] }
GET/api/meCurrent plan and usage (storage, projects, sessions, memories).

Errors

Every failure uses the same envelope:

{ "error": { "code": "quota_exceeded", "message": "Storage limit exceeded: 498.2 MB of 500 MB used on the Free plan..." } }
StatusCodeWhen
401unauthorized / invalid_api_keyMissing header, invalid or revoked key
402quota_exceeded / plan_requiredPlan quota reached or paid-plan feature
404not_foundResource doesn't exist or belongs to another user
409divergent_chunkDivergent chunk (source file rewritten)
400validation_errorInvalid request body

Limits

Storage (memory bodies + the compressed archive, shared per account) and seats vary by plan — see the plans. Ingest chunks up to 4 MB gzip.