Skip to content

API and integrations

Developer-facing screens: API keys, webhooks and an integrations directory.

Installation & usage

npx @youj/cli add app-api-keys

Also 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:

apiKeys-view.tsx
'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
      }}
    />
  )
}

Reference

Props26 props, 4 types

Props

ApiKeys props
PropType
themeThemeInput

A theme to force on the block. Default: none, so it inherits the app's (YoujProvider or a ThemeScope around it).

–
defaultEnvEnv
'live''test'

The environment shown when uncontrolled.

default 'live'

'live'
envEnv
'live''test'

The environment shown, controlled. Pair it with onEnvChange.

–
onEnvChange(env: Env) => void

Called with the environment the switch picks.

–
embeddedboolean

A 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
productstring

The product the keys are for, in the copy ("authenticate your server with …"). Prefer brand.

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.

–
headingLevel1 | 2 | 3

The title's level.

default 1

1
localestring

Formats relative times and counts. Default: the app's locale (YoujProvider's locale), else en-US.

–
keysApiKey[]

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
resourcesstring[]

The resources a key can be granted read or write on.

default Charges, Customers, Payouts, Webhooks

Charges, Customers, Payouts, Webhooks
expiriesApiKeyExpiry[]

The expiry choices in the create dialog; 'never' reads as no expiry.

default never, 30 days, 90 days, a year

never, 30 days, 90 days, a year
navApiKeysNavLink[]

The top bar's links (standalone only).

default the demo's five, on API keys

the demo's five, on API keys
nowDate | number

"Now", for "last used" times and the unused count.

default a fixed demo instant

a fixed demo instant
onCreate(key: ApiKeyDraft) => Promise<string> | string

Creates 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> | string

Rolls a key's secret on your server and returns the new one. Default: a demo random secret.

–
onRevoke(key: ApiKey) => Promise<unknown> | unknown

Revokes a key; resolve when it's gone, throw to show why it failed. Default: a short demo wait.

–
loadingboolean

Shows skeleton rows in place of the table while keys load.

default false

false
emptyReactNode

Replaces the empty state shown when an environment has no keys.

–
errorReactNode

A load failure, shown over the table with a Retry button when onRetry is set.

–
onRetry() => void

Called from the error's Retry button.

–
copyPartial<ApiKeysCopy>

Any of the page's strings, to rewrite or translate.

–
defaultCreateOpenboolean

Whether the create-key dialog is open when uncontrolled; true opens it with the page.

default false

false
createOpenboolean

Whether the create-key dialog is open, controlled. Pair it with onCreateOpenChange.

–
onCreateOpenChange(open: boolean) => void

Called with the create-key dialog's new open state.

–
linkComponentElementType

Renders the top bar's links, e.g. Next.js Link.

default 'a'

'a'

ApiKey

ApiKey props
PropType
idRequiredstring–
nameRequiredstring

What uses the key, as its owner named it.

–
envRequiredEnv
'live''test'
–
last4Requiredstring

The secret's last four characters; the rest is never shown again.

–
scopesRequiredScopes–
createdByRequiredstring–
lastUsedRequirednumber | null

When it last signed a request, in epoch ms; null if never.

–
expiresRequiredstring

One of the expiries values.

–
trafficRequirednumber[]

Requests a day over the last seven days, oldest first.

–

ApiKeyDraft

ApiKeyDraft props
PropType
nameRequiredstring–
envRequiredEnv
'live''test'
–
scopesRequiredScopes–
expiresRequiredstring–

ApiKeyExpiry

ApiKeyExpiry props
PropType
valueRequiredstring–
labelRequiredstring–
ApiKeysNavLink props
PropType
labelRequiredstring–
hrefRequiredstring–
currentboolean

The 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.

titledescriptionenvironmentlivetestcreateKeyhealthliveKeystestKeysactiverequestslastWeekunusedunusedNotekeysRegionemptyTitleemptyDescriptionemptyActionloadingfootnoterevokeTitlerevokeDescriptionrevokeConfirmtablenamekeyscopescreatedBylastUsedtrafficactionsactionsFornoExpiryexpiresInendingfullAccesstrafficLabelcopyIdrollrevokeneverjustNownewKeynewKeyDescriptionreadyreadyDescriptionnamePlaceholdernameRequiredpermissionspermissionsDescriptionpermissionsGroupresourceAccessnonereadwritepermissionRequiredexpirescancelmintingcreatedyoucopyNowshownOncesecretcopySecretcopiedcopyFailedsavedrolledTitlerolledDescriptionerrorTitleretryfailedbrandBadgenav
Built from22 components
Accessibilitylandmarks, 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.