From 673629ef29d5e8e147e62cfc779fd4c2e2c7de90 Mon Sep 17 00:00:00 2001
From: Takis Kakalis <80459599+Takaros999@users.noreply.github.com>
Date: Wed, 2 Sep 2026 11:24:54 -0700
Subject: [PATCH 1/4] docs: document selfie check 4.0
---
openapi/developer-portal.json | 90 ++++++++++++++++++++++-
snippets/idkit-response.mdx | 28 +++++++
world-id/SKILL.md | 28 ++++---
world-id/credentials/11.mdx | 38 +++++++---
world-id/idkit/credentials.mdx | 72 ++++++++++++++----
world-id/idkit/integrate.mdx | 5 ++
world-id/idkit/javascript.mdx | 22 ++++--
world-id/idkit/kotlin.mdx | 26 +++++++
world-id/idkit/mini-apps.mdx | 2 +-
world-id/idkit/react.mdx | 17 +++--
world-id/idkit/swift.mdx | 26 +++++--
world-id/idkit/verification-flows.mdx | 2 +-
world-id/overview.mdx | 2 +-
world-id/sandbox/testing-selfie-check.mdx | 11 +--
14 files changed, 298 insertions(+), 71 deletions(-)
diff --git a/openapi/developer-portal.json b/openapi/developer-portal.json
index 8acb393..3c5bc93 100644
--- a/openapi/developer-portal.json
+++ b/openapi/developer-portal.json
@@ -742,6 +742,32 @@
]
}
},
+ "selfie_check_v4": {
+ "summary": "Selfie Check (protocol 4.0)",
+ "value": {
+ "protocol_version": "4.0",
+ "nonce": "0xabc123",
+ "action": "selfie-check-2026-09-02",
+ "integrity_bundle": {
+ "version": 2,
+ "signature_format": "apple_app_attest",
+ "timestamp": 1788302923,
+ "signature": "a1b2c3d4",
+ "jwt": "eyJ..."
+ },
+ "responses": [
+ {
+ "identifier": "selfie",
+ "issuer_schema_id": 11,
+ "nullifier": "0x2bf8406809dcefb1486dadc96c0a897db9bab002053054cf64272db512c6fbd8",
+ "expires_at_min": 1788302888,
+ "proof": ["0x111", "0x222", "0x333", "0x444", "0x555"],
+ "signal_hash": "0x0",
+ "sybil_score": 10
+ }
+ ]
+ }
+ },
"session_v4": {
"summary": "Session proof (protocol 4.0)",
"value": {
@@ -861,7 +887,7 @@
"device",
"selfie"
],
- "description": "The legacy verification level. Use `selfie` for Selfie Check (Beta). The historical `face` value remains accepted for backward compatibility and behaves the same as `selfie`."
+ "description": "The legacy verification level. Use `selfie` for Selfie Check. The historical `face` value remains accepted for backward compatibility and behaves the same as `selfie`."
},
"action": {
"type": "string",
@@ -1250,6 +1276,33 @@
"additionalProperties": true,
"description": "Pass-through GraphQL response. Usually includes `data` and optionally `errors`."
},
+ "IntegrityBundle": {
+ "type": "object",
+ "required": ["version", "signature_format", "timestamp", "signature", "jwt"],
+ "description": "World ID App integrity attestation. Selfie Check 4.0 requires version 2, which covers the disclosed `sybil_score`.",
+ "properties": {
+ "version": {
+ "type": "integer",
+ "enum": [1, 2]
+ },
+ "signature_format": {
+ "type": "string",
+ "enum": ["apple_app_attest", "android_keystore"]
+ },
+ "timestamp": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "signature": {
+ "type": "string",
+ "description": "Hex-encoded device signature."
+ },
+ "jwt": {
+ "type": "string",
+ "description": "Attestation Gateway JWT used to verify the signing key."
+ }
+ }
+ },
"VerifyV4Request": {
"description": "Choose one request type.",
"oneOf": [
@@ -1303,6 +1356,9 @@
"enum": ["production", "staging"],
"default": "production"
},
+ "integrity_bundle": {
+ "$ref": "#/components/schemas/IntegrityBundle"
+ },
"responses": {
"type": "array",
"minItems": 1,
@@ -1337,9 +1393,17 @@
},
"environment": {
"type": "string",
- "enum": ["production", "staging"],
+ "enum": ["production", "staging", "sandbox"],
"default": "production"
},
+ "integrity_bundle": {
+ "description": "Required with version 2 when any response item is a Selfie Check credential (`issuer_schema_id: 11`).",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/IntegrityBundle"
+ }
+ ]
+ },
"responses": {
"type": "array",
"minItems": 1,
@@ -1373,9 +1437,17 @@
},
"environment": {
"type": "string",
- "enum": ["production", "staging"],
+ "enum": ["production", "staging", "sandbox"],
"default": "production"
},
+ "integrity_bundle": {
+ "description": "Required with version 2 when any response item is a Selfie Check credential (`issuer_schema_id: 11`).",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/IntegrityBundle"
+ }
+ ]
+ },
"responses": {
"type": "array",
"minItems": 1,
@@ -1395,7 +1467,7 @@
"properties": {
"identifier": {
"type": "string",
- "description": "Credential identifier returned by IDKit (for example, `orb` or `selfie`). Use `selfie` for Selfie Check (Beta); the historical `face` value remains accepted as a backward-compatible alias."
+ "description": "Credential identifier returned by IDKit (for example, `orb` or `selfie`). Use `selfie` for Selfie Check; the historical `face` value remains accepted as a backward-compatible alias."
},
"signal_hash": {
"type": "string",
@@ -1451,6 +1523,11 @@
"type": "string"
},
"description": "Exactly 5 hex elements (4 compressed proof elements + Merkle root)."
+ },
+ "sybil_score": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Selfie Check z-score decoded to an integer. Required only when `issuer_schema_id` is 11. Higher values indicate a stronger potential duplicate signal; this is not a probability or match count."
}
}
},
@@ -1493,6 +1570,11 @@
"items": {
"type": "string"
}
+ },
+ "sybil_score": {
+ "type": "integer",
+ "minimum": 0,
+ "description": "Selfie Check z-score decoded to an integer. Required only when `issuer_schema_id` is 11."
}
}
},
diff --git a/snippets/idkit-response.mdx b/snippets/idkit-response.mdx
index 200baa1..578e658 100644
--- a/snippets/idkit-response.mdx
+++ b/snippets/idkit-response.mdx
@@ -38,6 +38,34 @@
}
```
+```json title="World ID 4.0 Selfie Check"
+{
+ "protocol_version": "4.0",
+ "nonce": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
+ "action": "selfie-check-2026-09-02",
+ "environment": "production",
+ "integrity_bundle": {
+ "version": 2,
+ "signature_format": "apple_app_attest",
+ "timestamp": 1788302923,
+ "signature": "a1b2c3d4...device_signature",
+ "jwt": "eyJ...attestation_jwt"
+ },
+ "responses": [
+ {
+ "identifier": "selfie",
+ "signal_hash": "0x0",
+ "proof": ["0x1a2b...", "0x3c4d...", "0x5e6f...", "0x7a8b...", "0x9c0d..."],
+ "nullifier": "0x04e5f6...rp_scoped_nullifier",
+ "issuer_schema_id": 11,
+ "expires_at_min": 1788302888,
+ "sybil_score": 10
+ }
+ ],
+ "user_presence_completed": true
+}
+```
+
```json title="World ID 4.0 Session"
{
"protocol_version": "4.0",
diff --git a/world-id/SKILL.md b/world-id/SKILL.md
index 3a66cee..44bb06d 100644
--- a/world-id/SKILL.md
+++ b/world-id/SKILL.md
@@ -1,7 +1,7 @@
---
name: world-id-integration
description: |
- Use this skill when adding, upgrading, debugging, or testing World ID verification with IDKit in a new or existing web or mobile app. Covers Proof of Human, passport/document, Selfie Check (Beta), and session/sign-in flows; Developer Portal app, RP, and action setup; server-side signing and proof verification; environment matching; nullifier replay protection; and launch testing. Trigger when the user asks to add World ID, verify humans, stop bots or multi-accounting, add Sybil resistance, or mentions IDKit, Orb, World ID proof flows, World App proof flows, @worldcoin/idkit, signing keys, rp_id, or app_id.
+ Use this skill when adding, upgrading, debugging, or testing World ID verification with IDKit in a new or existing web or mobile app. Covers Proof of Human, passport/document, Selfie Check, and session/sign-in flows; Developer Portal app, RP, and action setup; server-side signing and proof verification; environment matching; nullifier replay protection; and launch testing. Trigger when the user asks to add World ID, verify humans, stop bots or multi-accounting, add Sybil resistance, or mentions IDKit, Orb, World ID proof flows, World App proof flows, @worldcoin/idkit, signing keys, rp_id, or app_id.
version: 0.1.0
metadata:
author: worldcoin
@@ -38,7 +38,7 @@ Before changing code or creating Portal resources:
- target environment and test path: staging simulator, production World ID, or both
- Developer Portal MCP connection
- whether an RP signing key already exists in a server-side secret store
- - requested credential policy, feature access (especially Selfie Check (Beta)), and whether legacy proof fallback is needed
+ - requested credential policy and whether legacy proof fallback is needed
3. Report a short readiness summary and ask only for unresolved blockers. **Never ask the user to paste a signing key, Portal API key, or other secret into chat.** Ask only whether it exists and where the application expects it.
4. Build a TODO from the missing steps. Preserve working configuration and existing Portal resources unless the user explicitly wants replacements.
@@ -99,18 +99,24 @@ The credential decides what the user proves. Nail this down before scaffolding
|---|---|---|
| **`proofOfHuman`** — Proof of Human (flagship) | The user is a unique person, biometrically verified at an Orb | Sybil resistance, airdrops, one-vote-per-human, gated signups. **The default if the user said "proof of human" or "verify a real human."** |
| **`passport`** — Passport | The user holds a valid government passport (NFC-verified) | Higher-assurance flows where you need document-grade identity (regulated apps, age-gating, KYC-adjacent). |
-| **`selfieCheckLegacy`** — Selfie Check (Beta) | A liveness selfie signal backed by a World ID 3.0 proof | Lower-assurance "is a human in front of the camera" — friction/bot deterrence without the full Orb requirement. |
+| **`selfieCheck`** — Selfie Check | A liveness and facial-similarity credential backed by a World ID 4.0 proof | Medium-assurance friction and bot deterrence without the full Orb requirement. Returns a verified `sybil_score` risk signal. |
-**DO NOT default to `proofOfHuman` if the user said "passport" or "verify their ID"** — that's `passport`. **DO NOT default to `proofOfHuman` if the user said "selfie" or "liveness"** — that's `selfieCheckLegacy`. When in doubt, ask one question.
+**DO NOT default to `proofOfHuman` if the user said "passport" or "verify their ID"** — that's `passport`. **DO NOT default to `proofOfHuman` if the user said "selfie" or "liveness"** — that's `selfieCheck`. When in doubt, ask one question.
-Other legacy presets exist (`documentLegacy`, `deviceLegacy`); reach for them only when the user asks specifically. For sign-in / session reuse across visits, use the v4 **session** flow instead of a uniqueness preset (see the integrate doc).
+Other legacy presets exist (`documentLegacy`, `selfieCheckLegacy`, `deviceLegacy`); reach for them only when the user asks specifically. For sign-in / session reuse across visits, use the v4 **session** flow instead of a uniqueness preset (see the integrate doc).
-### Selfie Check (Beta) access
+### Selfie Check
-Before implementing or testing Selfie Check, confirm that its feature flag is
-enabled for the target app. If it is not enabled, stop and tell the user to
-request access through their World contact or the documented support path. A
-valid app or action does not imply Selfie Check access.
+Use `selfieCheck`, which requests the World ID 4.0 Selfie Check credential and
+always disables legacy proof fallback. Each Selfie Check response includes a
+required integer `sybil_score`; forward the complete IDKit result unchanged so
+the Developer Portal can verify the proof and version 2 integrity signature
+before the app uses the score.
+
+World ID 4.0 uniqueness proofs are one-time per action for each user. If the
+same user needs to complete Selfie Check more than once, use a different action
+for each check. Keep the deprecated `selfieCheckLegacy` preset only when
+maintaining an existing World ID 3.0 integration.
## Phase 4 — Implement the 6 integration steps and explain the WHY
@@ -150,7 +156,7 @@ Do not declare the integration complete from compilation or Portal configuration
- [ ] Backend verification succeeds and the exact IDKit result reaches `/api/v4/verify/{rp_id}`.
- [ ] The verified nullifier is persisted.
- [ ] Replaying the same nullifier is rejected by the database uniqueness constraint.
-- [ ] Relevant failures—unavailable Selfie Check, invalid action/signature, or environment mismatch—produce an actionable user-facing error instead of an indefinite loading state.
+- [ ] Relevant failures—replayed nullifiers, invalid action/signature, or environment mismatch—produce an actionable user-facing error instead of an indefinite loading state.
- [ ] JS/React failures retain the `debugReport` and `request_id` needed for diagnosis without logging secrets.
Run automated tests for the routes and persistence behavior. Clearly identify simulator, phone, or production checks that still require the user; never imply a manual proof flow ran when it did not.
diff --git a/world-id/credentials/11.mdx b/world-id/credentials/11.mdx
index 8e8a2a8..60f53f3 100644
--- a/world-id/credentials/11.mdx
+++ b/world-id/credentials/11.mdx
@@ -1,5 +1,5 @@
---
-title: "Selfie Check (Beta)"
+title: "Selfie Check"
icon: "camera"
iconType: "duotone"
description: "A medium-assurance biometric credential using the device camera for liveness and facial similarity."
@@ -10,29 +10,26 @@ description: "A medium-assurance biometric credential using the device camera fo
import { CredentialHero } from "/snippets/credential-hero.jsx";
documentLegacyselfieCheckLegacyselfieCheck for new integrations.deviceLegacydeviceLegacy only for existing Device integrations. For new integrations, use Selfie Check (Beta).deviceLegacy only for existing Device integrations. For new integrations, use Selfie Check.&a=
const expiresAt = request.expiresAt; // Unix seconds
@@ -173,15 +178,18 @@ const request = await IDKit.requestWithInviteCode({
app_id: "app_xxxxx",
action: "my-action",
rp_context,
- allow_legacy_proofs: true,
-}).preset(selfieCheckLegacy({ signal: "user-123" }));
+ allow_legacy_proofs: false,
+}).preset(selfieCheck({ signal: "user-123" }));
const connectorURI = request.connectorURI; // display to user (URL with code embedded)
const expiresAt = request.expiresAt; // drive a countdown
const completion = await request.pollUntilCompletion();
```
-The config object is unchanged. The `connectorURI` now includes `&c=&a=` params; use it alongside `expiresAt` in your UI. Polling, proof verification, and nullifier storage stay the same.
+The `connectorURI` now includes `&c=&a=` params; use it alongside
+`expiresAt` in your UI. Polling, proof verification, and nullifier storage stay
+the same. Set `allow_legacy_proofs` for the preset you choose; `selfieCheck`
+always uses `false`.
## Server-side helpers
diff --git a/world-id/idkit/kotlin.mdx b/world-id/idkit/kotlin.mdx
index b0f8fae..fd0b008 100644
--- a/world-id/idkit/kotlin.mdx
+++ b/world-id/idkit/kotlin.mdx
@@ -71,6 +71,10 @@ if (completion is IDKitCompletionResult.Success) {
}
```
+For `selfieCheck`, the successful result contains a `ResponseItem.SelfieV4`
+item with a required `sybilScore: ULong` value. Forward the complete result to
+your backend before using the score.
+
## Presets
```kotlin
@@ -80,6 +84,28 @@ import com.worldcoin.idkit.orbLegacy
val request = IDKit.request(config).preset(orbLegacy(signal = "user-123"))
```
+Use `selfieCheck` for the World ID 4.0 Selfie Check credential. Set
+`allowLegacyProofs` to `false`; the preset also enforces this value so it never
+falls back to a legacy proof.
+
+```kotlin
+import com.worldcoin.idkit.IDKit
+import com.worldcoin.idkit.selfieCheck
+
+val selfieConfig = IDKitRequestConfig(
+ appId = "app_xxxxx",
+ action = "my-action",
+ rpContext = rpContext,
+ allowLegacyProofs = false,
+ returnTo = "myapp://verify-done",
+ environment = Environment.PRODUCTION,
+)
+
+val request = IDKit.request(selfieConfig).preset(
+ selfieCheck(signal = "user-123")
+)
+```
+
## Polling patterns
- `pollStatusOnce()` for manual loops
diff --git a/world-id/idkit/mini-apps.mdx b/world-id/idkit/mini-apps.mdx
index 9420b03..dce4810 100644
--- a/world-id/idkit/mini-apps.mdx
+++ b/world-id/idkit/mini-apps.mdx
@@ -37,7 +37,7 @@ The Mini-App-specific details:
| Goal | IDKit preset |
| --- | --- |
| Strong sybil resistance or one-human-one-action checks | `proofOfHuman` |
-| Lower-friction liveness or bot deterrence | `selfieCheckLegacy` |
+| Lower-friction liveness or bot deterrence | `selfieCheck` |
| Passport-backed checks | `passport` |
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/react.mdx b/world-id/idkit/react.mdx
index ff2c1f3..1d94654 100644
--- a/world-id/idkit/react.mdx
+++ b/world-id/idkit/react.mdx
@@ -80,6 +80,11 @@ const rpContext: RpContext = {
- If `handleVerify` throws/rejects, the widget enters an error state, emits `onError("failed_by_host_app")`, and does not call `onSuccess`. This means World App already returned a proof, but your callback or backend did not accept it.
- `onError` is optional.
+For `selfieCheck`, `result.responses` contains a typed
+`SelfieCheckResponseItemV4` with a required numeric `sybil_score`. Only use the
+score after `handleVerify` has successfully verified the complete result through
+your backend.
+
## Headless hooks
### `useIDKitRequest`
@@ -122,7 +127,7 @@ Hook result fields:
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.
```tsx
-import { IDKitInviteCodeRequestWidget, selfieCheckLegacy } from "@worldcoin/idkit";
+import { IDKitInviteCodeRequestWidget, selfieCheck } from "@worldcoin/idkit";
{ /* ... */ }}
onSuccess={() => { /* ... */ }}
/>;
@@ -172,7 +177,7 @@ import { IDKitRequestWidget, orbLegacy } from "@worldcoin/idkit";
```tsx
// After — invite-code widget
-import { IDKitInviteCodeRequestWidget, selfieCheckLegacy } from "@worldcoin/idkit";
+import { IDKitInviteCodeRequestWidget, selfieCheck } from "@worldcoin/idkit";
;
diff --git a/world-id/idkit/swift.mdx b/world-id/idkit/swift.mdx
index 95585b5..7f43ee0 100644
--- a/world-id/idkit/swift.mdx
+++ b/world-id/idkit/swift.mdx
@@ -76,13 +76,26 @@ case .failure(let error):
}
```
+For `selfieCheck`, the successful result contains a `ResponseItem.selfieV4`
+case with a required `sybilScore: UInt64` value. Forward the complete result to
+your backend before using the score.
+
## Invite-code mode
Use `presetWithInviteCode(_:)` on the builder to return an `IDKitInviteCodeRequest` instead of `IDKitRequest`. The polling surface is identical. See [Invite-code mode](/world-id/idkit/verification-flows#with-invite-code-mode) for when to use it.
```swift
-let request = try IDKit.request(config: config)
- .presetWithInviteCode(selfieCheckLegacy(signal: "user-123"))
+let selfieConfig = IDKitRequestConfig(
+ appId: "app_xxxxx",
+ action: "my-action",
+ rpContext: rpContext,
+ allowLegacyProofs: false,
+ returnTo: "myapp://verify-done",
+ environment: .production
+)
+
+let request = try IDKit.request(config: selfieConfig)
+ .presetWithInviteCode(selfieCheck(signal: "user-123"))
let connectorURL = request.connectorURL // URL with &c=&a=
let expiresAt = request.expiresAt // Date
@@ -102,15 +115,18 @@ let completion = await request.pollUntilCompletion()
```swift
// After — invite-code mode
-let request = try IDKit.request(config: config)
- .presetWithInviteCode(selfieCheckLegacy(signal: "user-123"))
+let request = try IDKit.request(config: selfieConfig)
+ .presetWithInviteCode(selfieCheck(signal: "user-123"))
let connectorURL = request.connectorURL // display to user (URL with code embedded)
let expiresAt = request.expiresAt // drive a countdown
let completion = await request.pollUntilCompletion()
```
-The config object is unchanged. The `connectorURL` now includes `&c=&a=` params; use it alongside `expiresAt` in your UI. Polling, proof verification, and nullifier storage stay the same.
+The `connectorURL` now includes `&c=&a=` params; use it alongside
+`expiresAt` in your UI. Polling, proof verification, and nullifier storage stay
+the same. Set `allowLegacyProofs` for the preset you choose; `selfieCheck`
+always uses `false`.
`IDKitInviteCodeRequest` exposes:
diff --git a/world-id/idkit/verification-flows.mdx b/world-id/idkit/verification-flows.mdx
index a1467b6..597c063 100644
--- a/world-id/idkit/verification-flows.mdx
+++ b/world-id/idkit/verification-flows.mdx
@@ -130,4 +130,4 @@ sequenceDiagram
**Integrate**
-Setup is identical to the [standard integration](/world-id/idkit/integrate) — only the request call changes. Only the `selfieCheckLegacy` preset is supported for Selfie Check (Beta) today. It returns World ID 3.0 proofs; Selfie Check with World ID 4.0 is not available yet. For code samples and migration guides, see the per-SDK sections: [JavaScript](/world-id/idkit/javascript#invite-code-mode), [React](/world-id/idkit/react#invite-code-mode), [Swift](/world-id/idkit/swift#invite-code-mode).
+Setup is identical to the [standard integration](/world-id/idkit/integrate) — only the request call changes. Use the `selfieCheck` preset with `allow_legacy_proofs: false` to request Selfie Check through invite-code mode. For code samples and migration guides, see the per-SDK sections: [JavaScript](/world-id/idkit/javascript#invite-code-mode), [React](/world-id/idkit/react#invite-code-mode), [Swift](/world-id/idkit/swift#invite-code-mode).
diff --git a/world-id/overview.mdx b/world-id/overview.mdx
index 43c46e2..4d716ae 100644
--- a/world-id/overview.mdx
+++ b/world-id/overview.mdx
@@ -54,7 +54,7 @@ Through credentials like Proof of Human, Document, and Selfie Check, World ID ex
- Selfie Check Beta
+ Selfie Check
Low-friction liveness and uniqueness signal from a selfie flow. Best for sign-up and bot defense where speed matters most.
diff --git a/world-id/sandbox/testing-selfie-check.mdx b/world-id/sandbox/testing-selfie-check.mdx
index 8c45d71..c35ef71 100644
--- a/world-id/sandbox/testing-selfie-check.mdx
+++ b/world-id/sandbox/testing-selfie-check.mdx
@@ -1,21 +1,16 @@
---
-title: "Testing Selfie Check (Beta) in Sandbox"
-description: "Coverage, critical user journeys, and known limitations for testing your Selfie Check (Beta) integration in Sandbox."
+title: "Testing Selfie Check in Sandbox"
+description: "Coverage, critical user journeys, and known limitations for testing your Selfie Check integration in Sandbox."
"og:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png"
"twitter:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png"
---
{/* cspell:ignore idkit DoB reinstalls */}
-Sandbox lets you run the full [Selfie Check (Beta)](/world-id/credentials/11) relying-party
+Sandbox lets you run the full [Selfie Check](/world-id/credentials/11) relying-party
journey end-to-end — from your surface, through IDKit, into the sandbox World ID app,
and back — without touching production identities or real proofs.
-
- Selfie Check (Beta) must be enabled for your app before you can test it. To
- enable the feature flag, request access through your World point of contact.
-
-
New to Sandbox? Start with [What is Sandbox?](/world-id/sandbox/what-is-sandbox) and
[How to get access](/world-id/sandbox/sandbox-access) before working through this
guide.
From ab9b001072aaadb8741134c4b015f0b0ef02b987 Mon Sep 17 00:00:00 2001
From: Takis Kakalis <80459599+Takaros999@users.noreply.github.com>
Date: Wed, 2 Sep 2026 12:13:32 -0700
Subject: [PATCH 2/4] docs: clarify user presence response
---
openapi/developer-portal.json | 6 +++---
snippets/idkit-response.mdx | 12 ++++--------
2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/openapi/developer-portal.json b/openapi/developer-portal.json
index 3c5bc93..0d03b0b 100644
--- a/openapi/developer-portal.json
+++ b/openapi/developer-portal.json
@@ -1368,7 +1368,7 @@
},
"user_presence_completed": {
"type": "boolean",
- "description": "Whether World App completed the requested user-presence check. IDKit always sends it; treat a missing value as false."
+ "description": "Whether World App completed the requested user-presence check. IDKit includes this field only when `require_user_presence` was true in the request."
}
}
},
@@ -1413,7 +1413,7 @@
},
"user_presence_completed": {
"type": "boolean",
- "description": "Whether World App completed the requested user-presence check. IDKit always sends it; treat a missing value as false."
+ "description": "Whether World App completed the requested user-presence check. IDKit includes this field only when `require_user_presence` was true in the request."
}
}
},
@@ -1457,7 +1457,7 @@
},
"user_presence_completed": {
"type": "boolean",
- "description": "Whether World App completed the requested user-presence check. IDKit always sends it; treat a missing value as false."
+ "description": "Whether World App completed the requested user-presence check. IDKit includes this field only when `require_user_presence` was true in the request."
}
}
},
diff --git a/snippets/idkit-response.mdx b/snippets/idkit-response.mdx
index 578e658..d160817 100644
--- a/snippets/idkit-response.mdx
+++ b/snippets/idkit-response.mdx
@@ -13,8 +13,7 @@
"merkle_root": "0x0abc123...root_hash",
"nullifier": "0x04e5f6...nullifier_hash"
}
- ],
- "user_presence_completed": false
+ ]
}
```
@@ -33,8 +32,7 @@
"issuer_schema_id": 1,
"expires_at_min": 1756166400
}
- ],
- "user_presence_completed": false
+ ]
}
```
@@ -61,8 +59,7 @@
"expires_at_min": 1788302888,
"sybil_score": 10
}
- ],
- "user_presence_completed": true
+ ]
}
```
@@ -81,8 +78,7 @@
"issuer_schema_id": 1,
"expires_at_min": 1756166400
}
- ],
- "user_presence_completed": false
+ ]
}
```
From f140b8633601f7a814e7bbd38595a342af3b6723 Mon Sep 17 00:00:00 2001
From: Takis Kakalis <80459599+Takaros999@users.noreply.github.com>
Date: Wed, 2 Sep 2026 14:34:28 -0700
Subject: [PATCH 3/4] bop
---
openapi/developer-portal.json | 8 +++---
snippets/idkit-response.mdx | 2 +-
world-id/SKILL.md | 2 +-
world-id/credentials/11.mdx | 24 ++++--------------
world-id/idkit/credentials.mdx | 46 ++++------------------------------
world-id/idkit/kotlin.mdx | 2 +-
6 files changed, 17 insertions(+), 67 deletions(-)
diff --git a/openapi/developer-portal.json b/openapi/developer-portal.json
index 0d03b0b..738f095 100644
--- a/openapi/developer-portal.json
+++ b/openapi/developer-portal.json
@@ -743,7 +743,7 @@
}
},
"selfie_check_v4": {
- "summary": "Selfie Check (protocol 4.0)",
+ "summary": "Selfie Check",
"value": {
"protocol_version": "4.0",
"nonce": "0xabc123",
@@ -1279,7 +1279,7 @@
"IntegrityBundle": {
"type": "object",
"required": ["version", "signature_format", "timestamp", "signature", "jwt"],
- "description": "World ID App integrity attestation. Selfie Check 4.0 requires version 2, which covers the disclosed `sybil_score`.",
+ "description": "World ID App integrity attestation. Selfie Check responses with `issuer_schema_id: 11` require version 2, which covers the disclosed `sybil_score`.",
"properties": {
"version": {
"type": "integer",
@@ -1527,7 +1527,7 @@
"sybil_score": {
"type": "integer",
"minimum": 0,
- "description": "Selfie Check z-score decoded to an integer. Required only when `issuer_schema_id` is 11. Higher values indicate a stronger potential duplicate signal; this is not a probability or match count."
+ "description": "Versioned Selfie Check risk signal represented as an integer. Required only when `issuer_schema_id` is 11."
}
}
},
@@ -1574,7 +1574,7 @@
"sybil_score": {
"type": "integer",
"minimum": 0,
- "description": "Selfie Check z-score decoded to an integer. Required only when `issuer_schema_id` is 11."
+ "description": "Versioned Selfie Check risk signal represented as an integer. Required only when `issuer_schema_id` is 11."
}
}
},
diff --git a/snippets/idkit-response.mdx b/snippets/idkit-response.mdx
index d160817..1fc4feb 100644
--- a/snippets/idkit-response.mdx
+++ b/snippets/idkit-response.mdx
@@ -36,7 +36,7 @@
}
```
-```json title="World ID 4.0 Selfie Check"
+```json title="Selfie Check"
{
"protocol_version": "4.0",
"nonce": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
diff --git a/world-id/SKILL.md b/world-id/SKILL.md
index 44bb06d..20a3d0e 100644
--- a/world-id/SKILL.md
+++ b/world-id/SKILL.md
@@ -107,7 +107,7 @@ Other legacy presets exist (`documentLegacy`, `selfieCheckLegacy`, `deviceLegacy
### Selfie Check
-Use `selfieCheck`, which requests the World ID 4.0 Selfie Check credential and
+Use `selfieCheck`, which requests the Selfie Check credential and
always disables legacy proof fallback. Each Selfie Check response includes a
required integer `sybil_score`; forward the complete IDKit result unchanged so
the Developer Portal can verify the proof and version 2 integrity signature
diff --git a/world-id/credentials/11.mdx b/world-id/credentials/11.mdx
index 60f53f3..a46863b 100644
--- a/world-id/credentials/11.mdx
+++ b/world-id/credentials/11.mdx
@@ -43,25 +43,11 @@ other prerequisite credential is required.
## Understand the Sybil score
-Each World ID 4.0 Selfie Check response includes `sybil_score`, a non-negative
-integer derived from the z-score of the closest face-match signal. A higher value
-means the match is more statistically unusual and is a stronger signal that the
-person may already be enrolled. The score is not a probability, percentage, or
-count of matching accounts.
-
-Treat `sybil_score` as one input to your abuse policy and choose a threshold that
-fits your use case. Only use the score after your backend has forwarded the
-complete IDKit result to the [Developer Portal verification endpoint](/api-reference/developer-portal/verify)
-and received a successful response. The verifier requires integrity bundle version
-2 for Selfie Check and verifies that the score is covered by the World ID App
-integrity signature.
-
-
- World ID 4.0 uniqueness proofs are one-time per action for each user. If the same
- user needs to complete Selfie Check more than once, use a different action for
- each check. Reusing the same action produces the same action-scoped nullifier and
- cannot be accepted as a new one-time verification.
-
+Each Selfie Check response includes a versioned `sybil_score` that
+can help an app assess the risk of repeated enrollment. It is a risk signal, not
+a uniqueness verdict, and should be considered alongside other evidence. The
+response also includes an `integrity_bundle` that lets the Developer Portal
+verify it came from an authentic World ID App.
## How it works
diff --git a/world-id/idkit/credentials.mdx b/world-id/idkit/credentials.mdx
index ac6f9ff..13f1722 100644
--- a/world-id/idkit/credentials.mdx
+++ b/world-id/idkit/credentials.mdx
@@ -105,7 +105,7 @@ const preset = passport({ signal: "user-123" });
## Selfie Check
-Use `selfieCheck()` to request the World ID 4.0 Selfie Check credential. This
+Use `selfieCheck()` to request Selfie Check. This
preset always disables fallback to legacy proofs.
Anyone with World ID App can complete the flow—no Orb or document credential is
@@ -145,46 +145,10 @@ const preset = selfieCheck({ signal: "user-123" });
```
-A successful Selfie Check response includes a required `sybil_score` on the
-response item with `identifier: "selfie"` and `issuer_schema_id: 11`:
-
-```json
-{
- "protocol_version": "4.0",
- "action": "my-action",
- "integrity_bundle": {
- "version": 2,
- "signature_format": "apple_app_attest",
- "timestamp": 1788302923,
- "signature": "...",
- "jwt": "..."
- },
- "responses": [
- {
- "identifier": "selfie",
- "issuer_schema_id": 11,
- "nullifier": "0x...",
- "proof": ["0x...", "0x...", "0x...", "0x...", "0x..."],
- "expires_at_min": 1788302888,
- "sybil_score": 10
- }
- ]
-}
-```
-
-The integer is derived from the disclosed face-match z-score. Higher values are
-a stronger potential duplicate signal; the value is not a probability or a count
-of matching accounts. Forward the complete response unchanged and only use
-`sybil_score` after the Developer Portal verifies the proof and version 2 integrity
-signature. See [Selfie Check](/world-id/credentials/11#understand-the-sybil-score)
-for interpretation guidance.
-
-
- If the same user needs to complete Selfie Check more than once, use a different
- action for each World ID 4.0 uniqueness proof. Reusing the same action produces
- the same action-scoped nullifier and cannot be accepted as a new one-time
- verification.
-
+The response includes a required `sybil_score` and an `integrity_bundle` that
+lets the Developer Portal verify the response came from an authentic World ID
+App. Forward the complete IDKit result unchanged and only use the score after
+server-side verification succeeds.
To test your integration end-to-end, see [Testing Selfie Check in Sandbox](/world-id/sandbox/testing-selfie-check).
diff --git a/world-id/idkit/kotlin.mdx b/world-id/idkit/kotlin.mdx
index fd0b008..9aec6b8 100644
--- a/world-id/idkit/kotlin.mdx
+++ b/world-id/idkit/kotlin.mdx
@@ -84,7 +84,7 @@ import com.worldcoin.idkit.orbLegacy
val request = IDKit.request(config).preset(orbLegacy(signal = "user-123"))
```
-Use `selfieCheck` for the World ID 4.0 Selfie Check credential. Set
+Use `selfieCheck` for Selfie Check. Set
`allowLegacyProofs` to `false`; the preset also enforces this value so it never
falls back to a legacy proof.
From dc0f5c4f8abbcc156e4d1cbb981d5877e7bfc795 Mon Sep 17 00:00:00 2001
From: Takis Kakalis <80459599+Takaros999@users.noreply.github.com>
Date: Wed, 2 Sep 2026 14:47:39 -0700
Subject: [PATCH 4/4] beep
---
world-id/SKILL.md | 15 +++++++--------
world-id/idkit/credentials.mdx | 9 +++------
world-id/idkit/integrate.mdx | 5 -----
world-id/idkit/javascript.mdx | 21 +++++++--------------
world-id/idkit/kotlin.mdx | 26 --------------------------
world-id/idkit/react.mdx | 17 ++++++-----------
world-id/idkit/swift.mdx | 26 +++++---------------------
world-id/idkit/verification-flows.mdx | 2 +-
8 files changed, 29 insertions(+), 92 deletions(-)
diff --git a/world-id/SKILL.md b/world-id/SKILL.md
index 20a3d0e..966f3ff 100644
--- a/world-id/SKILL.md
+++ b/world-id/SKILL.md
@@ -103,20 +103,19 @@ The credential decides what the user proves. Nail this down before scaffolding
**DO NOT default to `proofOfHuman` if the user said "passport" or "verify their ID"** — that's `passport`. **DO NOT default to `proofOfHuman` if the user said "selfie" or "liveness"** — that's `selfieCheck`. When in doubt, ask one question.
-Other legacy presets exist (`documentLegacy`, `selfieCheckLegacy`, `deviceLegacy`); reach for them only when the user asks specifically. For sign-in / session reuse across visits, use the v4 **session** flow instead of a uniqueness preset (see the integrate doc).
+Other legacy presets exist (`documentLegacy`, `deviceLegacy`); reach for them only when the user asks specifically. For sign-in / session reuse across visits, use the v4 **session** flow instead of a uniqueness preset (see the integrate doc).
### Selfie Check
-Use `selfieCheck`, which requests the Selfie Check credential and
-always disables legacy proof fallback. Each Selfie Check response includes a
-required integer `sybil_score`; forward the complete IDKit result unchanged so
-the Developer Portal can verify the proof and version 2 integrity signature
-before the app uses the score.
+Use `selfieCheck`, which requests the Selfie Check credential. Each Selfie Check
+response includes a required integer `sybil_score`; forward the complete IDKit
+result unchanged so the Developer Portal can verify the proof and version 2
+integrity signature before the app uses the score.
World ID 4.0 uniqueness proofs are one-time per action for each user. If the
same user needs to complete Selfie Check more than once, use a different action
-for each check. Keep the deprecated `selfieCheckLegacy` preset only when
-maintaining an existing World ID 3.0 integration.
+for each check. Migrate existing `selfieCheckLegacy` integrations to
+`selfieCheck`.
## Phase 4 — Implement the 6 integration steps and explain the WHY
diff --git a/world-id/idkit/credentials.mdx b/world-id/idkit/credentials.mdx
index 13f1722..4cb841e 100644
--- a/world-id/idkit/credentials.mdx
+++ b/world-id/idkit/credentials.mdx
@@ -105,8 +105,7 @@ const preset = passport({ signal: "user-123" });
## Selfie Check
-Use `selfieCheck()` to request Selfie Check. This
-preset always disables fallback to legacy proofs.
+Use `selfieCheck()` to request Selfie Check.
Anyone with World ID App can complete the flow—no Orb or document credential is
required. Forward the complete IDKit result to the
@@ -150,6 +149,8 @@ lets the Developer Portal verify the response came from an authentic World ID
App. Forward the complete IDKit result unchanged and only use the score after
server-side verification succeeds.
+If you use the legacy `selfieCheckLegacy` preset, migrate to `selfieCheck`.
+
To test your integration end-to-end, see [Testing Selfie Check in Sandbox](/world-id/sandbox/testing-selfie-check).
## Identity Check (Preview)
@@ -280,10 +281,6 @@ These presets only return World ID 3.0 proofs. Use them for existing integration
documentLegacy
At least a Document verification. Returns the user's highest legacy credential: Document, Secure Document, or Orb.
-
- selfieCheckLegacy
- Deprecated. Returns the World ID 3.0 Selfie Check proof. Keep it only for an existing legacy integration; use selfieCheck for new integrations.
-
deviceLegacy
Deprecated. Keep deviceLegacy only for existing Device integrations. For new integrations, use Selfie Check.
diff --git a/world-id/idkit/integrate.mdx b/world-id/idkit/integrate.mdx
index 2ede2bc..abbef5b 100644
--- a/world-id/idkit/integrate.mdx
+++ b/world-id/idkit/integrate.mdx
@@ -313,11 +313,6 @@ forward it directly to `POST https://developer.world.org/api/v4/verify/{rp_id}`.
Forward the IDKit result payload as-is. No field remapping is required.
-For Selfie Check, only use `responses[].sybil_score` after this endpoint returns
-success. Selfie Check responses require integrity bundle version 2, which lets
-the Developer Portal verify that the score was included in the World ID App
-integrity signature.
-
```typescript title="app/api/verify-proof/route.ts"
import { NextResponse } from "next/server";
import type { IDKitResult } from "@worldcoin/idkit";
diff --git a/world-id/idkit/javascript.mdx b/world-id/idkit/javascript.mdx
index 6f87416..03d8ce6 100644
--- a/world-id/idkit/javascript.mdx
+++ b/world-id/idkit/javascript.mdx
@@ -29,7 +29,7 @@ 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
-- `orbLegacy`, `secureDocumentLegacy`, `documentLegacy`, `selfieCheckLegacy`, and `deviceLegacy` for legacy presets
+- `orbLegacy`, `secureDocumentLegacy`, `documentLegacy`, and `deviceLegacy` for legacy presets
Each entry point returns a builder. Finalize it with `.preset(...)`.
@@ -82,10 +82,6 @@ After `.preset(...)`, you get an `IDKitRequest` object:
- `pollUntilCompletion({ pollInterval, timeout })`
- `getDebugReport()`
-When you use `selfieCheck`, the successful result contains a
-`SelfieCheckResponseItemV4`. Its required `sybil_score` field is a JavaScript
-`number`. Forward the complete result to your backend before using the score.
-
```ts
import { IDKitErrorCodes } from "@worldcoin/idkit-core";
@@ -134,14 +130,14 @@ if (!completion.success) {
Use `IDKit.requestWithInviteCode(config)` to open a landing page that displays both an invite code and a QR code. Validation, the returned `Status` shape, and the poll loop are identical to `IDKit.request`. See [Invite-code mode](/world-id/idkit/verification-flows#with-invite-code-mode) for when to use it.
```ts
-import { IDKit, selfieCheck } from "@worldcoin/idkit-core";
+import { IDKit, proofOfHuman } from "@worldcoin/idkit-core";
const request = await IDKit.requestWithInviteCode({
app_id: "app_xxxxx",
action: "my-action",
rp_context,
- allow_legacy_proofs: false,
-}).preset(selfieCheck({ signal: "user-123" }));
+ allow_legacy_proofs: true,
+}).preset(proofOfHuman({ signal: "user-123" }));
const connectorURI = request.connectorURI; // URL with &c=&a=
const expiresAt = request.expiresAt; // Unix seconds
@@ -178,18 +174,15 @@ const request = await IDKit.requestWithInviteCode({
app_id: "app_xxxxx",
action: "my-action",
rp_context,
- allow_legacy_proofs: false,
-}).preset(selfieCheck({ signal: "user-123" }));
+ allow_legacy_proofs: true,
+}).preset(proofOfHuman({ signal: "user-123" }));
const connectorURI = request.connectorURI; // display to user (URL with code embedded)
const expiresAt = request.expiresAt; // drive a countdown
const completion = await request.pollUntilCompletion();
```
-The `connectorURI` now includes `&c=&a=` params; use it alongside
-`expiresAt` in your UI. Polling, proof verification, and nullifier storage stay
-the same. Set `allow_legacy_proofs` for the preset you choose; `selfieCheck`
-always uses `false`.
+The config object is unchanged. The `connectorURI` now includes `&c=&a=` params; use it alongside `expiresAt` in your UI. Polling, proof verification, and nullifier storage stay the same.
## Server-side helpers
diff --git a/world-id/idkit/kotlin.mdx b/world-id/idkit/kotlin.mdx
index 9aec6b8..b0f8fae 100644
--- a/world-id/idkit/kotlin.mdx
+++ b/world-id/idkit/kotlin.mdx
@@ -71,10 +71,6 @@ if (completion is IDKitCompletionResult.Success) {
}
```
-For `selfieCheck`, the successful result contains a `ResponseItem.SelfieV4`
-item with a required `sybilScore: ULong` value. Forward the complete result to
-your backend before using the score.
-
## Presets
```kotlin
@@ -84,28 +80,6 @@ import com.worldcoin.idkit.orbLegacy
val request = IDKit.request(config).preset(orbLegacy(signal = "user-123"))
```
-Use `selfieCheck` for Selfie Check. Set
-`allowLegacyProofs` to `false`; the preset also enforces this value so it never
-falls back to a legacy proof.
-
-```kotlin
-import com.worldcoin.idkit.IDKit
-import com.worldcoin.idkit.selfieCheck
-
-val selfieConfig = IDKitRequestConfig(
- appId = "app_xxxxx",
- action = "my-action",
- rpContext = rpContext,
- allowLegacyProofs = false,
- returnTo = "myapp://verify-done",
- environment = Environment.PRODUCTION,
-)
-
-val request = IDKit.request(selfieConfig).preset(
- selfieCheck(signal = "user-123")
-)
-```
-
## Polling patterns
- `pollStatusOnce()` for manual loops
diff --git a/world-id/idkit/react.mdx b/world-id/idkit/react.mdx
index 1d94654..331a54b 100644
--- a/world-id/idkit/react.mdx
+++ b/world-id/idkit/react.mdx
@@ -80,11 +80,6 @@ const rpContext: RpContext = {
- If `handleVerify` throws/rejects, the widget enters an error state, emits `onError("failed_by_host_app")`, and does not call `onSuccess`. This means World App already returned a proof, but your callback or backend did not accept it.
- `onError` is optional.
-For `selfieCheck`, `result.responses` contains a typed
-`SelfieCheckResponseItemV4` with a required numeric `sybil_score`. Only use the
-score after `handleVerify` has successfully verified the complete result through
-your backend.
-
## Headless hooks
### `useIDKitRequest`
@@ -127,7 +122,7 @@ Hook result fields:
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.
```tsx
-import { IDKitInviteCodeRequestWidget, selfieCheck } from "@worldcoin/idkit";
+import { IDKitInviteCodeRequestWidget, proofOfHuman } from "@worldcoin/idkit";
{ /* ... */ }}
onSuccess={() => { /* ... */ }}
/>;
@@ -177,7 +172,7 @@ import { IDKitRequestWidget, orbLegacy } from "@worldcoin/idkit";
```tsx
// After — invite-code widget
-import { IDKitInviteCodeRequestWidget, selfieCheck } from "@worldcoin/idkit";
+import { IDKitInviteCodeRequestWidget, proofOfHuman } from "@worldcoin/idkit";
;
diff --git a/world-id/idkit/swift.mdx b/world-id/idkit/swift.mdx
index 7f43ee0..9bc1362 100644
--- a/world-id/idkit/swift.mdx
+++ b/world-id/idkit/swift.mdx
@@ -76,26 +76,13 @@ case .failure(let error):
}
```
-For `selfieCheck`, the successful result contains a `ResponseItem.selfieV4`
-case with a required `sybilScore: UInt64` value. Forward the complete result to
-your backend before using the score.
-
## Invite-code mode
Use `presetWithInviteCode(_:)` on the builder to return an `IDKitInviteCodeRequest` instead of `IDKitRequest`. The polling surface is identical. See [Invite-code mode](/world-id/idkit/verification-flows#with-invite-code-mode) for when to use it.
```swift
-let selfieConfig = IDKitRequestConfig(
- appId: "app_xxxxx",
- action: "my-action",
- rpContext: rpContext,
- allowLegacyProofs: false,
- returnTo: "myapp://verify-done",
- environment: .production
-)
-
-let request = try IDKit.request(config: selfieConfig)
- .presetWithInviteCode(selfieCheck(signal: "user-123"))
+let request = try IDKit.request(config: config)
+ .presetWithInviteCode(proofOfHuman(signal: "user-123"))
let connectorURL = request.connectorURL // URL with &c=&a=
let expiresAt = request.expiresAt // Date
@@ -115,18 +102,15 @@ let completion = await request.pollUntilCompletion()
```swift
// After — invite-code mode
-let request = try IDKit.request(config: selfieConfig)
- .presetWithInviteCode(selfieCheck(signal: "user-123"))
+let request = try IDKit.request(config: config)
+ .presetWithInviteCode(proofOfHuman(signal: "user-123"))
let connectorURL = request.connectorURL // display to user (URL with code embedded)
let expiresAt = request.expiresAt // drive a countdown
let completion = await request.pollUntilCompletion()
```
-The `connectorURL` now includes `&c=&a=` params; use it alongside
-`expiresAt` in your UI. Polling, proof verification, and nullifier storage stay
-the same. Set `allowLegacyProofs` for the preset you choose; `selfieCheck`
-always uses `false`.
+The config object is unchanged. The `connectorURL` now includes `&c=&a=` params; use it alongside `expiresAt` in your UI. Polling, proof verification, and nullifier storage stay the same.
`IDKitInviteCodeRequest` exposes:
diff --git a/world-id/idkit/verification-flows.mdx b/world-id/idkit/verification-flows.mdx
index 597c063..8e20009 100644
--- a/world-id/idkit/verification-flows.mdx
+++ b/world-id/idkit/verification-flows.mdx
@@ -130,4 +130,4 @@ sequenceDiagram
**Integrate**
-Setup is identical to the [standard integration](/world-id/idkit/integrate) — only the request call changes. Use the `selfieCheck` preset with `allow_legacy_proofs: false` to request Selfie Check through invite-code mode. For code samples and migration guides, see the per-SDK sections: [JavaScript](/world-id/idkit/javascript#invite-code-mode), [React](/world-id/idkit/react#invite-code-mode), [Swift](/world-id/idkit/swift#invite-code-mode).
+Setup is identical to the [standard integration](/world-id/idkit/integrate) — only the request call changes. Choose the appropriate preset in [Configure Credentials](/world-id/idkit/credentials). For code samples and migration guides, see the per-SDK sections: [JavaScript](/world-id/idkit/javascript#invite-code-mode), [React](/world-id/idkit/react#invite-code-mode), [Swift](/world-id/idkit/swift#invite-code-mode).