← Back to API reference

API Changelog

Every change to Symbol's public API surface, classified and dated. See the stability policy for what each classification means and the notice periods that apply. Subscribe via the Atom feed.

  1. Additivepreview

    Share-link verification adds a `not_applicable` reason

    The `share_verification.reason` field returned alongside created share links gains a new value, `not_applicable`. It is emitted with `verified: false` when the create path cannot round-trip a freshly minted token through the verification read path — specifically for Type/Collection (library) share tokens, whose authenticated resolve endpoint is capsule-only. `not_applicable` means verification was skipped, not that the link is broken. This is additive: the existing `access_denied` | `not_found` | `error` values and all request shapes are unchanged. Backed by issue #858 (item 3).

  2. Additivepreview

    Collection create/update accept an optional `alias`

    `POST /api/preview/types/{id}/collections` and `PATCH /api/preview/types/{id}/collections/{collectionId}` now accept an optional request field `alias` — a tenant-global shorthand that addresses a collection by `@alias` alone, without naming its parent Type, from MCP and CLI. An alias is a lowercase text token (max 60 chars, not purely numeric) and is unique per tenant (personal or workspace), unlike a collection's per-Type `slug`. Real Type slugs always take precedence: an alias that would shadow an existing Type slug is rejected, and resolution tries Type slugs first so a Type can never be shadowed by a collection alias. Renaming or removing an alias leaves a tombstone, so a bare `@alias` already written elsewhere keeps resolving to its original collection and never silently repoints. Both are additive and optional: omitting `alias` on create leaves the collection alias-less, an omitted `alias` on update leaves the stored value untouched (PATCH semantics), and passing `null` clears it. A taken alias or a Type-slug shadow returns `409`. No existing fields or response shapes change. Backed by issue #316 (migration 147).

  3. Additivepreview

    Workspaces accept an `icon` for switcher branding

    `PUT /api/preview/organizations/{id}` accepts an optional, nullable request field `icon` — a workspace icon key from a closed set (`building`, `tower`, `briefcase`, `landmark`, `store`, `users`, `rocket`, `box`, `layers`, `globe`) shown in the workspace switcher. Purely additive with PATCH semantics: omit it to leave the stored icon unchanged, or send `null` to reset to the default (`building`). Editable by a workspace owner or editor. No existing fields or response shapes change (migration 145).

  4. Additivepreview

    Types accept a `field_body_template` for field-structured capsules

    `POST /api/preview/types` and `PUT /api/preview/types/{id}` accept an optional request field `field_body_template` (string, max 10000) — a capsule body template for a field-structured Type. New capsules of the Type seed their `content_md` from it, and any `{field_name}` tokens render from the capsule's `field_values` at read time. Purely additive and optional: omit it (or send `""`) and the body is derived from the values as before; on update, an omitted field leaves the stored value untouched (PATCH semantics). No existing fields or response shapes change. Follow-up to the typed-fields work (issue #868, migration 144).

  5. Additivepreview

    Types accept a structured `field_schema`; capsules accept `field_values`

    Types can now declare optional structured fields with declarative validation. `POST /api/preview/types` and `PUT /api/preview/types/{id}` accept an optional request field `field_schema` — zero or more fields (`text` | `number` | `datetime` | `enum` | `reference`), each with an optional `required` flag (plus a custom `required_message`) and type-appropriate rules carrying per-rule messages. `POST /api/preview/capsules` and `PUT /api/preview/capsules/{id}` accept an optional `field_values` object that is validated against the owning Type's schema; all violations are returned together as RFC 9457 `application/problem+json` with an `errors[]` array. `PUT /api/preview/types/{id}` also accepts an optional `confirm_field_changes` flag: destructive schema edits (removing or renaming an enum value or field) return `409` with the required confirmation token and grandfather existing capsules once confirmed. All three fields are additive and optional — a Type with no `field_schema` behaves exactly as before, and on update an omitted field leaves the stored value untouched (PATCH semantics). Field-structured Types are mutually exclusive with end-to-end encryption (server-side validation needs plaintext). No existing fields or response shapes change. Backed by issue #868 (migration 143).

  6. Additivepreview

    Publicly shared prompts are safety-classified

    Capsules shared with the `prompt` render template now have their prompt body classified for safety (low/medium/high). High-risk prompts are withheld on the public share page behind a recipient acknowledgment; medium shows a non-blocking caution; low renders unchanged. Classification is best-effort and fails open — sharing and viewing always work even when the classifier is disabled or unavailable. A new GET /api/cron/classify-shared-prompts endpoint (Vercel cron, `Authorization: Bearer $CRON_SECRET`) backfills verdicts. No existing request/response shapes change. Backed by issue #856 (migration 143).

  7. Additivepreview

    Capsule write responses surface partial attachment failures

    `POST /api/preview/capsules` and `PUT /api/preview/capsules/{id}` may now return two optional `200` response fields: `partial` (boolean) and `attachment_error` (string). When a capsule's fields are written successfully but its attachments fail validation, the response sets `partial: true` and carries the validation detail in `attachment_error`, while the capsule fields above remain authoritative — so a client consuming only the structured response can detect the partial outcome instead of mistaking it for a clean write. Purely additive: clients that ignore the new fields are unaffected.

  8. Additivepreview

    Type update accepts an optional `share_template`

    `PUT /api/preview/types/{id}` now accepts an optional request field `share_template` (`article` | `prompt`) that controls how the Type's public share page renders. `prompt` presents each capsule as a grab-and-use prompt with body-only copy and variable highlighting; `article` (the default) keeps the standard reading layout. A shared Collection inherits its parent Type's template. The field is additive and optional: omitting it on update leaves the stored value untouched (PATCH semantics). No existing fields or response shapes change. Backed by issue #852 (migration 141).

  9. Additivepreview

    Capsule create/update accept an optional `slug` alias

    `POST /api/preview/capsules` and `PUT /api/preview/capsules/{id}` now accept an optional request field `slug` — a human-readable text alias that resolves to the same capsule as its permanent numeric ref (`@type/<slug>` works alongside `@type/<N>`). A slug is a lowercase alias (max 60 chars, not purely numeric) and is unique per (type, owner); renaming or removing one leaves a tombstone so `@type/<slug>` references already written elsewhere keep resolving. Both are additive and optional: omitting `slug` on create leaves the capsule alias-less, an omitted `slug` on update leaves the stored alias untouched (PATCH semantics), and passing `null` clears it. No existing fields or response shapes change. Backed by issue #715 (migration 136).

  10. Additivepreview

    Type create/update accept `package_as` and `format`

    `POST /api/preview/types` and `PUT /api/preview/types/{id}` now accept two optional request fields: `package_as` (`standard` | `skill`) and `format`. `package_as` controls how a Type's capsules are packaged — setting it to `skill` packages the Type (and every capsule in it) as a Claude Code skill, while `standard` keeps the default behavior. `format` records the export format. Both are additive and optional: omitting them leaves existing behavior unchanged, and on PUT an omitted field leaves the stored column untouched (PATCH semantics). No existing fields or response shapes change. Backed by the skill-packaging work (migration 133).

  11. Cosmeticpreview

    Rapid consecutive saves now always record a version

    The 60-second revision interval throttle has been removed. Previously, a same-author save landing less than 60 seconds after the prior version skipped capturing a new version row (the capsule/Type UPDATE still applied), and the PUT capsule/Type and restore responses could carry `version_skip_reason: "interval_throttle"`. Now every explicit save with changed content records a version, so `interval_throttle` is no longer emitted and is removed from the set of possible `version_skip_reason` values. No response shape change — this is a value-set narrowing. No-op saves still skip with `identical_content`, and the size, rate, quota, and capsule-cap gates are unchanged. Backed by issue #667.

  12. Additivepreview

    Workspace scoping for personal API keys

    POST /api/preview/user/api-keys accepts a new optional request field `workspaceIds` (array of strings). Each entry is either the literal "personal" or an organization-workspace UUID the caller can access. When present and non-empty the issued key's access is restricted to exactly those workspaces (intersected with the caller's live membership at request time); omitting the field or passing an empty array issues an unrestricted key with the same reach as before. Organization keys (POST /api/preview/organizations/{id}/keys) are already hard-scoped to their organization and are unaffected. Existing clients are unaffected. Backed by issue #597.

  13. Additivepreview

    Per-Type maximum capsule content length

    POST /api/preview/types and PUT /api/preview/types/{id} accept a new optional request field `content_md_max` (integer, floor 0, ceiling 90000, default 20000). It sets a per-Type cap on capsule `content_md` length that overrides the global per-capsule limit; capsule create/update reject bodies over the effective cap. Lowering a Type's cap grandfathers existing over-cap capsules (they remain editable but cannot grow). A cap of 0 makes the Type title-only. The field also appears on Type response bodies, and GET /api/preview/capsules/{id} now carries the denormalized `type_content_md_max` so editors can render a live character counter. Existing clients are unaffected — omitting the field preserves the previous behaviour. Backed by issue #601.

  14. Additivepreview

    update_type MCP tool for editing Type metadata

    The MCP server now exposes an `update_type` tool — a thin client over the existing PUT /api/preview/types/{id} endpoint. AI assistants can correct a Type's name, guidance, summary, freshness thresholds (stale_after_days / expire_after_days), orphan-warning visibility, and default project without a human opening the web UI; previously only create_type was available. PATCH semantics — only supplied fields change. The slug stays immutable and the one-way encryption flip is intentionally not exposed. The tool forwards an optional updated_at optimistic-concurrency token (mapped to the endpoint's client_updated_at) so a concurrent edit returns a conflict instead of silently overwriting, and guidance/summary edits are captured in the Type's version history. No REST contract change — the underlying endpoint is unchanged; this publishes the new MCP tool surface. Backed by issue #536.

  15. Additivepreview

    Per-Type opt-out for the orphan-capsules banner

    POST /api/preview/types and PUT /api/preview/types/{id} accept a new optional request field `hide_orphan_warning` (boolean, default false). When true, the Type's detail page suppresses the orphan-capsules banner that flags capsules with zero inbound references. The field also appears on Type response bodies. Existing clients are unaffected — omitting the field preserves the previous behaviour (warning shown).

  16. Additivepreview

    Capsule + type version history with quota gating

    Append-only snapshot history shipped for non-encrypted capsules and types. New endpoints: GET /api/preview/(capsules|types)/{id}/versions (cursor-paginated, newest-first), GET /api/preview/(capsules|types)/{id}/versions/{versionNum}, POST /api/preview/(capsules|types)/{id}/versions/{versionNum}/restore (append-only — captures the pre-restore state as a new version), and DELETE /api/preview/(capsules|types)/{id}/versions/{versionNum} for manual entries. Encrypted capsules/types never produce a version (storage-layer enforcement: record trigger, encryption-toggle purge trigger, and BEFORE INSERT reject trigger on the version tables). Storage is over-counted and tracked per-user; at 85% of plan storage the version write is skipped — the underlying capsule/type UPDATE still succeeds. PUT /api/preview/capsules/{id} and PUT /api/preview/types/{id} responses now always carry `version_skipped` (boolean) and `version_skip_reason` ("quota" | "encryption" | null) — additive, existing fields unchanged. 30-day hard retention enforced by a 6-hourly prune cron; nightly reconciliation auto-corrects counter drift above 1%. Operational notes, accounting formula, and rollback SQL in docs/versioning/README.md.

  17. Additivepreview

    GET /api/preview/types/{id} for read-side parity

    Single-type read endpoint added at GET /api/preview/types/{id}, closing the CRUD gap with capsules and projects. Callers holding a type ID (returned from createType, embedded in a capsule payload, or surfaced via list_types) can now fetch the full record without listing all types and filtering client-side. The response shape mirrors items in GET /api/preview/types — including the joined workspace_name, capsule_count, and last_capsule_at fields. Backed by issue #417.

  18. Additivepreview

    Canonical collection-membership endpoints

    Adding and removing capsules from a collection now lives at POST /api/preview/collections/{id}/capsules and DELETE /api/preview/collections/{id}/capsules. The server resolves the parent type and workspace from the collection ID alone — closing a class of cross-workspace scope drift that surfaced as 400 "Invalid collection ID" against IDs that round-tripped through list_collections. The legacy type-scoped paths (POST | DELETE /api/preview/types/{id}/collections/{collectionId}/capsules) keep working for one release cycle via a 308 Permanent Redirect (preserves method + body) and are now marked deprecated in the OpenAPI document so codegen flags them. Their summary text was updated in this release; no behavior change beyond the redirect. Bug fix #423.

  19. Additivepreview

    Read-side parity and defense-in-depth gates for preview API

    30 read- and lifecycle-side operations are now part of the published OpenAPI surface, bringing the preview spec to read/write parity with the implemented routes. New operations include capsule list/get/delete/archive plus batch archive/delete/move; capsule backlinks, graph, and references reads; project list/get/delete and capsule add/remove plus project context; type list/delete and collection list/get/delete plus collection capsule add/remove; share list/resolve/revoke; search; user profile; workspaces; and attachment delete. The underlying handlers were already shipping — this change publishes them in the contract so Scalar, generated openapi-fetch / Dart clients, and Postman pick them up. Backed by defense-in-depth public-surface gates that fail closed when an operation is referenced without an explicit allowlist entry.

  20. Additivepreview

    Typed 200-response schemas for capsule and share writes

    POST /api/preview/capsules, PUT /api/preview/capsules/{id}, and POST /api/preview/share now publish typed JSON-Schema response bodies in the OpenAPI document. New response fields documented (capsule writes: id, ref_id, title, type_id, browser_url, share_token, share_url, share_verification, attachments; share create: share_token, share_url, browser_url, share_verification). Wire shape is unchanged — the server has always emitted these fields; only the contract surface (consumed by Scalar, generated openapi-fetch, and Postman) is new. Clients can now codegen typed response models instead of hand-rolling them. Backed by Zod modules under @symbol/shared/contracts/output/*.

  21. Additivepreview

    Preview API launched

    Symbol's public HTTP API is now available under /api/preview/* on the free preview tier. The full surface — capsules, types, projects, organizations, share, collections, invitations, attachments, mentions, references, library, search, workspaces, billing (non-webhook), GDPR, and support — ships with a published OpenAPI 3.1 document, RFC 9457 Problem Details errors, generated TypeScript and Dart clients, and an MCP server. Subsequent changes will appear here, classified breaking / additive / cosmetic. Preview gives no SLA and no paid tier; v1 will follow once the surface stabilises.