Two adjacent admin surfaces: API key + webhook management (04g), and data-export / account-portability (04i). Both compose existing primitives — the patterns are in the wiring, the security copy, and the destructive-action flow.
When to use
API keys: programmatic access to your account — server-side
integrations, scripts, CI. Distinct from per-user OAuth tokens
(account login flow); these are long-lived bearer tokens scoped
to a workspace. Webhooks deliver events to a URL.
Data export: GDPR / CCPA / SOC-2 compliance + workspace
migration. The user requests, the system queues, an email
arrives with a download link.
API keys list
The active-keys list. Each row carries a name, prefix (last 4 chars only — never the full secret), scope tag, last-used time, and a kebab menu (Rotate / Revoke). "Create key" header action.
API keys3 active · last rotated 12 days agosk_live_…A4F2 · last used 4 minutes agoread · writesk_live_…9821 · last used 2 hours agoreadsk_test_…7f0e · last used 18 days agotest
Create key — one-time reveal
The just-created key shown once. After this view closes, the secret is not retrievable; only the prefix shows in the list. Copy button + alert explaining the one-shot semantics.
Your new API keyCopy it now — it won't be shown againThis is the only time we'll show this key.Store it in your secrets manager now. If you lose it, you'll need to revoke this key and create a new one.
Webhooks list
Endpoints + the events they subscribe to + last delivery status. Failed deliveries surface as a danger tag with a "Retry" affordance per row.
Webhooks2 endpoints · 1 failing5 events · last delivery 3 minutes ago200 OK3 events · last attempt 2 hours ago · 3 retries503
Data export — request
Compliance / portability flow. User picks scope (full workspace vs. just my data) + format, the system queues the job, an email arrives with a download link. Async, not synchronous.
Export your dataWe'll email you when the archive is readyExports are usually ready within 1 hour.Large workspaces (≥ 1M records) can take up to 24 hours. We'll email kim@example.com with a download link valid for 7 days.
Export history
The user's recent export jobs. Status tags (Queued / Running / Ready / Expired). "Ready" rows show a Download button until the link expires; expired rows are still visible for audit but disabled.
Recent exportsRequested 12 minutes ago · 1.2M recordsRunningReady 2 hours ago · 4.2 MB · expires in 6 daysReadyReady 14 days ago · link expiredExpired
Composition rules
Show the prefix, never the full key — the list view always renders sk_live_…A4F2. The full secret only ever appears in the one-time reveal card; if the user lost it, they have to revoke + recreate. Storing the full key in the DB plaintext is the smell this convention prevents.
One-time reveal needs a confirmation gate — the "I've stored it safely" button is the user's acknowledgment that they grabbed the key. Closing the modal/page without clicking it should still hide the secret (security default).
Webhook failures are first-class — a 503 tag + Retry button is the canonical row. Hiding failures in a sub-page guarantees they get ignored.
Data export is async, not sync — never block the UI on a "Generate now" call. Queue the job; email the link. Users with 1M-record workspaces shouldn't see a spinner.
Download links expire — 7 days is typical; longer for SOC-2 retention requirements. The UI shows the expiry and the "Expired" state retains audit visibility (don't delete the row).
Scope selection is policy-aware — "Entire workspace" must be admin-gated; non-admins see only "Just my data" (GDPR Article 15). Don't show the option then 403 the request.
Format choices match the consumer — JSON archive for re-import, NDJSON for streaming consumers, CSV for spreadsheets. Three is enough; PDF or XLSX adds support tickets without value.