{"openapi":"3.1.0","info":{"title":"Scribe API","version":"1.0.0","description":"Scribe REST API v1. Session-authenticated (web + desktop sync); it does NOT accept OAuth access tokens. Agents should use the MCP server at https://getscribe.ai/api/mcp (see https://getscribe.ai/auth.md and https://getscribe.ai/docs/api).\n\nVersioning: the current surface is v1. Prefer https://getscribe.ai/api/v1/*. Unversioned https://getscribe.ai/api/* is an alias of v1 and will remain until a v2 exists. Breaking changes ship as /api/v2/. Responses include API-Version: 1.\n\nDeprecation: routes or fields that will be removed are marked with the Deprecation header (RFC 9745) and a Sunset date (RFC 8594) at least 90 days in advance. There is no deprecated surface in v1 today.\n\nRate limits: 120 requests per 60 seconds per client on REST. Responses include RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, and RateLimit. 429 responses also include Retry-After.","contact":{"url":"https://getscribe.ai/contact"}},"servers":[{"url":"https://getscribe.ai/api/v1","description":"Scribe REST API v1 (current). Preferred."},{"url":"https://getscribe.ai/api","description":"Unversioned alias of v1."}],"security":[{"sessionAuth":[]}],"components":{"schemas":{"Error":{"type":"object","additionalProperties":true,"minProperties":1,"anyOf":[{"required":["error"]},{"required":["message"]}],"properties":{"error":{"type":"string","description":"Machine-readable code (NOT_FOUND, UNAUTHORIZED, …) or, on older handlers, the human explanation."},"message":{"type":"string","description":"Human-readable explanation the agent can surface."},"details":{"type":"object","additionalProperties":true,"description":"Optional structured context (field, resource, id)."},"code":{"type":"string","description":"Alternate machine-readable code on some ingest routes."},"hint":{"type":"string","description":"Optional recovery hint (upload/org context)."}}}},"parameters":{"ApiVersion":{"name":"API-Version","in":"header","required":false,"schema":{"type":"string","enum":["1"],"default":"1"},"description":"Scribe REST API version. Current value is 1. Omitted requests are treated as v1."}},"headers":{"API-Version":{"description":"Version of the API that produced this response.","schema":{"type":"string","enum":["1"]}},"RateLimit-Limit":{"description":"Maximum requests permitted in the current window.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests remaining in the current window.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Unix timestamp when the current window resets.","schema":{"type":"integer"}},"RateLimit":{"description":"IETF RateLimit header (limit, remaining, reset).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before retrying a 429.","schema":{"type":"integer"}},"Deprecation":{"description":"RFC 9745. Present when the resource is deprecated.","schema":{"type":"string"}},"Sunset":{"description":"RFC 8594 HTTP-date after which the resource may be removed.","schema":{"type":"string"}}},"securitySchemes":{"sessionAuth":{"type":"apiKey","in":"cookie","name":"better-auth.session_token","description":"Better Auth session (cookie, or a device-auth Bearer token). The /api/* routes do not accept OAuth access tokens — agents use the MCP server at /api/mcp instead."}},"responses":{"BadRequest":{"description":"The request was malformed or failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing or invalid credential.","headers":{"WWW-Authenticate":{"schema":{"type":"string"},"description":"Bearer challenge with resource_metadata pointing at /.well-known/oauth-protected-resource"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Authenticated but not allowed (wrong org, missing capability, or not admitted to the beta).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The requested resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server failure. Retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/health":{"get":{"operationId":"getHealth","summary":"Service health check","security":[],"responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/timeline":{"get":{"operationId":"listTimelineEvents","summary":"Query timeline work-evidence events (dots)","parameters":[{"name":"start","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"projectIds","in":"query","description":"Comma-separated project IDs","schema":{"type":"string"}},{"name":"sources","in":"query","description":"Comma-separated source types (git, claude, cursor…)","schema":{"type":"string"}},{"name":"deviceIds","in":"query","schema":{"type":"string"}},{"name":"teamId","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Matching timeline events","content":{"application/json":{"schema":{"type":"array"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/timeline/latest":{"get":{"operationId":"getLatestTimelineEvent","summary":"Most recent timeline event timestamp","responses":{"200":{"description":"Latest event","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/timeline/{id}":{"get":{"operationId":"getTimelineEvent","summary":"Fetch a single timeline event","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The event","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/projects/overview":{"get":{"operationId":"getProjectsOverview","summary":"List project groups with rollup stats","responses":{"200":{"description":"Project groups","content":{"application/json":{"schema":{"type":"array"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/projects":{"post":{"operationId":"createProject","summary":"Create a project without a discovered root","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":120},"color":{"type":"string","maxLength":32}}}}}},"responses":{"200":{"description":"Created project","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/clients":{"get":{"operationId":"listClients","summary":"List invoice clients","responses":{"200":{"description":"Clients","content":{"application/json":{"schema":{"type":"array"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createClient","summary":"Create an invoice client","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Created client","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/invoices":{"get":{"operationId":"listInvoices","summary":"List invoices","responses":{"200":{"description":"Invoices","content":{"application/json":{"schema":{"type":"array"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createInvoice","summary":"Create an invoice","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Created invoice","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/search":{"get":{"operationId":"searchEvents","summary":"Full-text search over timeline events","parameters":[{"name":"q","in":"query","required":true,"description":"Search query (min 2 chars)","schema":{"type":"string","minLength":2}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}},{"name":"start","in":"query","schema":{"type":"string"}},{"name":"end","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/upload":{"post":{"operationId":"uploadEvents","summary":"Ingest timeline events from a local device","description":"Used by the Scribe desktop app / CLI to push locally-scanned work evidence to the hub. Accepts an API key or device-auth bearer.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Upload accepted","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/chat":{"post":{"operationId":"chat","summary":"Conversational interface over your Scribe data","x-scribe-flag":"ai-features-enabled","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Streamed chat response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"AI features are disabled in this environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}}}}