POST /api/gather
First-party Smart Paste endpoint. The Squire reads raw text — meeting notes, chat dumps, email threads — and returns one or more Draft Shrubbery candidates with confidence levels. The caller (the in-app Capture surface) chooses which draft(s) to save.
/api/gather is not part of the public webhook surface. It authenticates via the user's Supabase session cookie, not a Bearer token, and there is no programmatic path to it. External integrations should call POST /api/v1/inbox instead.
⚠️ Try-it caveat. Sprint 37b enabled Scalar's interactive Try-it client on
/api-reference. Firing the gather operation from there sends a real request through your active session — which consumes a real BYOK token call against your nominated provider (OpenAI / Anthropic). Each try-it execution costs you the same as a Smart Paste from inside the app. The inbox + sync operations have no per-request cost (just a database write), so try-it is free-to-explore there.
Quick start
The endpoint is consumed by the in-app Smart Paste surface; direct curl calls require a valid session cookie. For programmatic testing during development:
curl -X POST http://localhost:3000/api/gather \
-H "Cookie: sb-access-token=$SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"text": "Alice, please ship the Q3 report by Friday. Bob can review."
}'A successful response is 200 OK with a drafts array, the upstream model name, and token usage as reported by the provider.
Reference
- Try it interactively:
/api-reference#tag/capture/post-api-gather— Scalar's sample switcher (curl / TypeScript / Python / Ruby / Go) + Test Request client. See the BYOK-cost caveat above before firing the test client. - OpenAPI JSON:
content/docs/_generated/openapi.json— auto-emitted from Zod, no manual drift.
Notes
- BYOK required. The endpoint resolves the caller's stored provider key (OpenAI or Anthropic) and calls the upstream LLM with that key. If no key is configured,
400 no_byok_keyis returned with a message directing the user to/settings/integrations. There is no platform-side fallback after Sprint 14 — this is a load-bearing privacy property, not a billing optimisation. - No row written.
/api/gatheronly extracts and returns drafts. Persisting a draft as a Shrubbery row is a separate step in the Capture flow (see Capture Flow). - Rate limits. Per-user limits via Upstash Ratelimit. On exceed,
429 rate_limitedis returned with aRetry-Afterheader in seconds. The limit window and burst are environment-configured; the response message rounds up to whole minutes for human display. - Upstream failures. If the provider returns an error (invalid key, quota exhausted, model unavailable),
502 upstream_failureis returned with the provider's message surfaced verbatim. Treat this as an opaque debugging string, not a stable error code. - No prompt injection mitigations beyond the system prompt. The extracted output is structured JSON validated against
DraftShrubberiesResponse; any extraction the model refuses to make returnsdrafts: []rather than an error.
Last updated: 17 May 2026