---
title: "React"
description: "ConnectKeyWidget, KeyWidget and the optional useFiducyKeys hook."
canonical_url: "https://fiducy.dev/docs/react"
markdown_url: "https://fiducy.dev/docs/react.md"
last_updated: "2026-11-02"
x_farming_labs_generated_preamble: true
---

# React
URL: /docs/react
LLM index: /llms.txt
Description: ConnectKeyWidget, KeyWidget and the optional useFiducyKeys hook.

# React

```ts
import { ConnectKeyWidget, KeyWidget, saveConnectedKey } from '@fiducy/sdk/react';
import { useFiducyKeys } from '@fiducy/sdk/react-query'; // optional
```

## Setup

`ConnectKeyWidget` and `KeyWidget` need only React. Nothing else to install.

`useFiducyKeys` is optional and lives in `@fiducy/sdk/react-query`. Use it if your app already runs TanStack Query; it needs `@tanstack/react-query` and a `QueryClientProvider` above it:

```bash
bun add @tanstack/react-query
```

```tsx title="src/app/providers.tsx"
'use client';

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useState } from 'react';

export function Providers({ children }: { children: React.ReactNode }) {
  const [queryClient] = useState(() => new QueryClient());
  return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
}
```

Without TanStack Query, list keys with a plain `fetch('/api/fiducy/keys')` and revoke with `DELETE /api/fiducy/keys/:keyID` (see [Server SDK](/docs/server)).

## ConnectKeyWidget

Renders the gateway iframe and, once the user saves a key, posts the handle to your server's Fiducy route.

```tsx
<ConnectKeyWidget
  gatewayURL="https://gateway.yourapp.com"
  appID="app_..."
  provider="openai"
  onConnected={(key) => console.log('connected', key.keyID)}
  onError={(message) => setError(message)}
/>
```

| Prop | Type | Notes |
| --- | --- | --- |
| `gatewayURL` | `string` | Your gateway |
| `appID` | `string` | Public app ID |
| `provider` | `'openai' \| 'anthropic' \| 'gemini' \| 'openrouter'` | Which provider this key is for |
| `basePath` | `string` | Your Fiducy route. Default `/api/fiducy` |
| `onConnected` | `(key) => void` | After your server saved the handle |
| `onError` | `(message) => void` | Widget or save errors |
| `className` | `string` | Applied to the wrapper |

The iframe only loads on origins listed in your app's allowed origins.

## useFiducyKeys(basePath?)

From `@fiducy/sdk/react-query`. Refreshes on its own when `ConnectKeyWidget` saves a key.

```tsx
const { keys, isLoading, error, refresh, revoke } = useFiducyKeys();
```

| Field | Type |
| --- | --- |
| `keys` | `{ keyID, provider, createdAt }[]` |
| `isLoading` | `boolean` |
| `error` | `string \| null` |
| `refresh` | `() => Promise<void>` |
| `revoke` | `(keyID) => Promise<void>` |

The list is cached under `fiducyKeysQueryKey(basePath)`, so you can invalidate it from your own mutations:

```tsx
import { fiducyKeysQueryKey } from '@fiducy/sdk/react-query';

queryClient.invalidateQueries({ queryKey: fiducyKeysQueryKey() });
```

## KeyWidget

The bare widget without the server save. Use it when you store handles your own way.

```tsx
<KeyWidget gatewayURL="..." appID="..." onHandle={(handle, record) => save(handle, record)} />
```

Outside React, `@fiducy/widget` exports `mountKeyWidget({ gatewayURL, appID, container, onHandle, onError })`.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
