generated: '2026-09-19' method: searched source: >- https://dokki.one/pub/api/api-conventions, https://dokki.one/pub/api/pagination-errors-and-rate-limits, https://dokki.one/pub/api/authentication, https://dokki.one/pub/api/capabilities-and-feature-discovery, https://dokki.one/pub/api/create-and-update-a-document, https://dokki.one/pub/docs/trash-and-restore, https://dokki.one/pub/docs/version-history — fetched 2026-09-19. description: >- Cross-cutting runtime semantics of the Dokki REST API (https://dokki.one/api/v1) that the generated OpenAPI cannot express: auth style, the three-gate authorization model, capability discovery as the live contract, pagination, identifiers, error envelope, retry policy, the ABSENCE of a server-side idempotency mechanism, and the reversal paths an agent can rely on. base_url: https://dokki.one/api/v1 api_style: REST over HTTPS, JSON request and response bodies; GET read, POST create/trigger, PATCH partial update, PUT replace a relationship or configuration, DELETE revoke/archive/remove. authentication: scheme: Authorization Bearer header credentials: [Dokki API key (dk_..., tenant-bound to Personal or one Org, carries scopes), Supabase bearer access token, browser session] verify: GET /api/v1/me returns type, user_id, org_id (null for Personal), key_id and effective scopes three_gates: [token scope, tenant boundary (Personal / Org / optional workspace context), object permission (resource, workspace or Org role, or public access)] docs: https://dokki.one/pub/api/authentication detail: authentication/dokki-one-authentication.yml scopes: scopes/dokki-one-scopes.yml capability_discovery: endpoint: GET /api/v1/capabilities role: '"the source of truth for the currently exposed endpoint catalog" — API version and preview status, scopes available to the caller, endpoint method/path pairs visible to that credential, whether writes are enabled' guidance: Call at startup, cache briefly, check the required method/path is present, degrade gracefully when it is absent. docs: https://dokki.one/pub/api/capabilities-and-feature-discovery idempotency: supported: false coverage: none mechanism: null provider_statement: >- "For create operations, use your own idempotency key in the integration layer and safely reconcile by name/metadata after timeouts. Do not assume a timed-out POST was not applied." agent_note: No Idempotency-Key header, no replay detection on any write. Retries of a timed-out POST can duplicate resources; reconcile by name/metadata before re-sending. docs: https://dokki.one/pub/api/pagination-errors-and-rate-limits concurrency_control: supported: partial mechanism: >- Snapshots (create_snapshot: true on PATCH /resources/{id}/content) as recovery points; no ETag / If-Match on the REST surface. The provider states "A later version of the API will expose stronger conditional-write headers; until then, do not blindly overwrite a document after a stale read." The MCP facade adds compare-and-set boundaries and confirm_token gates on destructive actions. docs: https://dokki.one/pub/api/create-and-update-a-document pagination: style: offset request_params: limit: number of items, bounded by the server offset: zero-based offset response_fields: page: object returned when the endpoint supports pagination applies_to: '"Most list endpoints"; the quickstart shows GET /api/v1/workspaces?limit=50' docs: https://dokki.one/pub/api/pagination-errors-and-rate-limits identifiers_and_timestamps: ids: UUIDs; treat as opaque timestamps: ISO 8601 strings in UTC forward_compatibility: Treat unknown response fields as forward-compatible additions. key_prefix: dk_ (API keys); req_ (request identifiers in examples) request_tracing: request_id_field: error.request_id (and request_id on success envelopes) guidance: Log request_id with the integration job and show it in support tickets; preserve it when asking for support. versioning: scheme: URL path version current: /api/v1 preview_status: reported by GET /api/v1/capabilities ("API version and preview status") policy_published: false detail: lifecycle/dokki-one-lifecycle.yml changelog: changelog/dokki-one-changelog.yml error_envelope: media_type: application/json rfc9457: false shape: '{ "error": { "code", "message", "request_id" } }' codes_documented: [unauthorized (401), insufficient_scope (403), forbidden (403), invalid request (400), not found (404), conflicting state (409), rate limit exceeded (429)] non_disclosure: '"Treat 404 as non-disclosure in permission-sensitive reads" — a 404 may be returned where revealing existence would leak information.' detail: errors/dokki-one-problem-types.yml retry_policy: retry: network failures and 408 / 429 / 5xx with exponential backoff and jitter do_not_retry: 400, 401, 403, 404, 422 without changing the request or authorization timeouts: set an explicit timeout; bound retries rate_limits: signal_status: 429 headers_documented: none guidance: Respect 429, keep concurrency bounded per key, Org and workspace, batch reads, cache immutable metadata, avoid fast polling. detail: rate-limits/dokki-one-rate-limits.yml dry_run_mode: supported: false note: No dry-run / validate-only flag is documented for any write. The MCP facade's confirm_token round-trip on destructive actions is a confirmation gate, not a rehearsal. reversibility: summary: >- Deletes are soft (Trash) with a stated 30-day window; content changes are recoverable through snapshots; publishing and agent runs have reversal operations without a stated window; emptying trash and deleting API keys / organizations are final. write_surfaces: - operation: deleteResource (DELETE /api/v1/resources/{resource_id}) reversal: restoreResource (POST /api/v1/resources/{resource_id}/restore) window: 'Workspace trash keeps deleted resource roots for 30 days; each item shows when it expires; a background purge can permanently remove expired trash.' window_source: https://dokki.one/pub/docs/trash-and-restore grade: verified caveat: Only the deleted ROOT can be restored (descendants return an error); the creator of the root or a workspace admin can restore. - operation: updateResourceContent (PATCH /api/v1/resources/{resource_id}/content) reversal: 'snapshots — createResourceSnapshot before the write (or create_snapshot: true on the PATCH), then restore from listResourceSnapshots / getResourceSnapshot' window: 'Automatic snapshots: at most 50 per document, pruned after 30 days. Manual snapshots are kept until you delete them.' window_source: https://dokki.one/pub/docs/version-history grade: verified caveat: Snapshots exist for documents, tables and artifacts; the REST reference exposes create/list/get/delete snapshot endpoints but no explicit "restore snapshot" operation — recovery is a re-write from the snapshot content. - operation: publishResource (POST /api/v1/resources/{resource_id}/publish) / publishWorkspace reversal: unpublishResource (DELETE /api/v1/resources/{resource_id}/publish) window: not stated grade: documented - operation: createAgentRun (POST /api/v1/agent-runs) reversal: cancelAgentRun (POST /api/v1/agent-runs/{run_id}/cancel) window: not stated (cancels remaining steps; side effects already taken by the run are not undone) grade: documented - operation: archiveWorkspace (POST /api/v1/workspaces/{workspace_id}/archive) reversal: restore from the archived-workspaces screen ("Archive is not deletion. The workspace and its resources remain recoverable.") window: not stated window_source: https://dokki.one/pub/docs/archive-workspaces grade: documented caveat: No REST un-archive operation appears in the reference. - operation: createResourcePermission / removeResourcePermissions, addWorkspaceMember / removeWorkspaceMember reversal: the inverse operation (re-grant / re-add) window: n/a grade: documented - operation: emptyWorkspaceTrash (DELETE /api/v1/workspaces/{workspace_id}/trash) reversal: none — '"Emptying trash permanently deletes every trash root and its content ... This action is destructive and should be treated as final."' grade: irreversible - operation: deleteApiKey (DELETE /api/v1/api-keys/{key_id}) reversal: none — create a replacement key; the provider recommends an overlap window before revoking the old key grade: irreversible - operation: deleteOrg (DELETE /api/v1/orgs/{org_id}) reversal: not documented grade: irreversible - operation: MCP facade destructive actions (edit resource.delete, table column delete, share public, publish add) reversal: gated by requires_confirmation + confirm_token before execution; resource.delete then follows the Trash rules above grade: documented other_conventions: - name: Least-scope guidance detail: New public API keys default to read scopes; integrations should request the minimum scope set and use separate keys per Org. - name: Secrets hygiene detail: Never put a key in a browser bundle, public repository, URL query string or client-side logs; form GET responses carry public-form and webhook tokens that must not reach a browser. - name: Field aliases detail: Form endpoints accept snake_case and camelCase aliases (is_active / isActive, rotate_webhook_token / rotateWebhookToken). - name: Metadata replace semantics detail: PATCH /resources/{id} metadata replaces the whole object — send every key you intend to retain.