Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 121 additions & 16 deletions world-id/idkit/credentials.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: "Configure Credentials"
"twitter:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png"
---

{/* cspell:ignore NFC liveness */}
{/* cspell:ignore NFC eID liveness */}

A [Credential](https://docs.rs/world-id-primitives/latest/world_id_primitives/credential/struct.Credential.html) is a statement an issuer makes about a World ID holder. In IDKit, the credential you request determines what the user proves to your application.

Expand All @@ -15,6 +15,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` |
| Selfie Check | A low-assurance biometric credential using the device camera for liveness and facial similarity. | `selfieCheckLegacy` today. World ID 4.0 support is rolling out soon. |
| 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`. |

You can also add a liveness check to any preset with `require_user_presence`.

Expand All @@ -24,7 +25,7 @@ You can also add a liveness check to any preset with `require_user_presence`.

# SDK presets

This page focuses on preset helpers for common credential requests: `proofOfHuman`, `passport`, `selfieCheckLegacy`, and the legacy presets.
This page focuses on preset helpers for common credential requests: `proofOfHuman`, `passport`, `selfieCheckLegacy`, `identityCheck`, and the legacy presets.

The snippets below use `rp_context` as if it was already generated and signed by your backend. See [Integrate IDKit](/world-id/idkit/integrate) for the full RP-signing flow.

Expand Down Expand Up @@ -141,9 +142,74 @@ const preset = selfieCheckLegacy({ signal: "user-123" });
```
</CodeGroup>

## Identity Check (Preview)

<Note>
Identity Check is currently in preview. If you're interested in using or learning more about Identity Check, please contact us.
</Note>


Identity Check lets your app ask the user to attest that document-backed attributes match your policy, without asking you to handle the underlying document data. Use it for eligibility checks such as minimum age, document type, issuing country, or nationality. You can request attributes such as:

| Attribute | Value type |
| --- | --- |
| `document_type` | `"passport"`, `"eid"` or `"mnc"` |
| `document_number` | `string` |
| `issuing_country` | ISO 3166-1 alpha-3 country code |
| `full_name` | `string` |
| `minimum_age` | `number` |
| `nationality` | ISO 3166-1 alpha-3 country code |

<CodeGroup title="Identity Check">
```typescript title="JavaScript"
import { IDKit, identityCheck } from "@worldcoin/idkit-core";
Comment thread
Takaros999 marked this conversation as resolved.

const preset = identityCheck({
attributes: [
{ type: "document_type", value: "passport" },
{ type: "minimum_age", value: 18 },
],
});

const request = await IDKit.request({
app_id: "app_xxxxx",
action: "my-action",
rp_context,
allow_legacy_proofs: false,
}).preset(preset);
```

```tsx title="React"
import { IDKitRequestWidget, identityCheck } from "@worldcoin/idkit";

const preset = identityCheck({
attributes: [
{ type: "document_type", value: "passport" },
{ type: "minimum_age", value: 18 },
],
});

<IDKitRequestWidget
open={open}
onOpenChange={setOpen}
app_id="app_xxxxx"
action="my-action"
rp_context={rpContext}
allow_legacy_proofs={false}
preset={preset}
handleVerify={handleVerify}
onSuccess={(result) => { /* ... */ }}
/>;
```
</CodeGroup>

Successful Identity Check responses include `identity_attested` so your backend can distinguish whether the requested attributes matched.

## User presence and liveness

`require_user_presence` asks World App to perform an additional liveness step before completing the proof. This flag works with presets.
To check for user presence and liveness, add the `require_user_presence` flag to your request. This is a request-level flag, not a credential; it asks World App for a fresh liveness check before returning the proof and fails with `user_presence_failed` if the check is not completed.

Depending on the credential requested, World App matches the user's live selfie to the credential image, such as the passport photo or the image captured during Orb verification.

<CodeGroup title="User presence">
```typescript title="JavaScript"
Expand Down Expand Up @@ -180,23 +246,62 @@ const preset = proofOfHuman({ signal: "user-123" });
```
</CodeGroup>

If the user does not complete the liveness step, the request fails with `user_presence_failed`.

## Other legacy presets

These presets only return World ID 3.0 proofs. Keep them for existing integrations or when you specifically need the older verification level.

| Preset | What it requests |
| --- | --- |
| `orbLegacy` | Orb verification. |
| `secureDocumentLegacy` | At least a Secure Document verification. Returns the user's highest legacy credential: Secure Document or Orb. |
| `documentLegacy` | At least a Document verification. Returns the user's highest legacy credential: Document, Secure Document, or Orb. |
| `deviceLegacy` | At least a Device verification. Returns the user's highest legacy credential: Device, Document, Secure Document, or Orb. |
<table>
<thead>
<tr>
<th className="p-2 text-left align-middle whitespace-nowrap">Preset</th>
<th className="p-2 text-left align-middle">What it requests</th>
</tr>
</thead>
<tbody>
<tr>
<td className="p-2 align-middle whitespace-nowrap"><code>orbLegacy</code></td>
<td className="p-2 align-middle">Orb verification.</td>
</tr>
<tr>
<td className="p-2 align-middle whitespace-nowrap"><code>secureDocumentLegacy</code></td>
<td className="p-2 align-middle">At least a Secure Document verification. Returns the user's highest legacy credential: Secure Document or Orb.</td>
</tr>
<tr>
<td className="p-2 align-middle whitespace-nowrap"><code>documentLegacy</code></td>
<td className="p-2 align-middle">At least a Document verification. Returns the user's highest legacy credential: Document, Secure Document, or Orb.</td>
</tr>
<tr>
<td className="p-2 align-middle whitespace-nowrap"><code>deviceLegacy</code></td>
<td className="p-2 align-middle">At least a Device verification. Returns the user's highest legacy credential: Device, Document, Secure Document, or Orb.</td>
</tr>
</tbody>
</table>

## Common parameters

| Parameter | Where it is used | Description |
| --- | --- | --- |
| `signal` | Presets | Binds application context into the proof, such as a user ID or wallet address. Your backend should enforce the same value. |
| `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. |
| `require_user_presence` | Request config and widgets | Optional liveness step. Defaults to `false`. |
<table>
<thead>
<tr>
<th className="p-2 text-left align-middle whitespace-nowrap">Parameter</th>
<th className="p-2 text-left align-middle">Where it is used</th>
<th className="p-2 text-left align-middle">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td className="p-2 align-middle whitespace-nowrap"><code>signal</code></td>
<td className="p-2 align-middle">Presets</td>
<td className="p-2 align-middle">Binds application context into the proof, such as a user ID or wallet address. Your backend should enforce the same value.</td>
</tr>
<tr>
<td className="p-2 align-middle whitespace-nowrap"><code>allow_legacy_proofs</code></td>
<td className="p-2 align-middle">Request config and widgets</td>
<td className="p-2 align-middle">Required for request flows. Set to <code>true</code> while accepting World ID 3.0 fallback proofs; set to <code>false</code> for World ID 4.0-only requests.</td>
</tr>
<tr>
<td className="p-2 align-middle whitespace-nowrap"><code>require_user_presence</code></td>
<td className="p-2 align-middle">Request config and widgets</td>
<td className="p-2 align-middle">Optional liveness step. Defaults to <code>false</code>.</td>
</tr>
</tbody>
</table>
58 changes: 29 additions & 29 deletions world-id/idkit/error-codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,149 +12,149 @@ This page focuses on IDKit SDK and bridge error codes returned during request fl
<table>
<thead>
<tr>
<th className="p-2 text-left align-middle">Code</th>
<th className="p-2 text-left align-middle whitespace-nowrap">Code</th>
<th className="p-2 text-left align-middle">Meaning</th>
<th className="p-2 text-left align-middle">Typical action</th>
</tr>
</thead>
<tbody>
<tr>
<td className="p-2 align-middle"><code>user_rejected</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>user_rejected</code></td>
<td className="p-2 align-middle">User cancelled in World App.</td>
<td className="p-2 align-middle">Treat as user cancellation, allow retry.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>verification_rejected</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>verification_rejected</code></td>
<td className="p-2 align-middle">Legacy rejection code (older bridge/app behavior).</td>
<td className="p-2 align-middle">Handle same as <code>user_rejected</code>.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>credential_unavailable</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>credential_unavailable</code></td>
<td className="p-2 align-middle">Requested credential type is not available for that user.</td>
<td className="p-2 align-middle">Offer fallback credential policy or explain requirement.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>world_id_4_not_available</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>world_id_4_not_available</code></td>
<td className="p-2 align-middle">World ID 4.0 credential is not available for that user.</td>
<td className="p-2 align-middle">Use a compatible fallback request or explain the World ID 4.0 requirement.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>world_id_3_not_available</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>world_id_3_not_available</code></td>
<td className="p-2 align-middle">World ID 3.0 credential is not available for that user.</td>
<td className="p-2 align-middle">Use a compatible fallback request or explain the World ID 3.0 requirement.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>malformed_request</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>malformed_request</code></td>
<td className="p-2 align-middle">Payload or configuration is invalid.</td>
<td className="p-2 align-middle">Check <code>app_id</code>, <code>rp_context</code>, and request shape.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>invalid_network</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>invalid_network</code></td>
<td className="p-2 align-middle">Environment mismatch between app config and World App context.</td>
<td className="p-2 align-middle">Align staging/production settings.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>inclusion_proof_pending</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>inclusion_proof_pending</code></td>
<td className="p-2 align-middle">Credential inclusion data is not ready yet.</td>
<td className="p-2 align-middle">Retry later.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>inclusion_proof_failed</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>inclusion_proof_failed</code></td>
<td className="p-2 align-middle">Inclusion proof retrieval failed.</td>
<td className="p-2 align-middle">Retry; if repeated, treat as operational incident.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>unexpected_response</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>unexpected_response</code></td>
<td className="p-2 align-middle">Malformed or unsupported bridge/app response.</td>
<td className="p-2 align-middle">Log diagnostics and retry once.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>connection_failed</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>connection_failed</code></td>
<td className="p-2 align-middle">Could not establish/maintain bridge communication.</td>
<td className="p-2 align-middle">Check connectivity and bridge reachability.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>max_verifications_reached</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>max_verifications_reached</code></td>
<td className="p-2 align-middle">Action already verified the maximum allowed number of times.</td>
<td className="p-2 align-middle">Treat as terminal business-rule outcome.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>failed_by_host_app</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>failed_by_host_app</code></td>
<td className="p-2 align-middle">Host app callback failed while processing a successful proof.</td>
<td className="p-2 align-middle">Fix host callback/backend logic and retry.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>invalid_rp_signature</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>invalid_rp_signature</code></td>
<td className="p-2 align-middle">RP signature could not be verified.</td>
<td className="p-2 align-middle">Check the RP signing key, nonce, timestamps, action, and signed message.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>nullifier_replayed</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>nullifier_replayed</code></td>
<td className="p-2 align-middle">Nullifier was already used for this action.</td>
<td className="p-2 align-middle">Treat as an already-verified outcome; do not retry the same action as a new verification.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>duplicate_nonce</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>duplicate_nonce</code></td>
<td className="p-2 align-middle">RP reused a signature nonce.</td>
<td className="p-2 align-middle">Generate a fresh nonce and signed RP context for each request.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>unknown_rp</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>unknown_rp</code></td>
<td className="p-2 align-middle">RP is not known to the registry.</td>
<td className="p-2 align-middle">Check the registered RP ID and app configuration.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>inactive_rp</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>inactive_rp</code></td>
<td className="p-2 align-middle">RP is registered but inactive.</td>
<td className="p-2 align-middle">Reactivate or reconfigure the RP before retrying.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>timestamp_too_old</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>timestamp_too_old</code></td>
<td className="p-2 align-middle">RP request timestamp is too old.</td>
<td className="p-2 align-middle">Generate a new signed RP context with a current timestamp.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>timestamp_too_far_in_future</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>timestamp_too_far_in_future</code></td>
<td className="p-2 align-middle">RP request timestamp is too far in the future.</td>
<td className="p-2 align-middle">Fix server clock skew and generate a new signed RP context.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>invalid_timestamp</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>invalid_timestamp</code></td>
<td className="p-2 align-middle">RP request timestamp is invalid.</td>
<td className="p-2 align-middle">Check timestamp format and regenerate the signed RP context.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>rp_signature_expired</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>rp_signature_expired</code></td>
<td className="p-2 align-middle">RP signature has expired.</td>
<td className="p-2 align-middle">Request a fresh RP signature before starting verification.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>user_presence_failed</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>user_presence_failed</code></td>
<td className="p-2 align-middle">Required user-presence check was not completed.</td>
<td className="p-2 align-middle">Let the user retry the request.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>identity_attributes_not_matched</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>identity_attributes_not_matched</code></td>
<td className="p-2 align-middle">User identity attributes did not match the requested constraints.</td>
<td className="p-2 align-middle">Show an eligibility fallback or adjust the requested attribute constraints.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>generic_error</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>generic_error</code></td>
<td className="p-2 align-middle">Catch-all unknown failure.</td>
<td className="p-2 align-middle">Log details and retry with backoff.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>invalid_rp_id_format</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>invalid_rp_id_format</code></td>
<td className="p-2 align-middle">RP ID is malformed.</td>
<td className="p-2 align-middle">Use the registered <code>rp_...</code> ID from your app configuration.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>timeout</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>timeout</code></td>
<td className="p-2 align-middle">Client-side polling timeout.</td>
<td className="p-2 align-middle">Extend timeout or let the user retry.</td>
</tr>
<tr>
<td className="p-2 align-middle"><code>cancelled</code></td>
<td className="p-2 align-middle whitespace-nowrap"><code>cancelled</code></td>
<td className="p-2 align-middle">Client-side cancellation (abort/task cancel/user close).</td>
<td className="p-2 align-middle">Treat as neutral cancellation path.</td>
</tr>
Expand Down
Loading