@worldcoin/idkit-core is the lowest-level JavaScript/TypeScript IDKit SDK.
Use it when you want full control over UI and state management or when you’re not using React.
Install
npm i @worldcoin/idkit-core
Entry points
IDKit.request(config) for uniqueness proofs
IDKit.createSession(config) for first-time session creation
IDKit.proveSession(sessionId, config) for returning users
CredentialRequest, any, all for explicit constraints
orbLegacy, secureDocumentLegacy, documentLegacy for presets
Each entry point returns a builder. Finalize it with either .constraints(...) or .preset(...).
Request config
import { IDKit } from "@worldcoin/idkit-core";
const builder = IDKit.request({
app_id: "app_xxxxx",
action: "my-action",
rp_context: {
rp_id: "rp_xxxxx",
nonce: "0x...",
created_at: 1735689600,
expires_at: 1735689900,
signature: "0x...",
},
action_description: "Verify user",
bridge_url: undefined,
allow_legacy_proofs: false,
override_connect_base_url: undefined,
environment: "production",
});
Generate rp_context in your backend only. Never expose your RP signing key in client code.
Constraints
Use constraints when you want explicit credential logic.
import { IDKit, CredentialRequest, any, all } from "@worldcoin/idkit-core";
const orb = CredentialRequest("orb", { signal: "user-123" });
const face = CredentialRequest("face", { signal: "user-123" });
const secureDocWithMinGenesis = CredentialRequest("secure_document", {
signal: "user-123",
genesis_issued_at_min: 1_735_689_600,
});
const request = await IDKit.request({
app_id: "app_xxxxx",
action: "my-action",
rp_context,
allow_legacy_proofs: false,
}).constraints(all(any(orb, face), secureDocWithMinGenesis));
CredentialRequest supports:
signal: Extra context bound into the proof (for example wallet_address or
user_id). The value is hashed and committed in the proof.
genesis_issued_at_min: Only accept credentials with
credential.genesis_issued_at >= genesis_issued_at_min.
expires_at_min: Only accept credentials with
credential.expires_at > expires_at_min. If you omit it, IDKit uses the
request created_at timestamp.
Presets
import { IDKit, orbLegacy } from "@worldcoin/idkit-core";
const request = await IDKit.request({
app_id: "app_xxxxx",
action: "my-action",
rp_context,
allow_legacy_proofs: true,
}).preset(orbLegacy({ signal: "user-123" }));
Use presets only when migrating from an older IDKit version. Preset-based
requests are backward compatible and can work with both World ID 4.0 and
World ID 3.0 (legacy) flows.
Sessions
Sessions are v4-only and return session_id.
import { IDKit, CredentialRequest, any, orbLegacy } from "@worldcoin/idkit-core";
const sessionConfig = {
app_id: "app_xxxxx",
rp_context,
action_description: "Sign in",
environment: "production" as const,
};
const createRequest = await IDKit.createSession(sessionConfig).constraints(
any(CredentialRequest("orb")),
);
const createResult = await createRequest.pollUntilCompletion();
if (!createResult.success) throw new Error(createResult.error);
const sessionId = createResult.result.session_id;
const proveRequest = await IDKit.proveSession(sessionId, sessionConfig).preset(
orbLegacy({ signal: "user-123" }),
);
const proveResult = await proveRequest.pollUntilCompletion();
In session flows, there is no allow_legacy_proofs toggle. Sessions are always World ID 4.0.
Polling and status
After .constraints(...) or .preset(...), you get an IDKitRequest object:
connectorURI
requestId
pollOnce()
pollUntilCompletion({ pollInterval, timeout, signal })
import { IDKitErrorCodes } from "@worldcoin/idkit-core";
const completion = await request.pollUntilCompletion({
pollInterval: 2_000,
timeout: 120_000,
});
if (!completion.success) {
if (completion.error === IDKitErrorCodes.Timeout) {
// UI timeout handling
}
if (completion.error === IDKitErrorCodes.Cancelled) {
// User/app cancellation handling
}
}
When running inside World App, native transport is used and connectorURI may be empty.
Outside World App, connectorURI is the URL you render as a QR code.
Server-side helpers
Use subpath exports on your backend:
import { signRequest } from "@worldcoin/idkit-core/signing";
import { hashSignal } from "@worldcoin/idkit-core/hashing";
const { sig, nonce, createdAt, expiresAt } = signRequest(
"my-action",
process.env.RP_SIGNING_KEY!,
);
const signalHash = hashSignal("user-123");
signRequest should only run in trusted server environments.
Related pages