Reference

Admin API

Every endpoint under /_/api/admin/*, grouped by purpose.

The admin UI and GitOps integrations talk to this surface. All mutation routes require a session cookie (issued by POST /_/api/admin/login). Sessions are IP-bound — a token is rejected from a different source IP — and default to a 4-hour TTL (DGP_SESSION_TTL_HOURS).

Endpoints documented here are admin only. The S3-compatible API lives under / and is documented by AWS themselves.

Authentication and session

MethodPathPurpose
POST/_/api/admin/loginBootstrap password → session cookie
POST/_/api/admin/login-asLog in as an IAM user (access_key_id + secret_access_key)
POST/_/api/admin/logoutEnd the current session
GET/_/api/admin/session{valid, admin_gui}
POST/_/api/admin/session/browser-connectIssue a limited browser-lift session for an IAM non-admin (S3 browse only)
POST/_/api/admin/session/open-browser-connectBrowser-lift session when authentication: none
GET/_/api/whoami{mode, version, user, external_providers}
POST/_/api/admin/recover-dbReset the config DB when the bootstrap hash doesn't match (public, rate-limited)
PUT/_/api/admin/passwordChange the bootstrap password — re-encrypts the SQLCipher DB atomically

Configuration — three scopes

All three scopes route through the same apply_config_transition path, so hot-reload semantics are identical no matter which level you use.

Field-level (legacy GUI forms)

MethodPathPurpose
GET/_/api/admin/configRuntime config as flat JSON
PUT/_/api/admin/configPartial JSON update

Section-level

MethodPathBodyPurpose
GET/_/api/admin/config/section/:name[?format=yaml]Section slice as JSON or YAML
PUT/_/api/admin/config/section/:nameRFC 7396 JSON Merge PatchPartial section update
POST/_/api/admin/config/section/:name/validatesame as PUTDry-run: {ok, warnings[], diff, requires_restart}

:nameadmission / access / storage / advanced. Unknown names → 404.

Merge-patch semantics: keys missing from the body are preserved; null deletes; objects merge recursively. Secrets round-trip (GET → edit → PUT never clears credentials).

Document-level (GitOps)

MethodPathBodyPurpose
GET/_/api/admin/config/export[?section=<name>]Canonical YAML (secrets redacted)
GET/_/api/admin/config/declarative-iam-exportProject current DB IAM into access: YAML fragment (for declarative GitOps seeding; see declarative-iam.md)
POST/_/api/admin/config/declarative-iam-validate{yaml: <access fragment>}Dry-run the declarative IAM reconcile (diff_iam preview, zero DB writes)
POST/_/api/admin/config/declarative-iam-apply{yaml: <access fragment>}Atomic single-transaction IAM reconcile from the YAML fragment
GET/_/api/admin/config/defaults[?section=<name>]JSON Schema (for YAML LSP and Monaco)
POST/_/api/admin/config/validate{yaml: <doc>}Dry-run full-document apply
POST/_/api/admin/config/section/:name/validate{<section-body>}Dry-run section apply; in declarative mode warns with diff_iam preview (see declarative-iam.md)
POST/_/api/admin/config/apply{yaml: <doc>}Atomic full-document apply + persist
POST/_/api/admin/config/tracesynthetic request bodyEvaluate against the admission chain
GET/_/api/admin/config/trace?method=&path=&...Query-param variant (bookmarkable trace URLs)
POST/_/api/admin/config/sync-nowForce an immediate config-DB pull from the sync bucket

Full-document apply returns {applied, persisted, requires_restart, warnings, persisted_path}. Persist failure returns HTTP 500, not 200+warning — GitOps pipelines can't mistake a half-applied state for a clean success.

CLI wrapper:

export DGP_BOOTSTRAP_PASSWORD=...
deltaglider_proxy config apply deltaglider_proxy.yaml --server https://s3.acme.example

Backends

MethodPathPurpose
GET/_/api/admin/backendsList named backends
POST/_/api/admin/backendsCreate; validates S3 creds upfront
DELETE/_/api/admin/backends/:nameRemove — refuses to delete the default or in-use backends
POST/_/api/admin/test-s3Test an arbitrary S3 connection without persisting
GET / POST/_/api/admin/bucketsList bucket origins / create a bucket on a backend
POST/_/api/admin/buckets/:bucket/migrateMove a bucket's data to another backend as a durable, write-gated job — see Jobs

IAM (gated by iam_mode)

POST/PUT/DELETE return 403 { "error": "iam_declarative" } when access.iam_mode: declarative. Reads stay open for diagnostics.

MethodPathPurpose
GET / POST/_/api/admin/usersList / create
PUT / DELETE/_/api/admin/users/:idUpdate / delete
POST/_/api/admin/users/:id/rotate-keysRotate access keys
POST/_/api/admin/users/:id/cloneClone a user (new keys, copied permissions)
GET / POST/_/api/admin/groupsList / create
PUT / DELETE/_/api/admin/groups/:idUpdate / delete
POST/_/api/admin/groups/:id/cloneClone a group
POST/_/api/admin/groups/:id/membersAdd user to group
DELETE/_/api/admin/groups/:id/members/:user_idRemove user from group
GET/_/api/admin/iam/versionMonotonic IAM-index rebuild counter for deterministic diagnostics/tests
GET/_/api/admin/policiesList canned policy templates (public, no session)

External auth (OAuth / OIDC)

MethodPathPurpose
GET / POST/_/api/admin/ext-auth/providersList / create
PUT / DELETE/_/api/admin/ext-auth/providers/:idUpdate / delete
POST/_/api/admin/ext-auth/providers/:id/testProbe the .well-known endpoint
GET / POST/_/api/admin/ext-auth/mappingsList / create group mapping rules
PUT / DELETE/_/api/admin/ext-auth/mappings/:idUpdate / delete
POST/_/api/admin/ext-auth/mappings/previewPreview which groups a given identity would be assigned
GET/_/api/admin/ext-auth/identitiesList external identities (read-only, not gated)
POST/_/api/admin/ext-auth/sync-membershipsRe-evaluate mapping rules and sync group memberships
GET/_/api/admin/ext-auth/versionMonotonic external-auth rebuild counter (sibling of iam/version) for deterministic diagnostics/tests
POST/_/api/admin/migrateMigrate legacy bootstrap creds into an IAM user

OAuth redirect flow (public, no session)

MethodPathPurpose
GET/_/api/admin/oauth/authorize/:providerKick off OAuth (PKCE, state, nonce)
GET/_/api/admin/oauth/callbackProvider callback → issue session cookie

Full Backup

MethodPathPurpose
GET/_/api/admin/backupExport zip (manifest + config + IAM + secrets)
POST/_/api/admin/backupImport — atomic; all parts sha256-verified before any state change. Gated by iam_mode.

Response on POST carries per-resource counters: {users_created, users_skipped, groups_created, groups_skipped, memberships_created, external_identities_created, external_identities_skipped}.

external_identities are remapped through the imported user + provider ID maps. Orphaned records (user or provider didn't import) are dropped with a WARN log.

Legacy JSON-only import path is still supported for pre-v0.8.4 scripts.

Diagnostics and usage

MethodPathPurpose
POST/_/api/admin/usage/scanTrigger a prefix-size scan
GET/_/api/admin/usageRead the cached usage tree
GET/_/api/admin/deltaspace/savingsPer-prefix reference-aware delta savings (30s in-memory cache)
GET/_/api/admin/diagnostics/delta-efficiencyCached delta-efficiency report for a bucket's deltaspaces
POST/_/api/admin/diagnostics/delta-efficiency/scanTrigger a delta-efficiency scan
POST/_/api/admin/diagnostics/delta-efficiency/verifyVerify reconstructed objects against stored deltas
GET/_/api/admin/diagnostics/scan[/status]Integrity-scan status (per-bucket or all-buckets map)
POST/_/api/admin/diagnostics/scan/start / /stopStart / stop a background integrity scan
GET/_/api/admin/diagnostics/scan/streamSSE stream of live scan progress
GET/_/api/admin/audit[?limit=N]Snapshot of the in-memory audit ring, newest first. Bounded (default 500, override DGP_AUDIT_RING_SIZE). Stdout tracing::info! is still the long-term audit source.
GET/_/api/admin/event-outbox[?status=failed&limit=N&offset=N&sort=occurred_at&order=desc]Paged durable object-event outbox rows plus status counts. Delivery is background-only; delivered rows default to 24h/10,000-row retention; see event-outbox.md.
POST/_/api/admin/event-outbox/:id/requeueRequeue a single failed outbox row for re-delivery
POST/_/api/admin/event-outbox/requeueBulk-requeue failed outbox rows
GET / PUT / DELETE/_/api/admin/session/s3-credentialsPer-session S3 credential store for the browse panel

Object operations (browse panel)

Server-side helpers behind the embedded S3 browser's bulk actions.

MethodPathPurpose
GET/_/api/admin/objects/listList all keys under a bucket/prefix
POST/_/api/admin/objects/copyServer-side copy of selected objects
POST/_/api/admin/objects/moveServer-side move (copy + delete)
POST/_/api/admin/objects/deleteBulk delete selected objects
GET/_/api/admin/objects/zipStream selected objects as a ZIP

Jobs — one surface for everything background

Replication rules, lifecycle rules, and one-off maintenance jobs (re-encrypt, bucket migration) share a single read+action API. Job ids are namespaced: replication:<rule>, lifecycle:<rule>, maintenance:<n>. Rules stay YAML-authoritative under storage.replication.rules[] / storage.lifecycle.rules[]; maintenance one-offs are DB-born. See replication.md and lifecycle.md for rule shapes and guardrails.

MethodPathPurpose
GET/_/api/admin/jobsEvery job as one normalized row: kind, scope, status (idle / queued / running / cancelling / succeeded / failed / cancelled), pause flag, progress, last run.
GET/_/api/admin/jobs/:id/runs?limit=NRecent runs, newest first. A maintenance one-off synthesizes a single run — the job IS its run.
GET/_/api/admin/jobs/:id/failures?limit=NRecent per-object failures, newest first.
POST/_/api/admin/jobs/:id/pause / /resumeReplication and lifecycle rules. Persists across restarts.
POST/_/api/admin/jobs/:id/run-nowReplication and lifecycle rules. Synchronous; 409 when paused or already leased.
POST/_/api/admin/jobs/:id/previewLifecycle only — dry-run candidate keys. Read-only: no deletes, no history rows.
POST/_/api/admin/jobs/:id/cancelMaintenance only — cancel a queued or running one-off. A pre-flip migrate cancel unwinds cleanly.
POST/_/api/admin/jobs/reencrypt{"buckets": [...]} (max 100) → one durable re-encrypt job per bucket: {started: [{bucket, job_id}], errors: [...]}.
POST/_/api/admin/buckets/:bucket/migrate{"target_backend": "...", "delete_source": false}202 Accepted + {job_id, id: "maintenance:<n>", bucket, from_backend, to_backend}.
GET/_/api/admin/jobs/bucket/:bucketThe bucket's active maintenance job, if any — status/phase/counts only, no config detail. Session-light: browser-lift sessions can read it (powers the busy banner in the object browser).

Actions outside a kind's capability matrix return 405 with the supported list. Lifecycle preview is intentionally read-only; scheduler and run-now executions persist history/failure rows in the config DB and use per-rule leases so instances sharing the DB never double-execute.

Write gate: while a re-encrypt or migrate job is active, S3 writes to that bucket return 503 SlowDown (SDKs back off and retry); reads pass untouched. The gate engages at job creation and lifts when the job finishes (for migrations, the moment the bucket flips to the new backend).

Resource limits (env vars)

VariableDefaultPurpose
DGP_MAX_OBJECT_SIZE100 MiBLargest single object (and, per upload, largest multipart upload).
DGP_MAX_MULTIPART_UPLOADS1000Maximum concurrent multipart uploads across the proxy.
DGP_MAX_TOTAL_MULTIPART_BYTESmax_object_size × max_uploads / 4Global in-flight byte cap across all multipart uploads. Protects against the C3 DoS pattern where many uploads accumulate without completing. Reject with SlowDown when exceeded.
DGP_MULTIPART_IDLE_TTL_HOURS24Idle-TTL for incomplete multipart uploads. The periodic sweeper drops uploads with no UploadPart activity for this long (excluding uploads currently being completed).
DGP_AUDIT_RING_SIZE500In-memory audit ring capacity.
DGP_SESSION_TTL_HOURS4Admin session cookie lifetime.

Keyboard shortcuts (app-wide)

Reachable via ? anywhere in the UI (when focus is not in an input). is Ctrl on non-Apple platforms.

KeyScopeAction
⌘,GlobalOpen Settings
⌘/GlobalOpen Docs
?GlobalThis shortcuts reference
/ Object browserMove between objects and folders
Enter / Object browserOpen folder / inspect object
/ BackspaceObject browserGo up one folder
Home / EndObject browserJump to first / last row
EscObject browserClose inspector, or go up one folder
⌘KSettingsCommand palette (fuzzy nav + shell actions)
⌘SSettingsApply the currently-visible dirty section
/ + Enter, EscPaletteNavigate / run / close

Operational endpoints (no admin prefix)

Unauthenticated — needed for load-balancer probes and Prometheus:

MethodPathPurpose
GET/_/health{status, peak_rss_bytes, cache_*} — no version (anti-fingerprinting)
GET/_/metricsPrometheus text format

Session-protected (reveals per-bucket sizes):

MethodPathPurpose
GET/_/statsAggregate storage stats, 10s server-side cache