React SDK (@hyperyai/sdk)

Install @hyperyai/sdk, configure HyperyProvider, and find every component, hook and helper the SDK exports — auth, workspaces, wallet, checkout, error handling, streaming and tokens.

@hyperyai/sdk is a React/Next.js library for apps that sign users in through Hypery and bill them through Hypery. The API is intentionally Clerk-like: wrap your app in one provider, then use <SignedIn> / <SignedOut>, <UserButton>, useUser(), and friends. On top of auth it ships workspace switching, a wallet, one-click checkout and subscriptions, classified billing errors with ready-made modals, and SSE streaming helpers.

Installation

Install the package from npm. It ships compiled JavaScript plus type declarations, so no extra transpilation step is required.

npm install @hyperyai/sdk

All components and hooks are client components ('use client'). Everything is imported from the package root:

import { HyperyProvider, useAuth, SignedIn, HyperyModals } from '@hyperyai/sdk';

HyperyProvider

Wrap your app once in HyperyProvider. Every component and hook reads from it; using a hook outside it throws useHyperyAuth must be used within HyperyProvider.

// app/providers.tsx
'use client';
 
import { HyperyProvider, HyperyModals } from '@hyperyai/sdk';
 
export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <HyperyProvider
      config={{
        clientId: process.env.NEXT_PUBLIC_OAUTH_CLIENT_ID!,
        redirectUri: process.env.NEXT_PUBLIC_REDIRECT_URI!, // e.g. https://yourapp.com/callback
        gatewayUrl: 'https://hypery.ai',
        scopes: ['read', 'write', 'ai:chat', 'billing:read'],
        storage: 'localStorage',
        interactionMode: 'auto',
      }}
    >
      {children}
      {/* Optional: auto-open billing / re-auth modals (see Error handling) */}
      <HyperyModals />
    </HyperyProvider>
  );
}
PropTypeDescription
configHyperyAuthConfigRequired. See the table below.
childrenReactNodeRequired. Your app.

Config options (HyperyAuthConfig)

OptionTypeDefaultDescription
clientIdstring—Required. Your OAuth app's client id.
redirectUristring—Required. OAuth redirect URI registered on the app. The provider must be mounted on this page (it handles the ?code= callback).
gatewayUrlstring—Required. Hypery base URL, e.g. https://hypery.ai.
scopesstring[]['read', 'write', 'ai:chat', 'ai:completions', 'ai:models', 'ai:images', 'billing:read']OAuth scopes to request. See Scopes.
storage'localStorage' | 'sessionStorage' | 'memory''localStorage'Where tokens and the cached user live. With memory, tokens stay in memory but the short-lived PKCE verifier + state go to sessionStorage (in-memory fallback) so the redirect login can complete; they're cleared after the exchange.
interactionMode'auto' | 'popup' | 'redirect''auto'How interactive steps of the checkout flow are shown. auto = popup on desktop, redirect on mobile / blocked popups. Popup mode needs a same-origin redirectUri.
onUnauthorized() => void—Called when an authenticatedFetch request is still 401 after one silent-refresh retry. authRequired is set either way.
onRestricted(error: ParsedError) => void—Called when an authenticatedFetch request returns a 402/429 billing restriction with a JSON body. restriction is set either way.

What the provider does

  • Callback handling — on load, if the URL has ?code=, it exchanges the code (PKCE, no client secret) after verifying the returned state against the one stored for this login attempt (a mismatch rejects without exchanging — popup callbacks are checked the same way), stores the tokens, fetches /api/user/me, and strips the query string. Otherwise it restores the stored session.
  • Silent refresh — getAccessToken() refreshes when the stored token is within 60 seconds of expiry. Concurrent callers share one in-flight refresh. A failed refresh clears the session.
  • Logout — logout() revokes the access token (POST /api/oauth/revoke), clears storage, sets a flag so the next login forces account selection, and navigates to /. It only signs out of your app.

Gateway access tokens last 1 hour and come with a refresh token. You rarely handle tokens yourself — call authenticatedFetch() or getAccessToken() when you need to call the API.

A minimal callback page, if your redirectUri is a dedicated route:

// app/callback/page.tsx
'use client';
 
import { useAuth } from '@hyperyai/sdk';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
 
export default function Callback() {
  const { isAuthenticated, isLoading } = useAuth();
  const router = useRouter();
  useEffect(() => {
    if (!isLoading && isAuthenticated) router.replace('/');
  }, [isAuthenticated, isLoading, router]);
  return <p>Signing you in…</p>;
}

useAuth / useHyperyAuth

The full auth context. useAuth is an alias of useHyperyAuth (same function).

import { useAuth } from '@hyperyai/sdk';
 
function Chat() {
  const { isAuthenticated, login, authenticatedFetch, gatewayUrl } = useAuth();
 
  const send = async () => {
    const res = await authenticatedFetch(`${gatewayUrl}/api/v1/chat/completions`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ model: 'openai/gpt-4o-mini', messages: [{ role: 'user', content: 'hi' }] }),
    });
    // 401 → refreshed + retried once; 402/429 → `restriction` set for <HyperyModals>
    console.log(await res.json());
  };
 
  return isAuthenticated ? <button onClick={send}>Send</button> : <button onClick={login}>Sign in</button>;
}

Returns AuthContextValue:

FieldTypeDescription
userUser | null{ id, email, name, image? } of the signed-in user.
isAuthenticatedbooleantrue when user is set.
isLoadingbooleantrue while the session is being restored or the callback exchanged.
errorstring | nullLast auth error message.
isLoggingOutbooleantrue from the start of logout() (keeps <Protect> from re-triggering login).
login(options?: LoginOptions) => Promise<void>Full-page redirect to the OAuth authorize page. Safe as onClick={login} (non-option arguments are ignored).
loginPopup(options?: LoginOptions) => Promise<PopupAuthResult>Log in via a centered popup. Resolves { ok, blocked, cancelled }; fall back to login() when blocked.
signUp() => Promise<void>Like login, with prompt=select_account.
logout() => Promise<void>Revoke, clear, redirect to /.
refreshAuth() => Promise<void>Reload the user from the gateway.
getAccessToken(forceRefresh?: boolean) => Promise<string | null>A valid access token (refreshing if needed), or null when signed out.
authenticatedFetch(input, init?) => Promise<Response>fetch with the bearer token. On 401 it force-refreshes and retries once, then sets authRequired; on 402/429 it sets restriction. Always returns the Response.
restrictionParsedError | nullBilling restriction from the last authenticatedFetch.
clearRestriction() => voidClear restriction.
authRequiredbooleanA 401 survived the refresh retry.
clearAuthRequired() => voidClear authRequired.
interactionMode'popup' | 'redirect'config.interactionMode resolved for this environment.
clientId, gatewayUrl, redirectUristringThe values the provider was configured with.

LoginOptions:

FieldTypeDescription
provider'google' | 'github'Optional. Skip Hypery's hosted login page and go straight to this identity provider. Omit to show the hosted login page.
const { login, loginPopup } = useAuth();
 
<button onClick={() => login({ provider: 'github' })}>Continue with GitHub</button>

useUser

A narrow read of the context.

import { useUser } from '@hyperyai/sdk';
 
const { user, isLoading } = useUser();
ReturnsType
userUser | null
isLoadingboolean

Export reference

Every runtime export of @hyperyai/sdk, and where it is documented.

ExportKindDocs
HyperyProviderProviderHyperyProvider
useAuth, useHyperyAuthHookuseAuth
useUserHookuseUser
SignIn, SignUpComponentComponents
SignInForm, ModernAuthFormComponentComponents
AuthModal, AuthButtonComponentComponents
UserButton, UserProfileComponentComponents
SignedIn, SignedOut, Protect, RedirectToSignInComponentControl components
WorkspaceSwitcherComponentWorkspaces
useMemberships, useActiveWorkspaceHookWorkspaces
setActiveWorkspaceFunctionWorkspaces
useWalletHookBilling & wallet
useBuyerWalletHookBilling & wallet
BuyButton, SubscribeButtonComponentCheckout
useCheckout, useAppSubscription, useMarketplaceHookCheckout
planPriceCentsFunctionCheckout
HyperyModals, RestrictionModalComponentError handling
SpendingLimitAlert, InsufficientCreditsAlert, ErrorBoundaryComponentError handling
useErrorHookError handling
parseError, isSpendingLimitError, isInsufficientCreditsError, isPaymentMethodRequiredError, isPaymentDeclinedError, isAuthError, isPermissionDeniedError, isRateLimitError, isBillingRestriction, formatTimeUntilResetFunctionError handling
consumeSSEStream, parseSSEFrame, parseSSEErrorFunctionStreaming
TokenStorageClassTokens
getAuthorizationUrl, exchangeCodeForToken, refreshAccessToken, getUserInfoFunctionTokens

Exported types are listed in the Types reference.

The component screenshots on these pages are rendered from the auth-demo example app in hyperyai/hypery-examples:

Component gallery overview

Next steps