> ## Documentation Index
> Fetch the complete documentation index at: https://tfh-docs-audit-world-id-content-fixes.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# IDKit Standalone

> Migrate from @worldcoin/idkit-standalone to @worldcoin/idkit-core.

The `@worldcoin/idkit-standalone` package is discontinued. Migrate any vanilla JavaScript or custom QR flow to `@worldcoin/idkit-core`.

## Migration Checklist

1. Enable World ID 4.0 in the [Developer Portal](https://developer.world.org) and keep your `app_id`, `rp_id`, and server-only `signing_key`.
2. Install `@worldcoin/idkit-core`.
3. Add a backend endpoint that generates an RP signature. See [RP Signatures](/world-id/idkit/signatures).
4. Pick a legacy preset that matches your previous `verification_level` configuration.
5. Replace `verifyCloudProof(...)` with a backend POST to `https://developer.world.org/api/v4/verify/{rp_id}`.
6. Store the verified `nullifier` for replay protection.

For the broader protocol migration, including proof types and timelines, see [World ID 4.0](/world-id/4-0-migration).

## Install

<CodeGroup>
  ```bash npm theme={"system"}
  npm i @worldcoin/idkit-core
  ```

  ```bash pnpm theme={"system"}
  pnpm add @worldcoin/idkit-core
  ```

  ```bash yarn theme={"system"}
  yarn add @worldcoin/idkit-core
  ```
</CodeGroup>

## Request a Proof

Standalone mounted UI through browser globals:

```ts title="Before" theme={"system"}
import "@worldcoin/idkit-standalone";

IDKit.init({
  app_id: "app_xxxxx",
  action: "my-action",
  signal: "user-123",
  verification_level: "orb",
});

await IDKit.open();
```

With `idkit-core`, fetch an RP signature from your backend, build the request, render the `connectorURI`, and poll until World ID returns a proof.

```ts title="After" theme={"system"}
import { IDKit, orbLegacy } from "@worldcoin/idkit-core";

const action = "my-action";
const signal = "user-123";

const rpContext = await fetch("/api/rp-signature", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ action }),
}).then((r) => r.json());

const request = await IDKit.request({
  app_id: "app_xxxxx",
  action,
  rp_context: {
    rp_id: "rp_xxxxx",
    nonce: rpContext.nonce,
    created_at: rpContext.created_at,
    expires_at: rpContext.expires_at,
    signature: rpContext.sig,
  },
  allow_legacy_proofs: true,
  environment: "production",
}).preset(orbLegacy({ signal }));

renderQrCode(request.connectorURI);

const completion = await request.pollUntilCompletion({
  pollInterval: 2_000,
  timeout: 120_000,
});

if (!completion.success) {
  throw new Error(`World ID verification failed: ${completion.error}`);
}

await fetch("/api/verify-proof", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ idkitResponse: completion.result }),
});
```

## Credential Mapping

Standalone used `verification_level` to choose what the user proves. In `idkit-core`, use a legacy preset instead. These presets only return World ID 3.0 proofs — a compatibility step, not the final migration target.

<Note type="info">
  Legacy presets return the maximum credential a user has. For example, if a user has an Orb credential but you request `documentLegacy`, they verify with their Orb credential.
</Note>

| Standalone | `idkit-core` preset (compatibility-only) |
| - | - |
| `verification_level: "orb"` | `orbLegacy({ signal })` |
| `verification_level: "secure_document"` | `secureDocumentLegacy({ signal })` |
| `verification_level: "document"` | `documentLegacy({ signal })` |
| `verification_level: "device"` | `deviceLegacy({ signal })` |

<Note>
  For World ID 4.0, use the v4-native presets: `proofOfHuman` (replaces `orbLegacy`), `passport` (NFC passports/eIDs), or `mnc` (Japanese My Number Card). They always keep World ID 3.0 fallback on, regardless of `allow_legacy_proofs`. A single preset narrows a `document` integration, since `documentLegacy` accepted Orb, passport/eID, and MNC holders alike; to keep all of them, use `.constraints(any(CredentialRequest("proof_of_human"), CredentialRequest("passport"), CredentialRequest("mnc")))`. Constraint requests have no credential-specific 3.0 fallback (any 3.0 fallback is Device-level), so use them with `allow_legacy_proofs: false`, which is also how you drop World ID 3.0 entirely. See [Configure Credentials](/world-id/idkit/credentials).
</Note>

```ts theme={"system"}
import {
  IDKit,
  deviceLegacy,
  documentLegacy,
  orbLegacy,
  secureDocumentLegacy,
} from "@worldcoin/idkit-core";

const request = await IDKit.request(config).preset(
  orbLegacy({ signal: "user-123" }),
);
```

## RP Signatures

IDKit 4.x requests require `rp_context`, signed by your backend with the Developer Portal `signing_key`. Never generate signatures in client code.

For implementation details, see the [RP Signatures](/world-id/idkit/signatures) reference. It includes the JavaScript helper, the signing algorithm, and test vectors for non-JavaScript backends.

## Verify the Proof

Standalone integrations typically verified with `verifyCloudProof(...)`:

```ts title="Before" theme={"system"}
import { verifyCloudProof } from "@worldcoin/idkit";

const response = await verifyCloudProof(proof, app_id, action, signal);
```

In IDKit 4.x, send the IDKit result to your backend and forward it directly to the [v4 verify endpoint](/api-reference/developer-portal/verify).

```ts title="After" theme={"system"}
import type { IDKitResult } from "@worldcoin/idkit-core";

export async function POST(request: Request): Promise<Response> {
  const { idkitResponse } = (await request.json()) as {
    idkitResponse: IDKitResult;
  };

  const response = await fetch(
    `https://developer.world.org/api/v4/verify/${process.env.WORLD_ID_RP_ID}`,
    {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(idkitResponse),
    },
  );

  return new Response(await response.text(), {
    status: response.status,
    headers: { "content-type": "application/json" },
  });
}
```

## Store the Nullifier

After `/api/v4/verify/{rp_id}` succeeds, store the verified `nullifier` for the action and reject duplicates. During migration, keep checking any old `nullifier_hash` records if the same user could have verified before the upgrade.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.