API and integrations
Developer-facing screens: API keys, webhooks and an integrations directory.
Installation & usage
npx @youj/cli add app-api-keysAlso installs alert, alert-dialog, app-page, async-button, avatar, badge, button, dialog, dropdown-menu, empty, field, icon-copy, icon-key, icon-more-horizontal, icon-plus, icon-refresh, icon-shield, icon-trash, input, presence-list, reveal, scramble-text, segmented-control, select, skeleton, sliding-indicator, sparkline, stat-card, table, toggle-group, youj-core, youj-presets, youj-ui-core.
The CLI copies the block to blocks/app/api-keys.tsx with every component it uses, so it’s yours to edit.
Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:
'use client'
import Link from 'next/link'
import { ApiKeys, type ApiKeysProps } from '@/blocks/app/api-keys'
export function ApiKeysView({ env, keys, resources, expiries }: Pick<ApiKeysProps, 'env' | 'keys' | 'resources' | 'expiries'>) {
return (
<ApiKeys
env={env}
keys={keys}
resources={resources}
expiries={expiries}
copy={{ title: 'API keys' }}
linkComponent={Link}
onEnvChange={(env) => {
// your code
}}
onCreate={async (key) => {
// await your API here; the block shows progress until it settles
}}
onRoll={async (key) => {
// await your API here; the block shows progress until it settles
}}
/>
)
}Description
Manage API keys in a table with scopes and recent use, and a dialog for creating a new key that shows its secret once.
Manage API keys in a table with scopes and recent use, and a dialog for creating a new key that shows its secret once.
The create-key flow: name the key, choose None, Read or Write for each resource, pick an expiry, then copy the secret, which is shown once. A key with no access, or without a name, is refused before anything is sent.
The create-key flow: name the key, choose None, Read or Write for each resource, pick an expiry, then copy the secret, which is shown once. A key with no access, or without a name, is refused before anything is sent.
Manage webhook endpoints with delivery status and subscribed events in one table, a delivery log with filters and a sheet for editing an endpoint.
Manage webhook endpoints with delivery status and subscribed events in one table, a delivery log with filters and a sheet for editing an endpoint.
Help users find integrations and review what each one can access before installing it.
Help users find integrations and review what each one can access before installing it.
One connected app as a page: a sample of what it posts, the connection's details with a status menu to pause, reconnect or disconnect, and a switch for each permission it holds.
One connected app as a page: a sample of what it posts, the connection's details with a status menu to pause, reconnect or disconnect, and a switch for each permission it holds.
Code
API Keys, the API keys story: the files youj add writes.
blocks/app
Reference
Props26 props, 4 types
Props
| Prop | Type | |
|---|---|---|
theme | ThemeInputA theme to force on the block. Default: none, so it inherits the app's (YoujProvider or a ThemeScope around it). | – |
defaultEnv | Env'live''test'The environment shown when uncontrolled. default 'live' | 'live' |
env | Env'live''test'The environment shown, controlled. Pair it with | – |
onEnvChange | (env: Env) => voidCalled with the environment the switch picks. | – |
embedded | booleanA page in your app's frame: the shared page header (AppPage) and the frame's gutter, across the whole width, with no top bar of its own. default true | true |
product | stringThe product the keys are for, in the copy ("authenticate your server with …"). Prefer default 'Ledger' | 'Ledger' |
brand | { name: string; logo?: ReactNode }The product's name and mark: the top bar's brand and the name in the copy. Default: Ledger, with an "L/" mark. | – |
headingLevel | 1 | 2 | 3The title's level. default 1 | 1 |
locale | stringFormats relative times and counts. Default: the app's locale (YoujProvider's | – |
keys | ApiKey[]The keys, both environments; the block keeps its own copy as keys are created, rolled and revoked. default the demo's four live keys | the demo's four live keys |
resources | string[]The resources a key can be granted read or write on. default Charges, Customers, Payouts, Webhooks | Charges, Customers, Payouts, Webhooks |
expiries | ApiKeyExpiry[]The expiry choices in the create dialog; default never, 30 days, 90 days, a year | never, 30 days, 90 days, a year |
nav | ApiKeysNavLink[]The top bar's links (standalone only). default the demo's five, on API keys | the demo's five, on API keys |
now | Date | number"Now", for "last used" times and the unused count. default a fixed demo instant | a fixed demo instant |
onCreate | (key: ApiKeyDraft) => Promise<string> | stringCreates a key on your server and returns its full secret, which is shown once. Default: a demo wait and a random secret. | – |
onRoll | (key: ApiKey) => Promise<string> | stringRolls a key's secret on your server and returns the new one. Default: a demo random secret. | – |
onRevoke | (key: ApiKey) => Promise<unknown> | unknownRevokes a key; resolve when it's gone, throw to show why it failed. Default: a short demo wait. | – |
loading | booleanShows skeleton rows in place of the table while keys load. default false | false |
empty | ReactNodeReplaces the empty state shown when an environment has no keys. | – |
error | ReactNodeA load failure, shown over the table with a Retry button when | – |
onRetry | () => voidCalled from the error's Retry button. | – |
copy | Partial<ApiKeysCopy>Any of the page's strings, to rewrite or translate. | – |
defaultCreateOpen | booleanWhether the create-key dialog is open when uncontrolled; true opens it with the page. default false | false |
createOpen | booleanWhether the create-key dialog is open, controlled. Pair it with | – |
onCreateOpenChange | (open: boolean) => voidCalled with the create-key dialog's new open state. | – |
linkComponent | ElementTypeRenders the top bar's links, e.g. Next.js default 'a' | 'a' |
ApiKey
| Prop | Type | |
|---|---|---|
idRequired | string | – |
nameRequired | stringWhat uses the key, as its owner named it. | – |
envRequired | Env'live''test' | – |
last4Required | stringThe secret's last four characters; the rest is never shown again. | – |
scopesRequired | Scopes | – |
createdByRequired | string | – |
lastUsedRequired | number | nullWhen it last signed a request, in epoch ms; null if never. | – |
expiresRequired | stringOne of the | – |
trafficRequired | number[]Requests a day over the last seven days, oldest first. | – |
ApiKeyDraft
| Prop | Type | |
|---|---|---|
nameRequired | string | – |
envRequired | Env'live''test' | – |
scopesRequired | Scopes | – |
expiresRequired | string | – |
ApiKeyExpiry
| Prop | Type | |
|---|---|---|
valueRequired | string | – |
labelRequired | string | – |
ApiKeysNavLink
| Prop | Type | |
|---|---|---|
labelRequired | string | – |
hrefRequired | string | – |
current | booleanThe page you're on. | – |
Strings75 keys for copy
Strings
copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.
titledescriptionenvironmentlivetestcreateKeyhealthliveKeystestKeysactiverequestslastWeekunusedunusedNotekeysRegionemptyTitleemptyDescriptionemptyActionloadingfootnoterevokeTitlerevokeDescriptionrevokeConfirmtablenamekeyscopescreatedBylastUsedtrafficactionsactionsFornoExpiryexpiresInendingfullAccesstrafficLabelcopyIdrollrevokeneverjustNownewKeynewKeyDescriptionreadyreadyDescriptionnamePlaceholdernameRequiredpermissionspermissionsDescriptionpermissionsGroupresourceAccessnonereadwritepermissionRequiredexpirescancelmintingcreatedyoucopyNowshownOncesecretcopySecretcopiedcopyFailedsavedrolledTitlerolledDescriptionerrorTitleretryfailedbrandBadgenavAccessibilitylandmarks, dialogs, secrets, status
Accessibility
Each screen is a main with labelled sections. API keys and Webhooks are tables whose row actions sit in a menu with arrow-key navigation. The create-key dialog and the secret reveal trap focus and close with Escape. Webhooks’ delivery filters use aria-pressed and its event picker is a labelled group. Integrations has a labelled search field, a category rail of toggle buttons (aria-pressed), a result count in a status region, and a detail sheet that lists the access an app asks for. The integration detail is a labelled region with a breadcrumb, a status menu button that names the current status, and a labelled switch for every permission (switches are disabled once the app is disconnected). Each resource in the create-key dialog is a labelled group of None, Read and Write buttons. Links and buttons are real a and button elements with the kit’s focus ring.