Lithic docs
lithicapp.io

Automatisierung

Persönliche Zugriffstoken, Webhooks, Export und das Auflösen von Links — überall dort spricht die Instanz nach außen. Dazu die wenigen Routen, die in die Gegenrichtung laufen: die Anmeldung zum frühen Zugang und die Frage des Anmeldebildschirms, welche Wege hinein diese Installation überhaupt anbietet. Das sind die Teile dieser API, die ganz ohne Sitzung erreichbar sind.

15 Operationen. Jeder Pfad ist relativ zum Ursprung der Instanz; jeder Antwortkörper ist JSON, sofern nicht anders vermerkt. Die Endpunktbeschreibungen unten stammen unverändert aus der Routentabelle des Servers und bleiben englisch. Authentifizierung, Fehler und seitenweise Abfrage stehen unter API.

GET /api/v1/auth/methods

Which ways into this instance are configured — password, password reset, and any social providers. Unauthenticated and outside the /workspaces/:workspaceId scope, because a sign-in screen has neither a session nor a workspace yet; getMyCapabilities answers a different question for somebody already inside. The single source for which sign-in buttons to render: a button for a provider this instance has no credentials for would send a person to Google and back into an error. The answer is a property of the deployment, identical for every caller, and reveals nothing about any account.

getAuthMethods · token scope: session only

Response 200application/json

  • password · boolean — required
  • passwordReset · boolean — required
  • social · "google"[] — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

POST /api/v1/waitlist

Join an early-access list. Unauthenticated, rate-limited, and outside the /workspaces/:workspaceId scope — the caller has no account yet. Creates an UNCONFIRMED signup and sends one confirmation mail (double opt-in): nothing is written to the address again until the link in it is followed, and an unconfirmed signup is deleted after 14 days. Answers {"status":"pending"} for a new address AND for one already on the list, deliberately — a differing answer would tell a stranger whether an address is known here. Never returns the row or the token.

createWaitlistSignup · token scope: session only

Request bodyapplication/json, required

  • email · string (email) — required, length 0–320
  • locale · "de" | "en" — required
  • product · "basalt" | "lithic" | "tecto" — required

Response 200application/json

  • status · "pending" | "confirmed" | "removed" — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

POST /api/v1/waitlist/confirm

Redeem a confirmation token and record consent (timestamp plus the confirming client's address, GDPR Art. 7(1)). Unauthenticated and rate-limited. Single use: a second attempt with the same token is refused like an unknown one. Every failure — unknown token, expired token, already confirmed — answers with ONE opaque error, so the route cannot be used to learn whether a token or an address exists.

confirmWaitlistSignup · token scope: session only

Request bodyapplication/json, required

  • token · string — required, length 1–200

Response 200application/json

  • status · "pending" | "confirmed" | "removed" — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

POST /api/v1/waitlist/unsubscribe

Withdraw consent and leave the list. Unauthenticated and rate-limited, and it takes the SAME token the confirmation mail carried — GDPR Art. 7(3) wants withdrawal to be as easy as consent was, and consent was one click. Unlike confirming, this accepts an EXPIRED token and an already-confirmed one: somebody who kept the mail for a month must still be able to leave. The row is DELETED, IP evidence included — there is no reason to keep proof of a consent that has been withdrawn. Idempotent by construction: a token that matches nothing (because it already unsubscribed) answers {"status":"removed"} too, so a second click cannot report a failure for something that is already true.

unsubscribeWaitlistSignup · token scope: session only

Request bodyapplication/json, required

  • token · string — required, length 1–200

Response 200application/json

  • status · "pending" | "confirmed" | "removed" — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

POST /api/v1/workspaces/{workspaceId}/unfurl

Fetch public metadata (title, description, icon, preview image, whether it may be framed) for a URL, so a pasted link can be shown as a titled link, a bookmark card or an embed. This makes the instance issue an outbound request to the URL, from its own IP address. The address is resolved, refused unless globally routable, and pinned into the connection; redirects are never followed. Answers are cached. Operators can disable the whole route with UNFURL=off, which makes it 403.

unfurlUrl · token scope: content:write

Path parameters

  • workspaceId · string (uuid) — required

Request bodyapplication/json, required

  • url · string (uri) — required, length 0–2000

Response 200application/json

  • url · string — required
  • title · string | null — required
  • description · string | null — required
  • siteName · string | null — required
  • iconUrl · string | null — required
  • imageUrl · string | null — required
  • embeddable · "allowed" | "refused" | "unknown" — required
  • cached · boolean — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

GET /api/v1/workspaces/{workspaceId}/export

Download the workspace as a zip: one Markdown file per page (folder tree mirroring the page hierarchy, field values as YAML frontmatter), one per outline under /outlines/ (inline marks flattened, which a page's body keeps), one per board under /boards/ (the body plus a card list per column), the attachments those pages reference, and basalt-export.json carrying every page's, outline's and board's verbatim title and path plus the collections, databases, fields, bindings, views and row memberships Markdown cannot express. All of it — structure included — is filtered to what the caller may read; an export is not a way around permissions.

exportWorkspace · token scope: content:read

Path parameters

  • workspaceId · string (uuid) — required

Response 200application/json

  • string

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

GET /api/v1/workspaces/{workspaceId}/tokens

The caller's own tokens in this workspace, newest first, including revoked and expired ones so a person can see what a credential has been doing. Never carries a secret. Session-only.

listTokens · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required

Query parameters

  • cursor · string — length 1–∞
  • limit · integer — 1–100

Response 200application/json

  • items · object[] — required
    • id · string (uuid) — required
    • workspaceId · string (uuid) — required
    • userId · string (uuid) — required
    • name · string — required
    • scopes · "content:read" | "content:write" | "admin:read" | "admin:write"[] — required
    • product · "basalt" | "lithic" | "tecto" | null — required
    • preview · string — required
    • createdAt · string (date-time) — required
    • expiresAt · string (date-time) — required
    • lastUsedAt · string (date-time) | null — required
    • revokedAt · string (date-time) | null — required
    • revokedReason · "manual" | "membership_lost" | null — required
  • nextCursor · string | null — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

POST /api/v1/workspaces/{workspaceId}/tokens

Mint a personal access token for the caller in this workspace. The response is the ONLY place the secret ever appears — it is stored as a SHA-256 digest and is not recoverable. The token acts as the caller: it can never do more than they can, and its scopes narrow that further. Session-only: a token may not mint a token.

createToken · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required

Request bodyapplication/json, required

  • name · string — required, length 1–200
  • scopes · "content:read" | "content:write" | "admin:read" | "admin:write"[] — required, 1–4 items
  • expiresInDays · integer — 1–365

Response 200application/json

  • id · string (uuid) — required
  • workspaceId · string (uuid) — required
  • userId · string (uuid) — required
  • name · string — required
  • scopes · "content:read" | "content:write" | "admin:read" | "admin:write"[] — required
  • product · "basalt" | "lithic" | "tecto" | null — required
  • preview · string — required
  • createdAt · string (date-time) — required
  • expiresAt · string (date-time) — required
  • lastUsedAt · string (date-time) | null — required
  • revokedAt · string (date-time) | null — required
  • revokedReason · "manual" | "membership_lost" | null — required
  • token · string — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

DELETE /api/v1/workspaces/{workspaceId}/tokens/{tokenId}

Revoke one token immediately. The row is kept, stamped revokedAt, so the listing still explains what existed and when it last ran. Session-only.

revokeToken · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required
  • tokenId · string (uuid) — required

Response 200application/json

  • id · string (uuid) — required
  • workspaceId · string (uuid) — required
  • userId · string (uuid) — required
  • name · string — required
  • scopes · "content:read" | "content:write" | "admin:read" | "admin:write"[] — required
  • product · "basalt" | "lithic" | "tecto" | null — required
  • preview · string — required
  • createdAt · string (date-time) — required
  • expiresAt · string (date-time) — required
  • lastUsedAt · string (date-time) | null — required
  • revokedAt · string (date-time) | null — required
  • revokedReason · "manual" | "membership_lost" | null — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

GET /api/v1/workspaces/{workspaceId}/webhooks

The caller's own endpoints in this workspace, newest first, with their failure state. Never carries a secret. Session-only.

listWebhooks · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required

Query parameters

  • cursor · string — length 1–∞
  • limit · integer — 1–100

Response 200application/json

  • items · object[] — required
    • id · string (uuid) — required
    • workspaceId · string (uuid) — required
    • ownerId · string (uuid) — required
    • url · string (uri) — required
    • events · "workspace" | "collection" | "page" | "outline" | "board" | "field" | "database" | "db_view" | "db_row" | "permission" | "group" | "invitation" | "comment"[] — required
    • secretPreview · string — required
    • enabled · boolean — required
    • disabledReason · "manual" | "delivery_failures" | "owner_lost_access" | null — required
    • consecutiveFailures · integer — required, -9007199254740991–9007199254740991
    • lastDeliveryAt · string (date-time) | null — required
    • lastSuccessAt · string (date-time) | null — required
    • createdAt · string (date-time) — required
  • nextCursor · string | null — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

POST /api/v1/workspaces/{workspaceId}/webhooks

Register an outbound endpoint for workspace events. The payload carries ids and timings, never content, and every frame naming a block is resolved against the endpoint OWNER before it is queued (ADR-0016 D9b). Needs the member role: making the server issue HTTP requests is a workspace-level act, not a per-page one. The response is the only place the signing secret appears. Session-only.

createWebhook · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required

Request bodyapplication/json, required

  • url · string (uri) — required, length 0–2000
  • events · "workspace" | "collection" | "page" | "outline" | "board" | "field" | "database" | "db_view" | "db_row" | "permission" | "group" | "invitation" | "comment"[] — required, 1–∞ items

Response 200application/json

  • id · string (uuid) — required
  • workspaceId · string (uuid) — required
  • ownerId · string (uuid) — required
  • url · string (uri) — required
  • events · "workspace" | "collection" | "page" | "outline" | "board" | "field" | "database" | "db_view" | "db_row" | "permission" | "group" | "invitation" | "comment"[] — required
  • secretPreview · string — required
  • enabled · boolean — required
  • disabledReason · "manual" | "delivery_failures" | "owner_lost_access" | null — required
  • consecutiveFailures · integer — required, -9007199254740991–9007199254740991
  • lastDeliveryAt · string (date-time) | null — required
  • lastSuccessAt · string (date-time) | null — required
  • createdAt · string (date-time) — required
  • secret · string — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

PATCH /api/v1/workspaces/{workspaceId}/webhooks/{webhookId}

Change an endpoint. A new URL is re-checked against the SSRF policy. Re-enabling an endpoint the server disabled also clears its failure counter. Session-only.

updateWebhook · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required
  • webhookId · string (uuid) — required

Request bodyapplication/json, required

  • url · string (uri) — length 0–2000
  • events · "workspace" | "collection" | "page" | "outline" | "board" | "field" | "database" | "db_view" | "db_row" | "permission" | "group" | "invitation" | "comment"[] — 1–∞ items
  • enabled · boolean

Response 200application/json

  • id · string (uuid) — required
  • workspaceId · string (uuid) — required
  • ownerId · string (uuid) — required
  • url · string (uri) — required
  • events · "workspace" | "collection" | "page" | "outline" | "board" | "field" | "database" | "db_view" | "db_row" | "permission" | "group" | "invitation" | "comment"[] — required
  • secretPreview · string — required
  • enabled · boolean — required
  • disabledReason · "manual" | "delivery_failures" | "owner_lost_access" | null — required
  • consecutiveFailures · integer — required, -9007199254740991–9007199254740991
  • lastDeliveryAt · string (date-time) | null — required
  • lastSuccessAt · string (date-time) | null — required
  • createdAt · string (date-time) — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

DELETE /api/v1/workspaces/{workspaceId}/webhooks/{webhookId}

Delete an endpoint and its delivery history. Session-only.

deleteWebhook · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required
  • webhookId · string (uuid) — required

Response 200application/json

  • id · string (uuid) — required
  • workspaceId · string (uuid) — required
  • ownerId · string (uuid) — required
  • url · string (uri) — required
  • events · "workspace" | "collection" | "page" | "outline" | "board" | "field" | "database" | "db_view" | "db_row" | "permission" | "group" | "invitation" | "comment"[] — required
  • secretPreview · string — required
  • enabled · boolean — required
  • disabledReason · "manual" | "delivery_failures" | "owner_lost_access" | null — required
  • consecutiveFailures · integer — required, -9007199254740991–9007199254740991
  • lastDeliveryAt · string (date-time) | null — required
  • lastSuccessAt · string (date-time) | null — required
  • createdAt · string (date-time) — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

POST /api/v1/workspaces/{workspaceId}/webhooks/{webhookId}/secret

Mint a new signing secret and return it once. Deliveries already queued are signed with the new secret — there is no overlap window, so rotate when the receiver is ready to accept it. Session-only.

rotateWebhookSecret · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required
  • webhookId · string (uuid) — required

Response 200application/json

  • id · string (uuid) — required
  • workspaceId · string (uuid) — required
  • ownerId · string (uuid) — required
  • url · string (uri) — required
  • events · "workspace" | "collection" | "page" | "outline" | "board" | "field" | "database" | "db_view" | "db_row" | "permission" | "group" | "invitation" | "comment"[] — required
  • secretPreview · string — required
  • enabled · boolean — required
  • disabledReason · "manual" | "delivery_failures" | "owner_lost_access" | null — required
  • consecutiveFailures · integer — required, -9007199254740991–9007199254740991
  • lastDeliveryAt · string (date-time) | null — required
  • lastSuccessAt · string (date-time) | null — required
  • createdAt · string (date-time) — required
  • secret · string — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64

GET /api/v1/workspaces/{workspaceId}/webhooks/{webhookId}/deliveries

Recent delivery attempts for one endpoint, newest first — what was sent, what came back, and when the next attempt is due. Session-only.

listWebhookDeliveries · token scope: session only

Path parameters

  • workspaceId · string (uuid) — required
  • webhookId · string (uuid) — required

Query parameters

  • cursor · string — length 1–∞
  • limit · integer — 1–100

Response 200application/json

  • items · object[] — required
    • id · string (uuid) — required
    • endpointId · string (uuid) — required
    • resource · string — required
    • resourceId · string (uuid) — required
    • status · "pending" | "delivered" | "dead" — required
    • attempt · integer — required, -9007199254740991–9007199254740991
    • responseStatus · integer | null — required
    • error · string | null — required
    • nextAttemptAt · string (date-time) | null — required
    • createdAt · string (date-time) — required
    • deliveredAt · string (date-time) | null — required
  • nextCursor · string | null — required

Response defaultapplication/json

  • error · object — required
    • code · "bad_request" | "validation_failed" | "unauthorized" | "forbidden" | "not_found" | "conflict" | "rate_limited" | "internal" — required
    • message · string — required
    • reason · string — length 1–64