# SDK QuickStart

{% hint style="info" %}
This guide uses the sandbox environment. You'll need a mock credential to complete it — [generating-mock-credentials](https://docs.humanity.org/developer-guides-and-tutorials/generating-mock-credentials "mention")
{% endhint %}

The easiest way to integrate with Humanty is using our [humanity-org-react-sdk](https://docs.humanity.org/build-with-humanity/build-with-the-sdk-api/humanity-org-react-sdk "mention")

By the end of this guide, you have a React app where users authenticate with the **Sign in with Humanity** button and their biometric verification status shows up on screen. Under 10 minutes, start to finish.

***Sign in with Humanity*** works like Sign in with Google — same OAuth flow, same redirect pattern. What you get back is different: not just an attestation, but a signed biometric credential tied to a unique person.

## Before you start

You need:

* [Node 18](https://nodejs.org/en) or higher
* [Bun](https://bun.sh) — used throughout this quickstart
* Access to [Developer Portal](https://docs.humanity.org/developer-portal)  — register at [developers.humanity.org](https://developers.humanity.org/) &#x20;
* A sandbox credential for ***Palm Vein*** created at <https://app.sandbox.humanity.org/sandbox>.&#x20;

## **How this Quickstart works**

1. Register your app in the Developer Portal and get credentials
2. Install the React SDK
3. Configure your environment
4. Wrap your app with `HumanityProvider`
5. Add a sign-in button and biometric verification
6. Run the app

## Quick Start

{% stepper %}
{% step %}

### Get your credentials

Go to the [Humanity Developer Portal](https://developers.humanity.org/) and create an app. You'll need:

* `clientId` generated as you create the app — e.g. `app_xxx`
* `redirectUri` — the OAuth callback URL you'll register (e.g. `https://localhost:3000/callback`)

Under **Settings** register the `redirectUri` in this case `https://localhost:3000/callback` .

Also under **Settings** you'll also select which **scopes** your app will request. For this example we need to request ***Identity Information (identity:read)*** that contains **Palm Verifed** and ***OpenID Connect (openid)***.
{% endstep %}

{% step %}

### Create the project and install dependencies

Scaffold a new Vite + React + TypeScript project:

```bash
bun create vite hello-humanity-react-sdk-app --template react-ts
```

When prompted select "**no"** then

```shellscript
cd hello-humanity-react-sdk-app
```

Install the React SDK and its dependencies:

```bash
bun add @humanity-org/react-sdk react-router-dom
bun add -d vite-plugin-node-polyfills @types/node
```

The SDK uses Node crypto APIs internally — `vite-plugin-node-polyfills` makes these available in the browser. Update `vite.config.ts`:

```tsx
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nodePolyfills } from 'vite-plugin-node-polyfills';

export default defineConfig({
  plugins: [
    react(),
    nodePolyfills({
      include: ['crypto', 'buffer', 'stream', 'util'],
      globals: { Buffer: true, process: true },
    }),
  ],
  server: { port: 3000 },
});
```

{% endstep %}

{% step %}

### Configure your environment

Create a `.env.local` file at the project root:

```
VITE_HUMANITY_CLIENT_ID=app_your_client_id_here
VITE_HUMANITY_ENVIRONMENT=sandbox
VITE_REDIRECT_URI=http://localhost:3000/callback
```

{% hint style="warning" %}
Make sure you are using the `cliend_id` from the **sandbox** environment tab.
{% endhint %}
{% endstep %}

{% step %}

### Wrap your app with `HumanityProvider`

Replace `src/main.tsx` with:

```tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { HumanityProvider } from '@humanity-org/react-sdk';
import '@humanity-org/react-sdk/styles.css';
import './index.css';
import App from './App';

const clientId = import.meta.env.VITE_HUMANITY_CLIENT_ID;
const environment = import.meta.env.VITE_HUMANITY_ENVIRONMENT || 'sandbox';
const redirectUri = import.meta.env.VITE_REDIRECT_URI || window.location.origin + '/callback';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <HumanityProvider
        clientId={clientId}
        redirectUri={redirectUri}
        environment={environment as 'production' | 'sandbox'}
        storage="sessionStorage"
        onError={(error) => console.error('[Humanity]', error)}
      >
        <App />
      </HumanityProvider>
    </BrowserRouter>
  </React.StrictMode>,
);
```

{% hint style="info" %}
`BrowserRouter` must wrap `HumanityProvider` — the SDK uses the router to handle the OAuth return.
{% endhint %}
{% endstep %}

{% step %}

### Add authentication and biometric verification

Replace `src/App.tsx` with:

```tsx
import { Routes, Route, useNavigate } from 'react-router-dom';
import {
  HumanityConnect,
  useHumanity,
  useVerification,
  clearVerificationCache,
} from '@humanity-org/react-sdk';
import { useEffect } from 'react';

function IsHumanCheck() {
  const { verify, result, isLoading } = useVerification(); 
  useEffect(() => {  
    verify('is_human');
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
 
  const isHuman = result?.value === true;

  return (
    <div className="status-card">
      {isLoading && <p className="status-checking">Checking biometric status...</p>}
      {!isLoading && isHuman && <p className="status-verified">✓ Biometrically verified</p>}
      {!isLoading && !isHuman && <p className="status-unverified">✗ Not biometrically verified</p>}
      {!isLoading && (
        <button
          className="btn-secondary"
          onClick={() => { clearVerificationCache(); verify('is_human'); }}
        >
          Re-check
        </button>
      )}
    </div>
  );
}

function Home() {
  const { isAuthenticated, isLoading, logout } = useHumanity();

  if (isLoading) return <div className="screen"><p>Loading...</p></div>;

  if (!isAuthenticated) {
    return (
      <div className="screen">
        <h1>Humanity react-sdk-quickstart</h1>
        <p>Connect your Humanity account to check your biometric verification status.</p>
        <HumanityConnect
          mode="redirect"
          scopes={['openid', 'identity:read']}
          onError={(err) => console.error(err)}
        />
      </div>
    );
  }

  return (
    <div className="screen">
      <h1>Humanity react-sdk-quickstart</h1>
      <IsHumanCheck />
      <button className="btn-ghost" onClick={logout}>Sign out</button>
    </div>
  );
}

function Callback() {
  const { isAuthenticated, isLoading } = useHumanity();
  const navigate = useNavigate();

  useEffect(() => {
    if (!isLoading && isAuthenticated) navigate('/', { replace: true });
  }, [isAuthenticated, isLoading, navigate]);

  return <div className="screen"><p>Completing sign-in...</p></div>;
}

export default function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/callback" element={<Callback />} />
    </Routes>
  );
}
```

Replace `src/index.css` with:

```css
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: system-ui, -apple-system, sans-serif;
  background: #0a0a0a;
  color: #ededed;
  -webkit-font-smoothing: antialiased;
}

.screen {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  padding: 2rem;
  text-align: center;
}

.screen h1 {
  font-size: 1.75rem;
  font-weight: 600;
}

.screen p {
  color: #888;
  font-size: 0.95rem;
}

.status-card {
  border: 1px solid #2a2a2a;
  border-radius: 12px;
  padding: 2rem;
  width: min(100%, 360px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  background: #141414;
}

.status-checking {
  color: #666;
}

p.status-verified {
  font-weight: 600;
  font-size: 1.1rem;
  color: #4ade80;
}

p.status-unverified {
  font-weight: 600;
  font-size: 1.1rem;
  color: #f87171;
}

.btn-secondary {
  padding: 0.5rem 1.25rem;
  border: 1px solid #333;
  border-radius: 8px;
  background: #1f1f1f;
  color: #ededed;
  cursor: pointer;
  font-size: 0.875rem;
}

.btn-ghost {
  padding: 0.5rem 1.25rem;
  border: 1px solid #2a2a2a;
  border-radius: 8px;
  background: none;
  cursor: pointer;
  font-size: 0.875rem;
  color: #666;
}

.btn-secondary:hover { background: #2a2a2a; }
.btn-ghost:hover { background: #141414; }
```

{% endstep %}

{% step %}

### Run it

```shellscript
bun dev
```

Open <http://localhost:3000>. Click the ***Sign-in with humanity button***, complete the OAuth flow, and you'll land back on the home page with the biometric status visible.
{% endstep %}
{% endstepper %}

## Next Steps

* Explore the [react SDK reference](https://docs.humanity.org/build-with-humanity/build-with-the-sdk-api/humanity-org-react-sdk) → All components, hooks, and error types
* Use our [code references](https://docs.humanity.org/starter-templates-and-examples/sdk-integration-templates/react-sdk-examples)  → Ready-to-run projects if you'd rather start from a working example

{% hint style="info" %}
Not building in React, or need full OAuth control? → [humanity-org-connect-sdk](https://docs.humanity.org/build-with-humanity/build-with-the-sdk-api/humanity-org-connect-sdk "mention")
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.humanity.org/build-with-humanity/build-with-the-sdk-api/sdk-quickstart.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
