From d2299d4650b67c7b6a73de7c7312adf2f4f63093 Mon Sep 17 00:00:00 2001 From: Soam Desai Date: Sun, 20 Sep 2026 20:56:00 -0700 Subject: [PATCH 1/7] docs(world-id): fix 29 audit findings across IDKit, credentials, sandbox, and technical reference - world-id/idkit/integrate.mdx: note Kotlin's GitHub Packages install requirement, sandbox environment value, sandbox testing cross-link, and advanced constraints() finalizer - world-id/idkit/error-codes.mdx: add missing feature_unavailable code, scope the JS/Kotlin/Swift parity claim to its two real exceptions - world-id/idkit/javascript.mdx: document constraints()/CredentialRequest/any/all as an alternative to preset(), and the sandbox environment value - world-id/sandbox/sandbox-access.mdx: fix Sandbox Support email domain (.org -> .com) - world-id/from-idkit-standalone.mdx: frame legacy presets as compatibility-only and point migrators to v4-native proofOfHuman/passport presets - world-id/credentials/9303.mdx: correct MNC to be its own credential (schema id 9310), not "the same credential" as the NFC/passport credential (9303) - world-id/reference/contracts.mdx: clarify additional on-chain groups are not RP-facing, fix ethers.js import path, fix nullifierHash row (was copy-pasted from root), reconcile Supported Chains testnet column with onchain-verification.mdx - world-id/reference/authenticator.mdx: rename requests -> proof_requests wire key, add required oprf_key_id and expires_at_min fields, replace placeholder signature with a valid r||s||v hex format - world-id/reference/poh-issuer.mdx: fix claims cap (15, not 16) and rename associated_data_hash -> associated_data_commitment, add issuer_version field - world-id/idkit/credentials.mdx: document the mnc preset alongside proofOfHuman/passport - world-id/idkit/react.mdx: document isOpen/isInWorldApp hook result fields and constraints as a preset alternative - world-id/idkit/signatures.mdx: document computeRpSignatureMessage and getSessionCommitment exports - world-id/credentials/1.mdx: rename associated_data_hash -> associated_data_commitment to match the real Credential struct - world-id/sandbox/testing-selfie-check.mdx: stop citing verification-flows.mdx for a "Warm" flow it doesn't define - world-id/4-0-migration.mdx: fix Solidity code fences mislabeled as jsx/ts --- world-id/4-0-migration.mdx | 4 +-- world-id/credentials/1.mdx | 2 +- world-id/credentials/9303.mdx | 2 +- world-id/from-idkit-standalone.mdx | 8 +++-- world-id/idkit/credentials.mdx | 40 ++++++++++++++++++++++- world-id/idkit/error-codes.mdx | 9 +++-- world-id/idkit/integrate.mdx | 8 +++-- world-id/idkit/javascript.mdx | 23 +++++++++++-- world-id/idkit/react.mdx | 6 +++- world-id/idkit/signatures.mdx | 7 ++++ world-id/reference/authenticator.mdx | 25 +++++++++----- world-id/reference/contracts.mdx | 24 +++++++------- world-id/reference/poh-issuer.mdx | 12 ++++--- world-id/sandbox/sandbox-access.mdx | 2 +- world-id/sandbox/testing-selfie-check.mdx | 5 ++- 15 files changed, 135 insertions(+), 42 deletions(-) diff --git a/world-id/4-0-migration.mdx b/world-id/4-0-migration.mdx index 354f7b7..a4a4e6c 100644 --- a/world-id/4-0-migration.mdx +++ b/world-id/4-0-migration.mdx @@ -123,7 +123,7 @@ proofs. At the app's cutover, it begins accepting only v4 proofs. **Old Contract - Disable minting here:** -```jsx Mint.sol +```solidity Mint.sol mapping(uint256 => bool) internal oldNullifierHashes; mapping(address => bool) public oldHasMinted; @@ -136,7 +136,7 @@ function mint(){ **New Contract - Check both old and new nullifiers:** -```ts Mintv4.sol +```solidity Mintv4.sol mapping(uint256 => bool) internal nullifierHashes; mapping(address => bool) public hasMinted; diff --git a/world-id/credentials/1.mdx b/world-id/credentials/1.mdx index 00070d1..cc7e181 100644 --- a/world-id/credentials/1.mdx +++ b/world-id/credentials/1.mdx @@ -86,7 +86,7 @@ This credential implements the following attributes beyond the defaults in the [ - associated_data_hash + associated_data_commitment The PoH credential has no associated data, so this field is always{" "} diff --git a/world-id/credentials/9303.mdx b/world-id/credentials/9303.mdx index 11bedcb..941117b 100644 --- a/world-id/credentials/9303.mdx +++ b/world-id/credentials/9303.mdx @@ -53,7 +53,7 @@ import { CredentialHero } from "/snippets/credential-hero.jsx"; ## Introduction -The NFC Credential represents a unique government-issued document. It supports passports and eIDs. Availability varies by country and continues to expand over time. An NFC Credential is **guaranteed to be issued to a single World ID per unique document**. In addition to ICAO-9303 compliant documents (such as passports or eIDs), the Japanese [My Number Card](https://en.wikipedia.org/wiki/My_Number_Card) (MNC) is also supported. The MNC flow uses different enrollment handling internally, but it issues the same credential. +The NFC Credential represents a unique government-issued document. It supports passports and eIDs. Availability varies by country and continues to expand over time. An NFC Credential is **guaranteed to be issued to a single World ID per unique document**. The Japanese [My Number Card](https://en.wikipedia.org/wiki/My_Number_Card) (MNC) is supported separately: it uses different enrollment handling internally and issues its own credential, requested with the `mnc`/`my-number-card` identifier under issuer schema ID `9310`, distinct from this passport/eID credential (`9303`). ## Use Cases diff --git a/world-id/from-idkit-standalone.mdx b/world-id/from-idkit-standalone.mdx index c1819f3..52d26b8 100644 --- a/world-id/from-idkit-standalone.mdx +++ b/world-id/from-idkit-standalone.mdx @@ -101,19 +101,23 @@ await fetch("/api/verify-proof", { ## Credential Mapping -Standalone used `verification_level` to choose what the user proves. In `idkit-core`, use a legacy preset instead. These presets are drop-in replacements for the old verification levels. +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 — they're an intermediate, compatibility-only step, not the final destination for a migration. 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. -| Standalone | `idkit-core` preset | +| 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 })` | + + Once you no longer need World ID 3.0 compatibility, migrate to the v4-native presets instead: `proofOfHuman` (replaces `orbLegacy`) and `passport` (NFC/document credentials). Both return World ID 4.0 credentials with automatic legacy fallback. See [Configure Credentials](/world-id/idkit/credentials). + + ```ts import { IDKit, diff --git a/world-id/idkit/credentials.mdx b/world-id/idkit/credentials.mdx index 7db3ccd..06a0314 100644 --- a/world-id/idkit/credentials.mdx +++ b/world-id/idkit/credentials.mdx @@ -14,6 +14,7 @@ A [Credential](https://docs.rs/world-id-primitives/latest/world_id_primitives/cr | --- | --- | --- | | Proof of Human | The user is a unique human, backed by anonymous biometric verification by the Orb. | `proofOfHuman` | | Passport | The user holds a verified NFC passport credential. | `passport` | +| My Number Card | The user holds a verified Japanese My Number Card (MNC) credential. | `mnc` | | Selfie Check (Beta) | A medium-assurance biometric credential using the device camera for liveness and facial similarity. | `selfieCheckLegacy` | | Identity Check | An attestation that a document-backed property about the user matches your requested attributes. | `identityCheck` with attributes like `minimum_age`, `nationality`, or `document_type`. | @@ -25,7 +26,7 @@ You can also add a liveness check to any preset with `require_user_presence`. # SDK presets -Preset helpers cover common credential requests: `proofOfHuman`, `passport`, `selfieCheckLegacy`, `identityCheck`, and the legacy presets. +Preset helpers cover common credential requests: `proofOfHuman`, `passport`, `mnc`, `selfieCheckLegacy`, `identityCheck`, and the legacy presets. The snippets below assume `rp_context` was already generated and signed by your backend. See [Integrate IDKit](/world-id/idkit/integrate) for the full RP-signing flow. @@ -103,6 +104,43 @@ const preset = passport({ signal: "user-123" }); ``` +## My Number Card + +Use `mnc` for the current World ID 4.0 My Number Card (MNC) credential, for users verifying with Japan's My Number Card. The preset also includes legacy document fallback for users without a World ID 4.0 proof. + + +```typescript title="JavaScript" +import { IDKit, mnc } from "@worldcoin/idkit-core"; + +const preset = mnc({ signal: "user-123" }); + +const request = await IDKit.request({ + app_id: "app_xxxxx", + action: "my-action", + rp_context, + allow_legacy_proofs: true, +}).preset(preset); +``` + +```tsx title="React" +import { IDKitRequestWidget, mnc } from "@worldcoin/idkit"; + +const preset = mnc({ signal: "user-123" }); + + { /* ... */ }} +/>; +``` + + ## Selfie Check (Beta) diff --git a/world-id/idkit/error-codes.mdx b/world-id/idkit/error-codes.mdx index 4d6d9be..cddfcae 100644 --- a/world-id/idkit/error-codes.mdx +++ b/world-id/idkit/error-codes.mdx @@ -33,6 +33,11 @@ This page documents the IDKit SDK and bridge error codes returned during request Requested credential type is not available for that user. Offer fallback credential policy or explain requirement. + + feature_unavailable + Requested feature is not enabled for the app. Available on Kotlin and JS/React; not yet on Swift (see availability note below). + Offer fallback credential policy or explain requirement, same as credential_unavailable. + world_id_4_not_available World ID 4.0 credential is not available for that user. @@ -145,7 +150,7 @@ This page documents the IDKit SDK and bridge error codes returned during request invalid_rp_id_format - RP ID is malformed. + RP ID is malformed. JS/React only — Kotlin and Swift have no equivalent code. Use the registered rp_... ID from your app configuration. @@ -169,7 +174,7 @@ In JS and React, failed requests expose an `IDKitDebugReport` for triage. The wi Treat version availability errors such as `world_id_4_not_available` and `world_id_3_not_available` as terminal for the current user and request. Retrying the same request usually returns the same result; change the requested credential policy or show a user-facing fallback instead. -In JS and React, match these with `IDKitErrorCodes`. Kotlin and Swift expose the same raw values through their `IDKitErrorCode` enums. +In JS and React, match these with `IDKitErrorCodes`. Kotlin and Swift expose the same raw values through their `IDKitErrorCode` enums, with two exceptions: `invalid_rp_id_format` is JS/React-only, and `feature_unavailable` is currently Kotlin/JS-only until the next Swift release. ```tsx ") } @@ -136,7 +138,7 @@ func handleRPSignature(w http.ResponseWriter, r *http.Request) { # Step 4: Generate the connect URL and collect proof -To test during development, use the [simulator](https://simulator.worldcoin.org/) and set `environment` to `"staging"`. +To test during development, use the [simulator](https://simulator.worldcoin.org/) and set `environment` to `"staging"`. To test against a real World ID app instead, see [Sandbox](/world-id/sandbox/what-is-sandbox). ```typescript title="JavaScript" @@ -162,7 +164,7 @@ const request = await IDKit.request({ signature: rpSig.sig, }, allow_legacy_proofs: true, - environment: "production", // Only set this to staging for testing with the simulator + environment: "production", // "staging" tests with the simulator; "sandbox" tests against a real World ID app — see /world-id/sandbox/what-is-sandbox return_to: "myapp://verify-done", // Optional: mobile deep-link callback URL // Signal (optional): Bind specific context into the requested proof. // Examples: user ID, wallet address. Your backend should enforce the same value. @@ -298,6 +300,8 @@ val completion = request.pollUntilCompletion() ``` +> Advanced: `.preset(...)` covers the common cases shown above. For custom multi-credential requests (e.g. Orb OR (Passport AND MNC)), finalize the builder with `.constraints(...)` instead, using the `any`/`all`/`enumerate`/`CredentialRequest` helpers exported by `@worldcoin/idkit-core`. + ### IDKit response After the user completes the verification flow, IDKit returns one of the following response shapes, depending on the protocol version and proof type. diff --git a/world-id/idkit/javascript.mdx b/world-id/idkit/javascript.mdx index 83ef949..09a3d2b 100644 --- a/world-id/idkit/javascript.mdx +++ b/world-id/idkit/javascript.mdx @@ -30,7 +30,7 @@ yarn add @worldcoin/idkit-core - `IDKit.requestWithInviteCode(config)` for invite-code mode - `orbLegacy`, `secureDocumentLegacy`, `documentLegacy`, `selfieCheckLegacy` for presets -Each entry point returns a builder. Finalize it with `.preset(...)`. +Each entry point returns a builder. Finalize it with `.preset(...)` for common single-credential requests, or `.constraints(...)` for custom/multi-credential requests (required for session flows — see [Constraints](#constraints)). ## Request config @@ -48,7 +48,7 @@ const builder = IDKit.request({ signature: "0x...", }, allow_legacy_proofs: true, - environment: "production", // Only set this to staging for testing with the simulator + environment: "production", // "production" | "staging" (simulator) | "sandbox" (real World ID app for integration testing) return_to: "myapp://verify-done", // Optional: mobile deep-link callback URL bridge_url: undefined, // Optional: custom bridge URL }); @@ -71,6 +71,25 @@ const request = await IDKit.request({ }).preset(orbLegacy({ signal: "user-123" })); ``` +## Constraints + +`.constraints(...)` is an alternative finalizer to `.preset(...)` for building custom, non-legacy (World ID 4.0) credential requests, including composite trees (e.g. Orb OR (Passport AND MNC)). Build the tree with `CredentialRequest`, `any`, `all`, and `enumerate`. It's the only option for `IDKit.createSession()`/`IDKit.proveSession()` builders — calling `.preset()` on a session builder throws. + +```ts +import { IDKit, CredentialRequest, any, all } from "@worldcoin/idkit-core"; + +const request = await IDKit.request({ + app_id: "app_xxxxx", + action: "my-action", + rp_context, +}).constraints( + any( + CredentialRequest("proof_of_human"), + all(CredentialRequest("passport"), CredentialRequest("mnc")), + ), +); +``` + ## Polling and status After `.preset(...)`, you get an `IDKitRequest` object: diff --git a/world-id/idkit/react.mdx b/world-id/idkit/react.mdx index ff2c1f3..2be80a3 100644 --- a/world-id/idkit/react.mdx +++ b/world-id/idkit/react.mdx @@ -108,15 +108,19 @@ Hook result fields: - `open()` - `reset()` +- `isOpen` - `isAwaitingUserConnection` - `isAwaitingUserConfirmation` - `isSuccess` - `isError` +- `isInWorldApp` — true when running inside the World App (mini app context) - `connectorURI` - `result` - `errorCode` - `getDebugReport()` +This is the same `IDKitHookResult` shape returned by `useIDKitInviteCodeRequest` and `useIDKitSession`, and shared by the equivalent widget-based flows. + ## Invite-code mode For invite-code flows, use `IDKitInviteCodeRequestWidget` (controlled) or `useIDKitInviteCodeRequest` (headless). Config matches `IDKitRequestWidget` / `useIDKitRequest` — invite-code mode adds no new required fields. See [Invite-code mode](/world-id/idkit/verification-flows#with-invite-code-mode) for when to use it. @@ -195,7 +199,7 @@ Session verification uses `IDKitSessionWidget` (controlled) or `useIDKitSession` ## Presets -React hooks/widgets take `preset` directly in config. +React hooks/widgets take `preset` directly in config for common single-credential requests. `constraints` is an equally valid, mutually-exclusive alternative for custom/multi-credential requests — a config takes either `preset` or `constraints`, never both. Session hooks/widgets (`useIDKitSession`, `IDKitSessionWidget`) require `constraints`; they have no `preset` option. ## Localization and UX notes diff --git a/world-id/idkit/signatures.mdx b/world-id/idkit/signatures.mdx index b4c4a08..09e4c2b 100644 --- a/world-id/idkit/signatures.mdx +++ b/world-id/idkit/signatures.mdx @@ -101,6 +101,13 @@ sig, err = signer.SignRequest(idkit.WithAction("my-action")) ``` +## Other exports + +`@worldcoin/idkit-server` (also re-exported from `@worldcoin/idkit-core/session` and `@worldcoin/idkit/session`) exports two more functions alongside `signRequest`: + +- `computeRpSignatureMessage(...)` — builds the message bytes described in [`compute_rp_signature_message`](#algorithm) above, if you need the raw message instead of a full signature. +- `getSessionCommitment(sessionId: string): bigint` — converts a session ID into the on-chain commitment value, for session-proof flows (see [Session proofs](/world-id/4-0-migration)). + ## Test vectors Verify your implementation against these. All vectors use deterministic inputs. diff --git a/world-id/reference/authenticator.mdx b/world-id/reference/authenticator.mdx index ddff0c8..02730bd 100644 --- a/world-id/reference/authenticator.mdx +++ b/world-id/reference/authenticator.mdx @@ -2,6 +2,8 @@ title: "Authenticator Reference" --- +{/* cspell:ignore oprf */} + ## Authenticator Requests & Responses This section describes how authenticators receive and respond to requests from RPs. This also reflects what is implemented in the Authenticator SDK. @@ -25,8 +27,9 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr "rp_id": "rp_0000000000000000000000000000000000001", "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", - "signature": "304502205cce35752b1642327bebf9f203960dc83f92fa919a4567981ce0c157060ca04e022100f328e42ff2609ddc1fbc7da17896ded2687acb3a4eeb8847a6f3a87ce50ed016", - "requests": [ + "signature": "0x111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222221c", + "oprf_key_id": "oprf_key_1", + "proof_requests": [ { "identifier": "passport", "issuer_schema_id": 9303, @@ -46,8 +49,9 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr "rp_id": "rp_0000000000000000000000000000000000001", "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", - "signature": "304502205cce35752b1642327bebf9f203960dc83f92fa919a4567981ce0c157060ca04e022100f328e42ff2609ddc1fbc7da17896ded2687acb3a4eeb8847a6f3a87ce50ed016", - "requests": [ + "signature": "0x111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222221c", + "oprf_key_id": "oprf_key_1", + "proof_requests": [ { "identifier": "passport", "issuer_schema_id": 9303, @@ -75,8 +79,9 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr "rp_id": "rp_0000000000000000000000000000000000001", "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", - "signature": "304502205cce35752b1642327bebf9f203960dc83f92fa919a4567981ce0c157060ca04e022100f328e42ff2609ddc1fbc7da17896ded2687acb3a4eeb8847a6f3a87ce50ed016", - "requests": [ + "signature": "0x111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222221c", + "oprf_key_id": "oprf_key_1", + "proof_requests": [ { "identifier": "passport", "issuer_schema_id": 9303, @@ -135,6 +140,8 @@ This priority mechanism allows RPs to request their preferred credential type wh The schema for the response is defined in the `world-id-primitives` crate as [`ProofResponse`](https://docs.rs/world-id-primitives/latest/world_id_primitives/request/struct.ProofResponse.html). +Each item in `responses` also includes a required `expires_at_min` field: the minimum expiration required for the credential used in the proof, needed when verifying the proof on-chain. + ### Response Examples @@ -148,7 +155,8 @@ The schema for the response is defined in the `world-id-primitives` crate as [`P "identifier": "orb", "issuer_schema_id": 1, "proof": "0x0000000000000000000000000000000000000000000000000000000000000000000000000", - "nullifier": "nil_00000000000000000000000000000000000000000000000001" + "nullifier": "nil_00000000000000000000000000000000000000000000000001", + "expires_at_min": 1771613013 } ] } @@ -174,7 +182,8 @@ The schema for the response is defined in the `world-id-primitives` crate as [`P "identifier": "orb", "issuer_schema_id": 1, "proof": "0x0000000000000000000000000000000000000000000000000000000000000000000000000", - "session_nullifier": "00000000000000000000000000000000000000000000000001" + "session_nullifier": "00000000000000000000000000000000000000000000000001", + "expires_at_min": 1771613013 } ] } diff --git a/world-id/reference/contracts.mdx b/world-id/reference/contracts.mdx index 97af716..2703fdf 100644 --- a/world-id/reference/contracts.mdx +++ b/world-id/reference/contracts.mdx @@ -41,7 +41,7 @@ All of our smart contracts are available on GitHub: /> World Chain - World Chain + World Chain Sepolia Bridged ~5 Minutes after Ethereum @@ -80,7 +80,7 @@ All of our smart contracts are available on GitHub: /> Polygon - Polygon + — Bridged ~40 Minutes after Ethereum @@ -93,7 +93,7 @@ All of our smart contracts are available on GitHub: /> Base - Base + Base Sepolia Bridged ~5 Minutes after Ethereum @@ -107,7 +107,7 @@ All of our smart contracts are available on GitHub: ## Architecture -This section offers a high-level overview of the various smart contracts that make up World ID. This structure (including state bridging) is replicated on testnets -- currently Sepolia, Optimism Sepolia, and Base Sepolia. +This section offers a high-level overview of the various smart contracts that make up World ID. This structure (including state bridging) is replicated on testnets -- currently Sepolia, World Chain Sepolia, Optimism Sepolia, and Base Sepolia. Polygon has no testnet deployment. ### Identity Managers: `WorldIdIdentityManager` @@ -133,7 +133,7 @@ One World ID contract is deployed on each bridged chain, with an associated Stat The World ID Router will route your call to the correct Identity Manager contract (Ethereum) or World ID contract (L2 Chains) based on the `groupId` argument. This contract is proxied, so you will not need to update your code if the underlying contracts are upgraded. - Only Orb credentials are supported on-chain, so the `groupId` must be `1`. + Orb credentials are `groupId` `1`. The live router does route additional groups, but those are not RP-facing — for on-chain Orb verification via `verifyProof`, use `groupId` `1`. ## Usage @@ -168,8 +168,9 @@ The `verifyProof` method of the **World ID Router** is used to verify proofs on- uint256 - Determines which Credential Type to verify against. As only Orb - credentials are supported on-chain, this must be 1. + Determines which Credential Type to verify against. For Orb + credentials, the RP-facing group, this is 1. The router + does route additional groups on-chain, but they are not RP-facing. @@ -191,9 +192,10 @@ The `verifyProof` method of the **World ID Router** is used to verify proofs on- uint256 - The root of the merkle tree to verify against. This is obtained from the - IDKit widget as a hex string nullifier_hash, and must be - converted to a uint256 before passing it to the{" "} + The nullifier for this proof, preventing double signaling. This is + obtained from the IDKit widget as a hex string{" "} + nullifier_hash, and must be converted to a{" "} + uint256 before passing it to the{" "} verifyProof method. @@ -259,7 +261,7 @@ const unpackedProof = decodeAbiParameters([{ type: 'uint256[8]' }], proof)[0] ```` ```ts title="ethers.js" -import { defaultAbiCoder as abi } from '@ethers/utils' +import { defaultAbiCoder as abi } from '@ethersproject/abi' const unpackedProof = abi.decode(['uint256[8]'], proof)[0] ```` diff --git a/world-id/reference/poh-issuer.mdx b/world-id/reference/poh-issuer.mdx index 8fbedc7..3673224 100644 --- a/world-id/reference/poh-issuer.mdx +++ b/world-id/reference/poh-issuer.mdx @@ -142,11 +142,12 @@ The `credential` response field is a base64-encoded JSON representation of the W "id": 123456789, "version": "V1", "issuer_schema_id": 42, + "issuer_version": 1, "sub": "", "genesis_issued_at": 1733241600, "expires_at": 1764777600, "claims": ["", "", ""], - "associated_data_hash": "", + "associated_data_commitment": "", "signature": "", "issuer": { "pk": ["", ""] @@ -161,17 +162,18 @@ The `credential` response field is a base64-encoded JSON representation of the W | `id` | `uint64` | Issuer-scoped reference identifier for the credential. | | `version` | `string` | Credential version. Current value is `V1`. | | `issuer_schema_id` | `uint64` | Identifier for the (issuer, schema) pair registered in `CredentialSchemaIssuerRegistry`. | +| `issuer_version` | `u8` | Issuer-specific versioning for the credential format. | | `sub` | `FieldElement` | Blinded subject identifier derived from the World ID leaf index and an issuer-specific blinding factor. | | `genesis_issued_at` | `uint64` | Unix timestamp (seconds) of the first issuance of this credential. | | `expires_at` | `uint64` | Unix timestamp (seconds) for expiration. | -| `claims` | `FieldElement[]` | Up to 16 claim commitments. Unused indices are the zero field element. | -| `associated_data_hash` | `FieldElement` | Poseidon2 hash of issuer-defined associated data. The associated data itself is not included. | +| `claims` | `FieldElement[]` | Up to 15 claim commitments (a 16th all-zero capacity slot is reserved internally and stripped on deserialization). Unused indices are the zero field element. | +| `associated_data_commitment` | `FieldElement` | Poseidon2 commitment to issuer-defined associated data. The associated data itself is not included. Previously named `associated_data_hash`; that name is a deprecated alias slated for removal. | | `signature` | `string` | 64-byte compressed EdDSA signature over the credential hash, hex-encoded (128 hex chars, no `0x`). | | `issuer` | `EdDSAPublicKey` | Issuer public key that signed the credential. | ### Field representations -- **FieldElement** values (`sub`, `claims`, `associated_data_hash`) are hex strings with a `0x` prefix and 64 hex characters. +- **FieldElement** values (`sub`, `claims`, `associated_data_commitment`) are hex strings with a `0x` prefix and 64 hex characters. - **Issuer public key** (`issuer.pk`) is serialized as `[x, y]` decimal strings for BabyJubJub affine coordinates. - **Signature** is hex-encoded compressed bytes (no `0x` prefix). @@ -180,7 +182,7 @@ The `credential` response field is a base64-encoded JSON representation of the W - The user first obtains an Orb credential (currently a PCP in v2.3 format). - `claim[0]` is a commitment to the Orb credential, currently `H(hashes.json)`. - When refreshing without a PCP, `claims[0]` is derived from issuer-defined refresh data (a hash of `idCommitment`, `sub`, and a timestamp). -- The PoH credential has no associated data, so `associated_data_hash` is the zero field element. +- The PoH credential has no associated data, so `associated_data_commitment` is the zero field element. - The PoH credential subject is blinded and differs from the Orb credential subject. - The issuer may require a proof for the requested `sub` to prevent bricking an identity. diff --git a/world-id/sandbox/sandbox-access.mdx b/world-id/sandbox/sandbox-access.mdx index d7c3930..ac193ea 100644 --- a/world-id/sandbox/sandbox-access.mdx +++ b/world-id/sandbox/sandbox-access.mdx @@ -45,7 +45,7 @@ request. TestFlight, not any other email. - If your request was rejected or your access was revoked, submitting the same email again won't create a new request. Contact Sandbox Support at - sandbox.access@toolsforhumanity.org. + sandbox.access@toolsforhumanity.com. ### Android — Google Play diff --git a/world-id/sandbox/testing-selfie-check.mdx b/world-id/sandbox/testing-selfie-check.mdx index 8c45d71..c361719 100644 --- a/world-id/sandbox/testing-selfie-check.mdx +++ b/world-id/sandbox/testing-selfie-check.mdx @@ -35,9 +35,8 @@ Semi-cold states](/world-id/idkit/verification-flows) as the rest of World ID: - **Hot** — the user already has World ID installed. If they're already Selfie Check enrolled, they go straight to face match; if not, World ID walks them through - enrollment first, then match. (Selfie Check has no distinct Warm flow — enrollment - happens inline within Hot, same as [Verification Flows](/world-id/idkit/verification-flows) - describes.) + enrollment first, then match. (Enrollment happens inline within Hot rather than as a + separate flow.) - **Cold** — a new user with no World ID app: the full funnel, including install, account creation, date of birth, invite code (iOS), enrollment, and Selfie Check. - **Semi-cold** — an existing user without World ID on this device: reinstall and From 676e559c4aa02e4be10e6768e61117be41b9dd9b Mon Sep 17 00:00:00 2001 From: Soam Desai Date: Mon, 21 Sep 2026 10:21:41 -0700 Subject: [PATCH 2/7] polish: tighten wording, match house style Style pass on the earlier audit commit: cut redundant clauses, self-explanatory asides, and repeated phrasing across the World ID docs it touched, tightening sentences to the surrounding terse Mintlify style without changing any technical content. --- world-id/credentials/9303.mdx | 2 +- world-id/from-idkit-standalone.mdx | 4 ++-- world-id/idkit/credentials.mdx | 2 +- world-id/idkit/error-codes.mdx | 4 ++-- world-id/idkit/integrate.mdx | 8 ++++---- world-id/idkit/javascript.mdx | 4 ++-- world-id/idkit/react.mdx | 2 +- world-id/reference/contracts.mdx | 8 ++++---- world-id/reference/poh-issuer.mdx | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/world-id/credentials/9303.mdx b/world-id/credentials/9303.mdx index 941117b..7b26c21 100644 --- a/world-id/credentials/9303.mdx +++ b/world-id/credentials/9303.mdx @@ -53,7 +53,7 @@ import { CredentialHero } from "/snippets/credential-hero.jsx"; ## Introduction -The NFC Credential represents a unique government-issued document. It supports passports and eIDs. Availability varies by country and continues to expand over time. An NFC Credential is **guaranteed to be issued to a single World ID per unique document**. The Japanese [My Number Card](https://en.wikipedia.org/wiki/My_Number_Card) (MNC) is supported separately: it uses different enrollment handling internally and issues its own credential, requested with the `mnc`/`my-number-card` identifier under issuer schema ID `9310`, distinct from this passport/eID credential (`9303`). +The NFC Credential represents a unique government-issued document. It supports passports and eIDs. Availability varies by country and continues to expand over time. An NFC Credential is **guaranteed to be issued to a single World ID per unique document**. The Japanese [My Number Card](https://en.wikipedia.org/wiki/My_Number_Card) (MNC) is a separate credential — `mnc`/`my-number-card`, issuer schema ID `9310` — with its own enrollment handling, distinct from this passport/eID credential (`9303`). ## Use Cases diff --git a/world-id/from-idkit-standalone.mdx b/world-id/from-idkit-standalone.mdx index 52d26b8..d45eb10 100644 --- a/world-id/from-idkit-standalone.mdx +++ b/world-id/from-idkit-standalone.mdx @@ -101,7 +101,7 @@ await fetch("/api/verify-proof", { ## 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 — they're an intermediate, compatibility-only step, not the final destination for a migration. +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. 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. @@ -115,7 +115,7 @@ Standalone used `verification_level` to choose what the user proves. In `idkit-c | `verification_level: "device"` | `deviceLegacy({ signal })` | - Once you no longer need World ID 3.0 compatibility, migrate to the v4-native presets instead: `proofOfHuman` (replaces `orbLegacy`) and `passport` (NFC/document credentials). Both return World ID 4.0 credentials with automatic legacy fallback. See [Configure Credentials](/world-id/idkit/credentials). + Once you drop World ID 3.0 compatibility, migrate to the v4-native presets: `proofOfHuman` (replaces `orbLegacy`) and `passport` (NFC/document credentials) — both return World ID 4.0 credentials with automatic legacy fallback. See [Configure Credentials](/world-id/idkit/credentials). ```ts diff --git a/world-id/idkit/credentials.mdx b/world-id/idkit/credentials.mdx index 06a0314..2036da7 100644 --- a/world-id/idkit/credentials.mdx +++ b/world-id/idkit/credentials.mdx @@ -106,7 +106,7 @@ const preset = passport({ signal: "user-123" }); ## My Number Card -Use `mnc` for the current World ID 4.0 My Number Card (MNC) credential, for users verifying with Japan's My Number Card. The preset also includes legacy document fallback for users without a World ID 4.0 proof. +Use `mnc` for the current World ID 4.0 My Number Card (MNC) credential. The preset also includes legacy document fallback for users without a World ID 4.0 proof. ```typescript title="JavaScript" diff --git a/world-id/idkit/error-codes.mdx b/world-id/idkit/error-codes.mdx index cddfcae..7fbfd42 100644 --- a/world-id/idkit/error-codes.mdx +++ b/world-id/idkit/error-codes.mdx @@ -35,7 +35,7 @@ This page documents the IDKit SDK and bridge error codes returned during request feature_unavailable - Requested feature is not enabled for the app. Available on Kotlin and JS/React; not yet on Swift (see availability note below). + Requested feature is not enabled for the app. Not yet available on Swift. Offer fallback credential policy or explain requirement, same as credential_unavailable. @@ -174,7 +174,7 @@ In JS and React, failed requests expose an `IDKitDebugReport` for triage. The wi Treat version availability errors such as `world_id_4_not_available` and `world_id_3_not_available` as terminal for the current user and request. Retrying the same request usually returns the same result; change the requested credential policy or show a user-facing fallback instead. -In JS and React, match these with `IDKitErrorCodes`. Kotlin and Swift expose the same raw values through their `IDKitErrorCode` enums, with two exceptions: `invalid_rp_id_format` is JS/React-only, and `feature_unavailable` is currently Kotlin/JS-only until the next Swift release. +In JS and React, match these with `IDKitErrorCodes`. Kotlin and Swift expose the same raw values through their `IDKitErrorCode` enums, except `invalid_rp_id_format` (JS/React-only) and `feature_unavailable` (Kotlin/JS-only until the next Swift release). ```tsx ") } @@ -164,7 +164,7 @@ const request = await IDKit.request({ signature: rpSig.sig, }, allow_legacy_proofs: true, - environment: "production", // "staging" tests with the simulator; "sandbox" tests against a real World ID app — see /world-id/sandbox/what-is-sandbox + environment: "production", // "staging" (simulator) or "sandbox" (real World ID app) return_to: "myapp://verify-done", // Optional: mobile deep-link callback URL // Signal (optional): Bind specific context into the requested proof. // Examples: user ID, wallet address. Your backend should enforce the same value. @@ -300,7 +300,7 @@ val completion = request.pollUntilCompletion() ``` -> Advanced: `.preset(...)` covers the common cases shown above. For custom multi-credential requests (e.g. Orb OR (Passport AND MNC)), finalize the builder with `.constraints(...)` instead, using the `any`/`all`/`enumerate`/`CredentialRequest` helpers exported by `@worldcoin/idkit-core`. +> Advanced: for custom multi-credential requests (e.g. Orb OR (Passport AND MNC)), use `.constraints(...)` instead of `.preset(...)`, built with the `any`/`all`/`enumerate`/`CredentialRequest` helpers from `@worldcoin/idkit-core`. ### IDKit response diff --git a/world-id/idkit/javascript.mdx b/world-id/idkit/javascript.mdx index 09a3d2b..02577ef 100644 --- a/world-id/idkit/javascript.mdx +++ b/world-id/idkit/javascript.mdx @@ -30,7 +30,7 @@ yarn add @worldcoin/idkit-core - `IDKit.requestWithInviteCode(config)` for invite-code mode - `orbLegacy`, `secureDocumentLegacy`, `documentLegacy`, `selfieCheckLegacy` for presets -Each entry point returns a builder. Finalize it with `.preset(...)` for common single-credential requests, or `.constraints(...)` for custom/multi-credential requests (required for session flows — see [Constraints](#constraints)). +Each entry point returns a builder. Finalize it with `.preset(...)` for single-credential requests, or `.constraints(...)` for multi-credential and session requests — see [Constraints](#constraints). ## Request config @@ -73,7 +73,7 @@ const request = await IDKit.request({ ## Constraints -`.constraints(...)` is an alternative finalizer to `.preset(...)` for building custom, non-legacy (World ID 4.0) credential requests, including composite trees (e.g. Orb OR (Passport AND MNC)). Build the tree with `CredentialRequest`, `any`, `all`, and `enumerate`. It's the only option for `IDKit.createSession()`/`IDKit.proveSession()` builders — calling `.preset()` on a session builder throws. +`.constraints(...)` builds custom World ID 4.0 credential requests, including composite trees (e.g. Orb OR (Passport AND MNC)), using `CredentialRequest`, `any`, `all`, and `enumerate`. It's the only finalizer `IDKit.createSession()`/`IDKit.proveSession()` builders accept — `.preset()` throws on a session builder. ```ts import { IDKit, CredentialRequest, any, all } from "@worldcoin/idkit-core"; diff --git a/world-id/idkit/react.mdx b/world-id/idkit/react.mdx index 2be80a3..6ecb86f 100644 --- a/world-id/idkit/react.mdx +++ b/world-id/idkit/react.mdx @@ -199,7 +199,7 @@ Session verification uses `IDKitSessionWidget` (controlled) or `useIDKitSession` ## Presets -React hooks/widgets take `preset` directly in config for common single-credential requests. `constraints` is an equally valid, mutually-exclusive alternative for custom/multi-credential requests — a config takes either `preset` or `constraints`, never both. Session hooks/widgets (`useIDKitSession`, `IDKitSessionWidget`) require `constraints`; they have no `preset` option. +React hooks/widgets take `preset` or `constraints` in config — never both — for single- or multi-credential requests respectively. Session hooks/widgets (`useIDKitSession`, `IDKitSessionWidget`) require `constraints`; they have no `preset` option. ## Localization and UX notes diff --git a/world-id/reference/contracts.mdx b/world-id/reference/contracts.mdx index 2703fdf..9bad552 100644 --- a/world-id/reference/contracts.mdx +++ b/world-id/reference/contracts.mdx @@ -133,7 +133,7 @@ One World ID contract is deployed on each bridged chain, with an associated Stat The World ID Router will route your call to the correct Identity Manager contract (Ethereum) or World ID contract (L2 Chains) based on the `groupId` argument. This contract is proxied, so you will not need to update your code if the underlying contracts are upgraded. - Orb credentials are `groupId` `1`. The live router does route additional groups, but those are not RP-facing — for on-chain Orb verification via `verifyProof`, use `groupId` `1`. + Orb credentials use `groupId` `1`. The router does route additional groups on-chain, but they aren't RP-facing. ## Usage @@ -168,9 +168,9 @@ The `verifyProof` method of the **World ID Router** is used to verify proofs on- uint256 - Determines which Credential Type to verify against. For Orb - credentials, the RP-facing group, this is 1. The router - does route additional groups on-chain, but they are not RP-facing. + Determines which Credential Type to verify against. Orb credentials + are 1 — the only RP-facing group; the router does route + others on-chain. diff --git a/world-id/reference/poh-issuer.mdx b/world-id/reference/poh-issuer.mdx index 3673224..d15af63 100644 --- a/world-id/reference/poh-issuer.mdx +++ b/world-id/reference/poh-issuer.mdx @@ -166,8 +166,8 @@ The `credential` response field is a base64-encoded JSON representation of the W | `sub` | `FieldElement` | Blinded subject identifier derived from the World ID leaf index and an issuer-specific blinding factor. | | `genesis_issued_at` | `uint64` | Unix timestamp (seconds) of the first issuance of this credential. | | `expires_at` | `uint64` | Unix timestamp (seconds) for expiration. | -| `claims` | `FieldElement[]` | Up to 15 claim commitments (a 16th all-zero capacity slot is reserved internally and stripped on deserialization). Unused indices are the zero field element. | -| `associated_data_commitment` | `FieldElement` | Poseidon2 commitment to issuer-defined associated data. The associated data itself is not included. Previously named `associated_data_hash`; that name is a deprecated alias slated for removal. | +| `claims` | `FieldElement[]` | Up to 15 claim commitments (the 16th slot is reserved internally and stripped on deserialization). Unused indices are the zero field element. | +| `associated_data_commitment` | `FieldElement` | Poseidon2 commitment to issuer-defined associated data (not included). Previously `associated_data_hash` — deprecated alias, slated for removal. | | `signature` | `string` | 64-byte compressed EdDSA signature over the credential hash, hex-encoded (128 hex chars, no `0x`). | | `issuer` | `EdDSAPublicKey` | Issuer public key that signed the credential. | From 29491cf891c8fa7030e4d143960d72e9b247d990 Mon Sep 17 00:00:00 2001 From: Soam Desai Date: Mon, 21 Sep 2026 16:31:07 -0700 Subject: [PATCH 3/7] fix: mention mnc in the v4-native document migration note Addresses a Codex review comment on PR #197: the note only listed proofOfHuman/passport as the v4 migration target, which would leave standalone document-level (MNC) users without a documented preset to migrate to, even though v4 exposes mnc as its own preset distinct from passport. --- world-id/from-idkit-standalone.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world-id/from-idkit-standalone.mdx b/world-id/from-idkit-standalone.mdx index d45eb10..6e2760f 100644 --- a/world-id/from-idkit-standalone.mdx +++ b/world-id/from-idkit-standalone.mdx @@ -115,7 +115,7 @@ Standalone used `verification_level` to choose what the user proves. In `idkit-c | `verification_level: "device"` | `deviceLegacy({ signal })` | - Once you drop World ID 3.0 compatibility, migrate to the v4-native presets: `proofOfHuman` (replaces `orbLegacy`) and `passport` (NFC/document credentials) — both return World ID 4.0 credentials with automatic legacy fallback. See [Configure Credentials](/world-id/idkit/credentials). + Once you drop World ID 3.0 compatibility, migrate to the v4-native presets: `proofOfHuman` (replaces `orbLegacy`), `passport` (NFC passports/eIDs), and `mnc` (Japanese My Number Card — also covered by the legacy `document`/`documentLegacy` mapping above) — all three return World ID 4.0 credentials with automatic legacy fallback. See [Configure Credentials](/world-id/idkit/credentials). ```ts From 830b995ab2beefea285a1fd8085f893b6c5b2687 Mon Sep 17 00:00:00 2001 From: Soam Desai Date: Tue, 22 Sep 2026 18:47:04 -0700 Subject: [PATCH 4/7] docs(world-id): correct SDK types, examples, and issuer claims --- world-id/credentials/9303.mdx | 2 +- world-id/idkit/javascript.mdx | 7 ++++--- world-id/idkit/react.mdx | 2 +- world-id/idkit/signatures.mdx | 6 +++--- world-id/reference/authenticator.mdx | 6 +++--- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/world-id/credentials/9303.mdx b/world-id/credentials/9303.mdx index 7b26c21..ae70b55 100644 --- a/world-id/credentials/9303.mdx +++ b/world-id/credentials/9303.mdx @@ -98,7 +98,7 @@ This credential implements the following attributes beyond the defaults in the [ -In addition, the credential implements the following claims: +The following shared issuer claim definitions cover passport/eID and MNC enrollment. MNC-specific entries describe the MNC flow; they do not mean a passport/eID request accepts MNC. In IDKit, request passport/eID with schema `9303` and MNC with schema `9310`. ### Claim 0 - Authentication Claim diff --git a/world-id/idkit/javascript.mdx b/world-id/idkit/javascript.mdx index 7b25d9f..09d12e4 100644 --- a/world-id/idkit/javascript.mdx +++ b/world-id/idkit/javascript.mdx @@ -74,7 +74,7 @@ const request = await IDKit.request({ ## Constraints -`.constraints(...)` builds custom World ID 4.0 credential requests, including composite trees (e.g. Orb OR (Passport AND MNC)), using `CredentialRequest`, `any`, `all`, and `enumerate`. It's the only finalizer `IDKit.createSession()`/`IDKit.proveSession()` builders accept — `.preset()` throws on a session builder. +`.constraints(...)` builds custom World ID 4.0 credential requests, including composite trees (e.g. Proof of Human AND (Passport OR MNC)), using `CredentialRequest`, `any`, `all`, and `enumerate`. It's the only finalizer `IDKit.createSession()`/`IDKit.proveSession()` builders accept — `.preset()` throws on a session builder. ```ts import { IDKit, CredentialRequest, any, all } from "@worldcoin/idkit-core"; @@ -83,10 +83,11 @@ const request = await IDKit.request({ app_id: "app_xxxxx", action: "my-action", rp_context, + allow_legacy_proofs: false, }).constraints( - any( + all( CredentialRequest("proof_of_human"), - all(CredentialRequest("passport"), CredentialRequest("mnc")), + any(CredentialRequest("passport"), CredentialRequest("mnc")), ), ); ``` diff --git a/world-id/idkit/react.mdx b/world-id/idkit/react.mdx index eeedb34..76060fd 100644 --- a/world-id/idkit/react.mdx +++ b/world-id/idkit/react.mdx @@ -119,7 +119,7 @@ Hook result fields: - `errorCode` - `getDebugReport()` -This is the same `IDKitHookResult` shape returned by `useIDKitInviteCodeRequest` and `useIDKitSession`, and shared by the equivalent widget-based flows. +`useIDKitRequest` and `useIDKitSession` return `IDKitHookResult`. `useIDKitInviteCodeRequest` returns `IDKitInviteCodeHookResult`, which includes these common fields plus `codeExpiresAt`, the invite code's expiration timestamp in Unix seconds (or `null` before a code is available). ## Invite-code mode diff --git a/world-id/idkit/signatures.mdx b/world-id/idkit/signatures.mdx index 09e4c2b..89ff94a 100644 --- a/world-id/idkit/signatures.mdx +++ b/world-id/idkit/signatures.mdx @@ -103,10 +103,10 @@ sig, err = signer.SignRequest(idkit.WithAction("my-action")) ## Other exports -`@worldcoin/idkit-server` (also re-exported from `@worldcoin/idkit-core/session` and `@worldcoin/idkit/session`) exports two more functions alongside `signRequest`: +`@worldcoin/idkit-server` exports two more functions alongside `signRequest`: -- `computeRpSignatureMessage(...)` — builds the message bytes described in [`compute_rp_signature_message`](#algorithm) above, if you need the raw message instead of a full signature. -- `getSessionCommitment(sessionId: string): bigint` — converts a session ID into the on-chain commitment value, for session-proof flows (see [Session proofs](/world-id/4-0-migration)). +- `computeRpSignatureMessage(...)` — builds the message bytes described in [`compute_rp_signature_message`](#algorithm) above, if you need the raw message instead of a full signature. Also exported from `@worldcoin/idkit-core/signing`. +- `getSessionCommitment(sessionId: string): bigint` — converts a session ID into the on-chain commitment value, for session-proof flows (see [Session proofs](/world-id/idkit/session-proofs)). Also exported from `@worldcoin/idkit-core/session` and `@worldcoin/idkit/session`. ## Test vectors diff --git a/world-id/reference/authenticator.mdx b/world-id/reference/authenticator.mdx index 02730bd..96ded37 100644 --- a/world-id/reference/authenticator.mdx +++ b/world-id/reference/authenticator.mdx @@ -28,7 +28,7 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", "signature": "0x111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222221c", - "oprf_key_id": "oprf_key_1", + "oprf_key_id": "0x1", "proof_requests": [ { "identifier": "passport", @@ -50,7 +50,7 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", "signature": "0x111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222221c", - "oprf_key_id": "oprf_key_1", + "oprf_key_id": "0x1", "proof_requests": [ { "identifier": "passport", @@ -80,7 +80,7 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", "signature": "0x111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222222222222222221c", - "oprf_key_id": "oprf_key_1", + "oprf_key_id": "0x1", "proof_requests": [ { "identifier": "passport", From c7f62292a4a00d1171e2b51b71b246a1a76f876b Mon Sep 17 00:00:00 2001 From: Soam Desai Date: Tue, 22 Sep 2026 18:47:59 -0700 Subject: [PATCH 5/7] docs(world-id): use constraints for session proof examples --- world-id/SKILL.md | 4 ++-- world-id/idkit/credentials.mdx | 6 +++--- world-id/idkit/mini-apps.mdx | 2 +- world-id/idkit/session-proofs.mdx | 15 ++++++++------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/world-id/SKILL.md b/world-id/SKILL.md index ad7884f..ba331aa 100644 --- a/world-id/SKILL.md +++ b/world-id/SKILL.md @@ -108,7 +108,7 @@ Other legacy presets exist (`documentLegacy`, `deviceLegacy`); reach for them on ### Selfie Check For repeated Selfie Check verification, use `IDKit.createSession` followed by -`IDKit.proveSession` with `.preset(selfieCheck())`. +`IDKit.proveSession` with `.constraints(CredentialRequest("selfie"))`. Save the verified `session_id` against the application account and require that same session on later checks; enforce per-proof replay protection. @@ -132,7 +132,7 @@ The full code for each step is at [https://docs.world.org/world-id/idkit/integra The checklist below describes uniqueness requests. For session integrations, adapt it using `/world-id/idkit/session-proofs`: omit action setup and omit the action from RP signing, -use `IDKitSessionWidget` or the session builders with presets, and replace +use `IDKitSessionWidget` with a `constraints` prop or session builders with `.constraints(...)`, and replace uniqueness-nullifier storage with verified account-to-session binding and per-proof replay protection. Test both creation and proving the saved session. diff --git a/world-id/idkit/credentials.mdx b/world-id/idkit/credentials.mdx index 2cd43fe..d8c19fa 100644 --- a/world-id/idkit/credentials.mdx +++ b/world-id/idkit/credentials.mdx @@ -143,7 +143,7 @@ const preset = mnc({ signal: "user-123" }); ## Selfie Check -Use `selfieCheck()` with [session proofs](/world-id/idkit/session-proofs) to verify +Use `CredentialRequest("selfie")` with [session proofs](/world-id/idkit/session-proofs) to verify users when they first arrive and when they return. Create a session once, save its verified `session_id`, then prove that same session on later checks. @@ -151,12 +151,12 @@ Anyone with World ID App can complete the flow—no Orb or document credential i required. ```typescript -import { IDKit, selfieCheck } from "@worldcoin/idkit-core"; +import { IDKit, CredentialRequest } from "@worldcoin/idkit-core"; const request = await IDKit.createSession({ app_id: "app_xxxxx", rp_context, -}).preset(selfieCheck()); +}).constraints(CredentialRequest("selfie")); ``` Follow the [session guide](/world-id/idkit/session-proofs) for the complete diff --git a/world-id/idkit/mini-apps.mdx b/world-id/idkit/mini-apps.mdx index b8166c3..af6baec 100644 --- a/world-id/idkit/mini-apps.mdx +++ b/world-id/idkit/mini-apps.mdx @@ -41,7 +41,7 @@ The Mini-App-specific details: | Passport-backed checks | `passport` | For repeated Selfie Check verification of returning users, use -[session proofs](/world-id/idkit/session-proofs) with the `selfieCheck()` preset. +[session proofs](/world-id/idkit/session-proofs) with `.constraints(CredentialRequest("selfie"))`. Check out this [page](/world-id/idkit/credentials) to learn about the different World ID credentials and which preset to use for each. diff --git a/world-id/idkit/session-proofs.mdx b/world-id/idkit/session-proofs.mdx index a8d9404..927e6bc 100644 --- a/world-id/idkit/session-proofs.mdx +++ b/world-id/idkit/session-proofs.mdx @@ -38,13 +38,13 @@ each example invocation. ## Create a session ```typescript -import { IDKit, selfieCheck } from "@worldcoin/idkit-core"; +import { IDKit, CredentialRequest } from "@worldcoin/idkit-core"; const request = await IDKit.createSession({ app_id, rp_context, environment: "production", -}).preset(selfieCheck()); +}).constraints(CredentialRequest("selfie")); // Display request.connectorURI as a link or QR code, then wait for the user. const completion = await request.pollUntilCompletion({ timeout: 120_000 }); @@ -54,7 +54,8 @@ if (!completion.success) throw new Error(completion.error); // Save its session_id against the account only after verification succeeds. ``` -The `selfieCheck()` preset selects the Selfie Check credential. See +`CredentialRequest("selfie")` selects the Selfie Check credential. Session builders +accept `.constraints(...)`; `.preset(...)` is only supported for uniqueness requests. See [Configure Credentials](/world-id/idkit/credentials) for credential options. Your backend must verify the complete result before saving its `session_id`. @@ -68,13 +69,13 @@ Load the saved session ID from your backend for the account being verified, and obtain a fresh RP signature. Prove that existing session: ```typescript -import { IDKit, selfieCheck } from "@worldcoin/idkit-core"; +import { IDKit, CredentialRequest } from "@worldcoin/idkit-core"; const request = await IDKit.proveSession(savedSessionId, { app_id, rp_context, environment: "production", -}).preset(selfieCheck()); +}).constraints(CredentialRequest("selfie")); const completion = await request.pollUntilCompletion({ timeout: 120_000 }); if (!completion.success) throw new Error(completion.error); @@ -87,7 +88,7 @@ if (!completion.success) throw new Error(completion.error); Preserve it unchanged. Creating a new session on each visit does not establish continuity with the account's existing session. -For React, use `IDKitSessionWidget` with -`preset={selfieCheck()}`. Omit `existing_session_id` for +For React, import `IDKitSessionWidget` and `CredentialRequest` from +`@worldcoin/idkit`, then use `constraints={CredentialRequest("selfie")}`. Omit `existing_session_id` for creation and set it to the saved session ID for subsequent checks. The widget's `handleVerify` callback should call your backend before `onSuccess` grants access. From b507cc7db158b8f156f184146b9fbb6f553e422b Mon Sep 17 00:00:00 2001 From: Soam Desai Date: Wed, 23 Sep 2026 15:00:01 -0700 Subject: [PATCH 6/7] docs(world-id): address verification findings - integrate: constraints example is Proof of Human AND (Passport OR MNC), scoped to JS/React; passport and MNC are alternatives (any, never all) - error-codes: feature_unavailable is JS/React only until the next Kotlin and Swift releases; fix its remedy - 9303: MNC has its own schema (9310) but counts as the user's one NFC credential; drop my-number-card; name the IDKit credential types - from-idkit-standalone: keep all document users with any(proof_of_human, passport, mnc); note v4 presets always keep 3.0 fallback, so dropping 3.0 needs constraints + allow_legacy_proofs: false - contracts: only groupId 1 is supported for RPs; IDKit 4.x v3 responses use nullifier - authenticator: examples parse with world-id-primitives 0.14.1 (numeric timestamps, 0x-hex signals, canonical proof/nullifiers, session_id) - javascript/react/poh-issuer: add mnc and session entry points, missing invite-code hook fields, uint8, claims slot wording - integrate/javascript: sandbox build of World ID; Maven Central comment --- world-id/credentials/9303.mdx | 4 ++-- world-id/from-idkit-standalone.mdx | 2 +- world-id/idkit/error-codes.mdx | 6 ++--- world-id/idkit/integrate.mdx | 8 +++---- world-id/idkit/javascript.mdx | 7 +++--- world-id/idkit/react.mdx | 2 ++ world-id/reference/authenticator.mdx | 33 ++++++++++++++-------------- world-id/reference/contracts.mdx | 13 +++++------ world-id/reference/poh-issuer.mdx | 4 ++-- 9 files changed, 41 insertions(+), 38 deletions(-) diff --git a/world-id/credentials/9303.mdx b/world-id/credentials/9303.mdx index ae70b55..6823a46 100644 --- a/world-id/credentials/9303.mdx +++ b/world-id/credentials/9303.mdx @@ -53,7 +53,7 @@ import { CredentialHero } from "/snippets/credential-hero.jsx"; ## Introduction -The NFC Credential represents a unique government-issued document. It supports passports and eIDs. Availability varies by country and continues to expand over time. An NFC Credential is **guaranteed to be issued to a single World ID per unique document**. The Japanese [My Number Card](https://en.wikipedia.org/wiki/My_Number_Card) (MNC) is a separate credential — `mnc`/`my-number-card`, issuer schema ID `9310` — with its own enrollment handling, distinct from this passport/eID credential (`9303`). +The NFC Credential represents a unique government-issued document. It supports passports and eIDs. Availability varies by country and continues to expand over time. An NFC Credential is **guaranteed to be issued to a single World ID per unique document**. The Japanese [My Number Card](https://en.wikipedia.org/wiki/My_Number_Card) (MNC) has its own issuer schema ID, `9310`, and its own enrollment handling, distinct from passport/eID (`9303`), but it still counts as the user's one NFC credential. Request MNC and passport/eID as alternatives, never together. ## Use Cases @@ -98,7 +98,7 @@ This credential implements the following attributes beyond the defaults in the [ -The following shared issuer claim definitions cover passport/eID and MNC enrollment. MNC-specific entries describe the MNC flow; they do not mean a passport/eID request accepts MNC. In IDKit, request passport/eID with schema `9303` and MNC with schema `9310`. +The following shared issuer claim definitions cover passport/eID and MNC enrollment. MNC-specific entries describe the MNC flow; they do not mean a passport/eID request accepts MNC. In IDKit, request passport/eID with `passport` (schema `9303`) and MNC with `mnc` (schema `9310`); to accept either, use `any(CredentialRequest("passport"), CredentialRequest("mnc"))`. ### Claim 0 - Authentication Claim diff --git a/world-id/from-idkit-standalone.mdx b/world-id/from-idkit-standalone.mdx index 6e2760f..b38b835 100644 --- a/world-id/from-idkit-standalone.mdx +++ b/world-id/from-idkit-standalone.mdx @@ -115,7 +115,7 @@ Standalone used `verification_level` to choose what the user proves. In `idkit-c | `verification_level: "device"` | `deviceLegacy({ signal })` | - Once you drop World ID 3.0 compatibility, migrate to the v4-native presets: `proofOfHuman` (replaces `orbLegacy`), `passport` (NFC passports/eIDs), and `mnc` (Japanese My Number Card — also covered by the legacy `document`/`documentLegacy` mapping above) — all three return World ID 4.0 credentials with automatic legacy fallback. See [Configure Credentials](/world-id/idkit/credentials). + 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). ```ts diff --git a/world-id/idkit/error-codes.mdx b/world-id/idkit/error-codes.mdx index 7fbfd42..20ecc73 100644 --- a/world-id/idkit/error-codes.mdx +++ b/world-id/idkit/error-codes.mdx @@ -35,8 +35,8 @@ This page documents the IDKit SDK and bridge error codes returned during request feature_unavailable - Requested feature is not enabled for the app. Not yet available on Swift. - Offer fallback credential policy or explain requirement, same as credential_unavailable. + Requested feature is not enabled for the app. JS/React only until the next Kotlin and Swift releases. + Get the feature enabled for your app, or fall back to a request that doesn't use it. world_id_4_not_available @@ -174,7 +174,7 @@ In JS and React, failed requests expose an `IDKitDebugReport` for triage. The wi Treat version availability errors such as `world_id_4_not_available` and `world_id_3_not_available` as terminal for the current user and request. Retrying the same request usually returns the same result; change the requested credential policy or show a user-facing fallback instead. -In JS and React, match these with `IDKitErrorCodes`. Kotlin and Swift expose the same raw values through their `IDKitErrorCode` enums, except `invalid_rp_id_format` (JS/React-only) and `feature_unavailable` (Kotlin/JS-only until the next Swift release). +In JS and React, match these with `IDKitErrorCodes`. Kotlin and Swift expose the same raw values through their `IDKitErrorCode` enums, except `invalid_rp_id_format` (JS/React-only) and `feature_unavailable` (JS/React only until the next Kotlin and Swift releases). ```tsx ") @@ -138,7 +138,7 @@ func handleRPSignature(w http.ResponseWriter, r *http.Request) { # Step 4: Generate the connect URL and collect proof -To test during development, use the [simulator](https://simulator.worldcoin.org/) and set `environment` to `"staging"`. To test against a real World ID app instead, see [Sandbox](/world-id/sandbox/what-is-sandbox). +To test during development, use the [simulator](https://simulator.worldcoin.org/) and set `environment` to `"staging"`. To test with the sandbox build of World ID instead, see [Sandbox](/world-id/sandbox/what-is-sandbox). ```typescript title="JavaScript" @@ -164,7 +164,7 @@ const request = await IDKit.request({ signature: rpSig.sig, }, allow_legacy_proofs: true, - environment: "production", // "staging" (simulator) or "sandbox" (real World ID app) + environment: "production", // "staging" (simulator) or "sandbox" (sandbox build of World ID) return_to: "myapp://verify-done", // Optional: mobile deep-link callback URL // Signal (optional): Bind specific context into the requested proof. // Examples: user ID, wallet address. Your backend should enforce the same value. @@ -300,7 +300,7 @@ val completion = request.pollUntilCompletion() ``` -> Advanced: for custom multi-credential requests (e.g. Orb OR (Passport AND MNC)), use `.constraints(...)` instead of `.preset(...)`, built with the `any`/`all`/`enumerate`/`CredentialRequest` helpers from `@worldcoin/idkit-core`. +> Advanced (JS/React): for custom multi-credential requests (e.g. Proof of Human AND (Passport OR MNC)), use `.constraints(...)` instead of `.preset(...)` (in React, the `constraints` prop instead of `preset`), built with the `any`/`all`/`enumerate`/`CredentialRequest` helpers from `@worldcoin/idkit-core` (also exported by `@worldcoin/idkit`). A user holds at most one [NFC credential](/world-id/credentials/9303), so passport and MNC are alternatives: combine them with `any`, never `all`. The Kotlin and Swift SDKs don't expose these helpers. ### IDKit response diff --git a/world-id/idkit/javascript.mdx b/world-id/idkit/javascript.mdx index 09d12e4..0d83ce7 100644 --- a/world-id/idkit/javascript.mdx +++ b/world-id/idkit/javascript.mdx @@ -28,7 +28,8 @@ yarn add @worldcoin/idkit-core - `IDKit.request(config)` for uniqueness proofs - `IDKit.requestWithInviteCode(config)` for invite-code mode -- `proofOfHuman`, `passport`, `selfieCheck`, and `identityCheck` for current presets +- `IDKit.createSession(config)` and `IDKit.proveSession(sessionId, config)` for [session proofs](/world-id/idkit/session-proofs) +- `proofOfHuman`, `passport`, `mnc`, `selfieCheck`, and `identityCheck` for current presets - `orbLegacy`, `secureDocumentLegacy`, `documentLegacy`, and `deviceLegacy` for legacy presets Each entry point returns a builder. Finalize it with `.preset(...)` for single-credential requests, or `.constraints(...)` for multi-credential and session requests — see [Constraints](#constraints). @@ -49,7 +50,7 @@ const builder = IDKit.request({ signature: "0x...", }, allow_legacy_proofs: true, - environment: "production", // "production" | "staging" (simulator) | "sandbox" (real World ID app for integration testing) + environment: "production", // "production" | "staging" (simulator) | "sandbox" (sandbox build of World ID, for integration testing) return_to: "myapp://verify-done", // Optional: mobile deep-link callback URL bridge_url: undefined, // Optional: custom bridge URL }); @@ -94,7 +95,7 @@ const request = await IDKit.request({ ## Polling and status -After `.preset(...)`, you get an `IDKitRequest` object: +After `.preset(...)` or `.constraints(...)`, you get an `IDKitRequest` object: - `connectorURI` - `requestId` diff --git a/world-id/idkit/react.mdx b/world-id/idkit/react.mdx index 76060fd..273812c 100644 --- a/world-id/idkit/react.mdx +++ b/world-id/idkit/react.mdx @@ -145,10 +145,12 @@ import { IDKitInviteCodeRequestWidget, proofOfHuman } from "@worldcoin/idkit"; - `open()` - `reset()` +- `isOpen` - `isAwaitingUserConnection` - `isAwaitingUserConfirmation` - `isSuccess` - `isError` +- `isInWorldApp` - `connectorURI` - `codeExpiresAt` - `result` diff --git a/world-id/reference/authenticator.mdx b/world-id/reference/authenticator.mdx index 96ded37..e73ce22 100644 --- a/world-id/reference/authenticator.mdx +++ b/world-id/reference/authenticator.mdx @@ -22,8 +22,8 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr { "id": "req_18c0f7f03e7d", "version": 1, - "created_at": "1771612953", - "expires_at": "1771613013", + "created_at": 1771612953, + "expires_at": 1771613013, "rp_id": "rp_0000000000000000000000000000000000001", "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", @@ -33,7 +33,7 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr { "identifier": "passport", "issuer_schema_id": 9303, - "signal": "abcd-efgh-ijkl" + "signal": "0xdeadbeef" } ] } @@ -44,8 +44,8 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr { "id": "req_18c0f7f03e7d", "version": 1, - "created_at": "1771612953", - "expires_at": "1771613013", + "created_at": 1771612953, + "expires_at": 1771613013, "rp_id": "rp_0000000000000000000000000000000000001", "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", @@ -55,12 +55,12 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr { "identifier": "passport", "issuer_schema_id": 9303, - "signal": "abcd-efgh-ijkl" + "signal": "0xdeadbeef" }, { "identifier": "poh", "issuer_schema_id": 1, - "signal": "abcd-efgh-ijkl" + "signal": "0xdeadbeef" } ], "constraints": { @@ -74,8 +74,8 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr { "id": "req_18c0f7f03e7d", "version": 1, - "created_at": "1771612953", - "expires_at": "1771613013", + "created_at": 1771612953, + "expires_at": 1771613013, "rp_id": "rp_0000000000000000000000000000000000001", "action": "0x0000000000000000000000000000000000000000000000000000000000000001", "nonce": "0x11d223ce7b91ac212f42cf50f0a3439ae3fcdba4ea32acb7f194d1051ed324c2", @@ -85,17 +85,17 @@ The schema for the request is defined in the `world-id-primitives` crate as [`Pr { "identifier": "passport", "issuer_schema_id": 9303, - "signal": "abcd-efgh-ijkl" + "signal": "0xdeadbeef" }, { "identifier": "my-number-card", "issuer_schema_id": 9310, - "signal": "mnop-qrst-uvwx" + "signal": "0xfeedface" }, { "identifier": "orb", "issuer_schema_id": 1, - "signal": "abcd-efgh-ijkl" + "signal": "0xdeadbeef" } ], "constraints": { @@ -154,8 +154,8 @@ Each item in `responses` also includes a required `expires_at_min` field: the mi { "identifier": "orb", "issuer_schema_id": 1, - "proof": "0x0000000000000000000000000000000000000000000000000000000000000000000000000", - "nullifier": "nil_00000000000000000000000000000000000000000000000001", + "proof": "00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000", + "nullifier": "nil_0000000000000000000000000000000000000000000000000000000000000001", "expires_at_min": 1771613013 } ] @@ -177,12 +177,13 @@ Each item in `responses` also includes a required `expires_at_min` field: the mi { "id": "req_18c0f7f03e7d", "version": 1, + "session_id": "session_00000000000000000000000000000000000000000000000000000000000003ea0100000000000000000000000000000000000000000000000000000000000001", "responses": [ { "identifier": "orb", "issuer_schema_id": 1, - "proof": "0x0000000000000000000000000000000000000000000000000000000000000000000000000", - "session_nullifier": "00000000000000000000000000000000000000000000000001", + "proof": "00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000", + "session_nullifier": "snil_00000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000001", "expires_at_min": 1771613013 } ] diff --git a/world-id/reference/contracts.mdx b/world-id/reference/contracts.mdx index 9bad552..bfb0ad0 100644 --- a/world-id/reference/contracts.mdx +++ b/world-id/reference/contracts.mdx @@ -133,7 +133,7 @@ One World ID contract is deployed on each bridged chain, with an associated Stat The World ID Router will route your call to the correct Identity Manager contract (Ethereum) or World ID contract (L2 Chains) based on the `groupId` argument. This contract is proxied, so you will not need to update your code if the underlying contracts are upgraded. - Orb credentials use `groupId` `1`. The router does route additional groups on-chain, but they aren't RP-facing. + Only `groupId` `1` (Orb credentials) is supported for RPs. ## Usage @@ -168,9 +168,8 @@ The `verifyProof` method of the **World ID Router** is used to verify proofs on- uint256 - Determines which Credential Type to verify against. Orb credentials - are 1 — the only RP-facing group; the router does route - others on-chain. + Determines which Credential Type to verify against. Only{" "} + 1 (Orb credentials) is supported for RPs. @@ -193,9 +192,9 @@ The `verifyProof` method of the **World ID Router** is used to verify proofs on- The nullifier for this proof, preventing double signaling. This is - obtained from the IDKit widget as a hex string{" "} - nullifier_hash, and must be converted to a{" "} - uint256 before passing it to the{" "} + obtained from IDKit as a hex string (nullifier in IDKit + 4.x v3 responses, nullifier_hash in older versions), and + must be converted to a uint256 before passing it to the{" "} verifyProof method. diff --git a/world-id/reference/poh-issuer.mdx b/world-id/reference/poh-issuer.mdx index d15af63..21facef 100644 --- a/world-id/reference/poh-issuer.mdx +++ b/world-id/reference/poh-issuer.mdx @@ -162,11 +162,11 @@ The `credential` response field is a base64-encoded JSON representation of the W | `id` | `uint64` | Issuer-scoped reference identifier for the credential. | | `version` | `string` | Credential version. Current value is `V1`. | | `issuer_schema_id` | `uint64` | Identifier for the (issuer, schema) pair registered in `CredentialSchemaIssuerRegistry`. | -| `issuer_version` | `u8` | Issuer-specific versioning for the credential format. | +| `issuer_version` | `uint8` | Issuer-specific versioning for the credential format. | | `sub` | `FieldElement` | Blinded subject identifier derived from the World ID leaf index and an issuer-specific blinding factor. | | `genesis_issued_at` | `uint64` | Unix timestamp (seconds) of the first issuance of this credential. | | `expires_at` | `uint64` | Unix timestamp (seconds) for expiration. | -| `claims` | `FieldElement[]` | Up to 15 claim commitments (the 16th slot is reserved internally and stripped on deserialization). Unused indices are the zero field element. | +| `claims` | `FieldElement[]` | Up to 15 claim commitments. Unused indices are the zero field element. The 16th hash slot is reserved: a trailing zero 16th element is stripped on deserialization, and a nonzero one is rejected. | | `associated_data_commitment` | `FieldElement` | Poseidon2 commitment to issuer-defined associated data (not included). Previously `associated_data_hash` — deprecated alias, slated for removal. | | `signature` | `string` | 64-byte compressed EdDSA signature over the credential hash, hex-encoded (128 hex chars, no `0x`). | | `issuer` | `EdDSAPublicKey` | Issuer public key that signed the credential. | From 9bcc7fb3cf3f63d356a2d19d5cab27c8525d8831 Mon Sep 17 00:00:00 2001 From: Soam Desai Date: Wed, 23 Sep 2026 15:02:51 -0700 Subject: [PATCH 7/7] docs(world-id): note presets that override allow_legacy_proofs - credentials: proofOfHuman, passport, mnc and identityCheck always accept World ID 3.0 fallback and selfieCheck never does, whatever allow_legacy_proofs says (idkit preset.rs allow_legacy_proofs_override), so the options table matches the migration note --- world-id/idkit/credentials.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world-id/idkit/credentials.mdx b/world-id/idkit/credentials.mdx index d8c19fa..e1a96c1 100644 --- a/world-id/idkit/credentials.mdx +++ b/world-id/idkit/credentials.mdx @@ -324,7 +324,7 @@ These presets only return World ID 3.0 proofs. Use them for existing integration allow_legacy_proofs Request config and widgets - Required for request flows. Set to true while accepting World ID 3.0 fallback proofs; set to false for World ID 4.0-only requests. + Required for request flows. Set to true while accepting World ID 3.0 fallback proofs; set to false for World ID 4.0-only requests. Presets override it: proofOfHuman, passport, mnc, and identityCheck always accept 3.0 fallback, and selfieCheck never does. require_user_presence