{"openapi":"3.1.0","info":{"title":"DynoTable API","version":"1.0.0","summary":"Licensing, download, and site-content query API for DynoTable — the DynamoDB GUI.","description":"DynoTable (https://dynotable.com) is a local-first desktop DynamoDB GUI (macOS/Windows/Linux) with a real SQL workbench, PartiQL console, an AI agent on the customer's own Amazon Bedrock keys, and an MCP server built into the app (see https://dynotable.com/docs/dynamodb-mcp).\n\n**When to use this API** (agents): use `queryContent`/`queryContentJson` to answer any DynamoDB or DynoTable question from this site's docs, curriculum, error reference, FAQ, and code examples; use `getLatestVersion`/`downloadArtifact` to resolve or fetch the latest desktop build; the license endpoints are called by the DynoTable desktop app itself with a signed license token.\n\nThe webhook receivers under /api/webhooks/* and /api/aws/register are for Clerk, Stripe, and AWS Marketplace deliveries only (signature-authenticated) and are not client-callable. Site pages also negotiate markdown: request any documentation URL with `Accept: text/markdown` to get a markdown rendition. Start at https://dynotable.com/llms.txt for the curated site map.","contact":{"name":"DynoTable support","email":"support@dynotable.com","url":"https://dynotable.com/contact"},"termsOfService":"https://dynotable.com/terms"},"externalDocs":{"description":"Human-readable product docs","url":"https://dynotable.com/docs"},"servers":[{"url":"https://dynotable.com"}],"paths":{"/api/license/refresh":{"post":{"operationId":"refreshLicenseToken","summary":"Rotate a license token","description":"Trade a still-signature-valid Ed25519 license token for a fresh one (the DynoTable app calls this ~every 4h). Every entitlement gate is re-checked; any failure is `410 Gone` and the app must drop to signed-out/read-only — a 410 is never transient.","tags":["license"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseTokenRequest"}}}},"responses":{"200":{"description":"A fresh token (new jti, new 3-day expiry).","content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The new Ed25519 JWS license token."}}}}}},"400":{"description":"Malformed request body (`error: invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"License gone — stop and drop to signed-out/read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseGoneError"}}}}}}},"/api/license/deactivate":{"post":{"operationId":"deactivateLicenseMachine","summary":"Free the machine slot a token is bound to","description":"Releases the machine slot so it can be reused on another machine. Idempotent — re-running on an already-freed machine still succeeds. The token is the auth and may only free its own bound machine.","tags":["license"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseTokenRequest"}}}},"responses":{"204":{"description":"Machine freed (or was already free)."},"400":{"description":"Malformed request body (`error: invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The token may only free its own machine (`error: machine_mismatch`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Token verification failed (same reason set as refresh).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseGoneError"}}}}}}},"/api/account/devices":{"get":{"operationId":"listAccountDevices","summary":"List the signed-in user's active machines","description":"Backs the /account/devices page. Requires a Clerk browser session; only slot-holding machines are listed.","tags":["account"],"security":[{"clerkSession":[]}],"responses":{"200":{"description":"The active machines.","content":{"application/json":{"schema":{"type":"object","required":["devices"],"properties":{"devices":{"type":"array","items":{"$ref":"#/components/schemas/Device"}}}}}}},"401":{"description":"No Clerk session (`error: unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/account/devices/{machineHash}/deactivate":{"post":{"operationId":"deactivateAccountDevice","summary":"Remotely deactivate one of your machines","description":"Frees the named machine slot from the web account UI. Requires a Clerk browser session; the machine must be a slot-holding machine belonging to the caller.","tags":["account"],"security":[{"clerkSession":[]}],"parameters":[{"name":"machineHash","in":"path","required":true,"description":"The SHA-256 machine hash, as listed by listAccountDevices.","schema":{"type":"string"}}],"responses":{"204":{"description":"Machine freed."},"401":{"description":"No Clerk session (`error: unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not a slot-holding machine of this user (`error: not_found`) — unknown, foreign-owned, already freed, or stale.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/version":{"get":{"operationId":"getLatestVersion","summary":"Latest desktop release (public JSON)","description":"The latest DynoTable desktop release: bare semver version (no `v` prefix), publish date, and per-platform availability. Used by package registries (Scoop checkver, Homebrew livecheck) and safe for any client — no auth, no asset URLs.","tags":["downloads"],"responses":{"200":{"description":"The release summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseSummary"}}}},"502":{"description":"Could not resolve the latest release (transient — retry).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Version lookup unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/download/{platform}":{"get":{"operationId":"downloadArtifact","summary":"Download the desktop app (302 to the release asset)","description":"Redirects to the signed release-asset URL for the platform. Append `/{version}` to pin a release (`/api/download/win/1.4.3`) — package managers should pin, since a `latest` URL breaks published checksums on the next release.","tags":["downloads"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Target artifact.","schema":{"type":"string","enum":["mac","win","deb","rpm","appimage"]}}],"responses":{"302":{"description":"Redirect to the signed asset URL."},"400":{"description":"Malformed version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown platform/version, or no build for this platform.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Could not resolve the download (transient — retry).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Downloads unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/llms":{"get":{"operationId":"queryContent","summary":"Query the site content index (markdown answer)","description":"Full-text query over the same index the site's own search uses — docs, the DynamoDB curriculum, comparisons, the error reference, FAQ, code examples, and blog. Answers with titled, deep-linked absolute URLs plus snippets. A bare GET (no `query`) returns the usage doc.","tags":["content"],"parameters":[{"name":"query","in":"query","required":false,"description":"The topic, in words. Also accepted as `q`. Omit for the usage doc.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Max results (default 5).","schema":{"type":"integer","minimum":1,"maximum":20,"default":5}},{"name":"locale","in":"query","required":false,"description":"One of the 13 shipped locales (default `en`).","schema":{"type":"string","default":"en"}}],"responses":{"200":{"description":"Markdown-formatted results (or the usage doc on a bare GET).","content":{"text/plain":{"schema":{"type":"string"}}}},"400":{"description":"An explicitly empty `?query=` — the usage doc is returned as the body.","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/llms/json":{"get":{"operationId":"queryContentJson","summary":"Query the site content index (JSON answer)","description":"The same answer as queryContent, machine-readable.","tags":["content"],"parameters":[{"name":"query","in":"query","required":false,"description":"The topic, in words. Also accepted as `q`. Omit for the usage doc.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Max results (default 5).","schema":{"type":"integer","minimum":1,"maximum":20,"default":5}},{"name":"locale","in":"query","required":false,"description":"One of the 13 shipped locales (default `en`).","schema":{"type":"string","default":"en"}}],"responses":{"200":{"description":"The query answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentQueryAnswer"}}}},"400":{"description":"An explicitly empty `?query=`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":["string","null"]},"usage":{"type":"string"}}}}}}}}}},"components":{"securitySchemes":{"clerkSession":{"type":"apiKey","in":"cookie","name":"__session","description":"Clerk browser session cookie — the account endpoints back the signed-in web UI and are not intended for headless API clients."}},"schemas":{"Error":{"type":"object","description":"Machine-readable error. `error` is a stable code; `message`/`hint` are for humans and agents.","required":["error"],"properties":{"error":{"type":"string","description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"hint":{"type":"string","description":"Where to look next."}}},"LicenseGoneError":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["malformed","bad_alg","bad_kid","bad_signature","invalid_claims","expiry_too_far","machine_mismatch","revoked","token_revoked","no_subscription","trial_ended","period_ended","machine_inactive","unknown_user"],"description":"Why the license is gone (docs/api.md has the full matrix)."}}},"LicenseTokenRequest":{"type":"object","required":["token","machineHash"],"properties":{"token":{"type":"string","description":"The current Ed25519 JWS license token (the auth)."},"machineHash":{"type":"string","description":"The calling machine's SHA-256 hash — must match the token's."}}},"Device":{"type":"object","required":["machineHash","machineName","os","firstSeen","lastSeen"],"properties":{"machineHash":{"type":"string"},"machineName":{"type":"string"},"os":{"type":"string"},"firstSeen":{"type":"integer","description":"Unix seconds."},"lastSeen":{"type":"integer","description":"Unix seconds."}}},"ReleaseSummary":{"type":"object","required":["version","publishedAt","available"],"properties":{"version":{"type":"string","description":"Bare semver, no `v` prefix."},"publishedAt":{"type":"string","format":"date-time"},"available":{"type":"object","description":"Per-platform build availability.","properties":{"mac":{"type":"boolean"},"win":{"type":"boolean"},"deb":{"type":"boolean"},"rpm":{"type":"boolean"},"appimage":{"type":"boolean"}}}}},"ContentQueryAnswer":{"type":"object","required":["query","locale","total","results","links"],"properties":{"query":{"type":"string"},"locale":{"type":"string"},"total":{"type":"integer","description":"Total matches; `results` is the first page."},"results":{"type":"array","items":{"type":"object","required":["title","section","url","kind","snippet"],"properties":{"title":{"type":"string","description":"The page's H1."},"section":{"type":"string","description":"Matching section heading, if any."},"url":{"type":"string","format":"uri","description":"Absolute, deep-linked URL."},"kind":{"type":"string","description":"Which surface the hit came from."},"snippet":{"type":"string"}}}},"links":{"type":"object","description":"Where to go next (llms.txt map, sitemap, endpoint twins).","additionalProperties":{"type":"string"}}}}}}}