Scrybert Developer API

Reference for the Scrybert Developer API.

Overview

The Developer API provides programmatic access to a Scrybert account's conversation data and to-do list. For a description of the underlying product behavior, see Features and How It Works. Access to this API is governed by a developer key, distinct from the account's primary credential and limited to the scope described in this document.

Four components are exposed:

Authentication

All Developer API requests authenticate with a developer key. One key exists per account.

Getting a key

  1. In the app: Settings > Developer.
  2. Tap Generate Key.
  3. The full key is shown once, at generation time. Copy it immediately — it cannot be viewed again.

Generating a new key immediately invalidates the previous one. The server stores only the key's SHA-256 hash and its last four characters, so if the full value is lost, generate a new one rather than trying to recover it.

Key format:

scry_dev_<43 characters, URL-safe base64>

Requests authenticate with a bearer token:

Authorization: Bearer scry_dev_<key>

Key comparison is performed in constant time against the stored hash.

Retention requirement

Key generation and all authenticated requests, except webhook delivery, require the account's Cloud Backup (data retention) setting to be 30 days or longer. At a Cloud Backup setting of 0 days, these requests return 403:

{"detail": "Turn Cloud Backup on for 30 days or longer to use this."}

Webhooks are exempt from this requirement.

MCP server

Endpointhttps://api.scrybert.com/v1/mcp
MethodPOST only. GET returns 405.
TransportMCP Streamable HTTP. JSON-RPC 2.0. One response per request; no server-initiated stream.
Protocol versions2025-06-18, 2025-03-26, 2024-11-05
AuthenticationAuthorization: Bearer <developer key>

Seven tools are exposed. Six are read-only; one performs a write.

ToolRead-onlyDescriptionParameters
list_conversationsYes Returns conversations in reverse chronological order: title, blurb, tags, topics, people, things. tag (string, exact match, case-insensitive), since, until (date), topic (string, partial match), person, thing (string), limit (integer, max 50)
get_conversationYes Returns one conversation: summary, action items, list items, and optionally the transcript. session_id (string, required), include_transcript (boolean)
searchYes Returns conversations matching a query string, with a text snippet per match. query (string, required, min 2 characters), include_transcripts (boolean), limit (integer, max 50)
tallyYes Returns conversation counts grouped by topic, person, or thing, in descending order. kind (enum: topics, people, things, required), since, until (date)
list_tagsYes Returns every tag on the account's conversations, standard and custom, with a conversation count per tag, in descending order. since, until (date)
list_todosYes Returns to-do items in reverse chronological order. status (enum: open, done, all), limit (integer, max 200)
create_todoNo Creates one to-do item. This is the only tool that modifies account data. text (string, required, max 500 characters), due (string, YYYY-MM-DD or YYYY-MM-DDTHH:MM)

A session identifier has the form 20260921-093512, corresponding to the timestamp recording began. Read operations are limited to data retained under the account's Cloud Backup setting. Data outside the scope of this document, including My People, My Things, and Pivotal Moments, is not accessible through this interface.

OAuth authentication, required by claude.ai's and ChatGPT's browser-based connectors, is not implemented. Clients that accept a bearer token directly, including Claude Code, are supported.

Pull conversations by tag

Every conversation carries up to three tags: the standard categories Scrybert assigns (for example Work, Family, Finance) and the account's three custom tags. Where the account holder has changed a conversation's tags in the app, those choices are used. Custom tags are returned under their current names; renaming a custom tag in the app changes it everywhere at once.

List tags

Endpointhttps://api.scrybert.com/v1/developer/tags
MethodGET
AuthenticationAuthorization: Bearer <developer key>
Query parameterssince, until (optional, YYYY-MM-DD)
{
  "tags": [ { "tag": string, "conversations": integer }, ... ]
}

Conversations by tag

Endpointhttps://api.scrybert.com/v1/developer/conversations
MethodGET
AuthenticationAuthorization: Bearer <developer key>
Query parameters tag (optional, exact match, case-insensitive; omit for all conversations), since, until (optional, YYYY-MM-DD), limit (optional, default 20, max 100), full (optional, true adds summary, action items and list items), transcript (optional, true also adds the transcript)

Example:

curl "https://api.scrybert.com/v1/developer/conversations?tag=Work&full=true" \
  -H "Authorization: Bearer scry_dev_<key>"

Response (status 200), newest first:

{
  "tag": string or null,
  "total": integer,
  "returned": integer,
  "conversations": [
    {
      "session_id": string,
      "when": string,
      "title": string,
      "blurb": string,
      "tags": [string],
      "topics": [string],
      "people": [string],
      "things": [string],
      "action_items": integer, or [string] when full=true,
      "summary": string (Markdown, full=true),
      "list_items": [string] (full=true),
      "transcript": string (transcript=true)
    }
  ]
}

Only conversations retained under the account's Cloud Backup setting are returned. An invalid or missing key returns 401; Cloud Backup off returns 403.

To-do endpoint

Endpointhttps://api.scrybert.com/v1/todos
MethodPOST
AuthenticationAuthorization: Bearer <developer key>

Request body:

{
  "text": string, required, max 500 characters,
  "due": string, optional, "YYYY-MM-DD" or "YYYY-MM-DDTHH:MM",
  "source": string, optional, max 40 characters, default "API",
  "id": string, optional, max 128 characters
}

Response, new item (status 201):

{
  "uid": string,
  "text": string,
  "due": string or null,
  "source": string,
  "created_at": integer (unix ms),
  "duplicate": false
}

If id is supplied and matches a previous request, the endpoint returns status 200 with "duplicate": true and the original item, rather than creating a second item.

An invalid due value returns 422. A missing or empty text value returns 422.

Rate limit: 120 creations per account per hour, tracked in memory. Requests exceeding this limit return 429.

Items created through this endpoint appear on the account's device on the next synchronization cycle, which occurs on application open or at intervals not exceeding 15 minutes.

Webhooks

Four account events are available for subscription. Each event has an independent enabled state and target URL, configured in Settings > Developer.

conversation.summarized
transcript.received
recap.created
todo.created

Payload envelope

{
  "id": string (uuid, unique per delivery attempt group),
  "event": string,
  "test": boolean,
  "created_at": string (ISO 8601, UTC),
  "data": object
}

Request headers

Content-Type: application/json
User-Agent: Scrybert-Webhooks/1
Scrybert-Event: <event name>
Scrybert-Delivery: <delivery id>
Scrybert-Signature: t=<unix timestamp>,v1=<hex-encoded HMAC-SHA256>

Signature verification

Each account has one webhook signing secret, prefixed whsec_, available in Settings > Developer. The v1 value is computed as:

HMAC-SHA256(key = secret, message = "{t}." + raw_request_body)

Reference implementation:

import hmac, hashlib

def verify(secret: str, header: str, body: bytes) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t, v1 = parts["t"], parts["v1"]
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, v1)

The signature must be computed over the raw request body as received. Re-serializing the payload before verification can alter key order or whitespace and will produce a mismatch.

Delivery behavior

Retry scheduleImmediate, then +5 seconds, then +30 seconds (maximum 3 attempts)
Retry conditionsNetwork error or response status 5xx
Terminal conditionsResponse status 4xx is not retried
Timeout5 seconds per attempt
RedirectsNot followed
Target address requirementshttps only; must resolve to a public IP address at both save time and delivery time

Pivotal Moments data is not included in any webhook payload under any event.

Rate limits and requirements

Cloud Backup requirement, MCP and to-do endpoint30 days or longer
Cloud Backup requirement, webhooksNone
To-do creation rate limit120 per account per hour, shared across MCP and the to-do endpoint
list_conversations / search result limit50 maximum
list_todos result limit200 maximum
Webhook delivery timeout5 seconds per attempt, 3 attempts maximum

Status codes

200Request succeeded. For the to-do endpoint with a repeated id, indicates the original item was returned.
201A new item was created.
401Missing or invalid developer key.
403Cloud Backup setting below the required threshold.
405Method not allowed (for example, GET on the MCP endpoint).
409Required configuration missing (for example, testing a webhook with no saved address).
422Request body failed validation.
429Rate limit exceeded.

Support

For issues not covered by this document, see Contact.