> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gu1.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox mock data

> Test document numbers and expected outcomes for KYC in sandbox — in the gu1 KYC API for identity verification flows, with examples for sandbox mock data use.

## Overview

In **sandbox**, when you create a KYC validation for a **person entity**, the API can return an **immediate mock result** based on the entity's **taxId** (document number). No external verification is performed; the response and webhooks match the outcome associated with that document in our test set.

This lets you test all flows (approved, rejected, cancelled, RENAPER double-check, etc.) without going through a real verification.

<Warning>
  **Configure a webhook to receive responses!**

  In sandbox, KYC results are updated **asynchronously** (same as production). While the API returns 201 immediately after creating the validation, the final result (approved, rejected, etc.) is sent via **webhooks** moments later.

  **You must configure a webhook endpoint in your organization** to receive validation notifications. Without a configured webhook, you won't receive status updates.

  📚 **Learn to set up webhooks:** [Webhook integration](/en/use-cases/kyc/webhook-integration)
</Warning>

<Info>
  **Format does not matter.** The entity's `taxId` can be sent with or without formatting (e.g. `99.990.001` or `99990001`). The API normalizes it before matching, so both work the same.
</Info>

## How It Works

1. The person entity belongs to an organization that is in **sandbox** mode.
2. You call **POST /api/kyc/validations** with that entity's `entityId`.
3. The API looks up the entity's **taxId** in the sandbox test map (after normalizing: digits and letters only).
4. If there is a match, a **mock validation** is created with `pending` status (201 Created) and moments later it's updated to the **final status** (e.g. `approved`, `rejected`, `cancelled`).
5. **Webhooks are sent** to your configured endpoint with the final result.
6. If there is no match, the API follows the normal flow (creates a real verification session and returns `providerSessionUrl`).

**Asynchronous flow:** The sandbox behavior **exactly replicates the production flow**, which is asynchronous. The validation is created in `pending` state, then updated and notified via webhook. **Do not attempt immediate polling** to the GET endpoint after creating the validation - use webhooks to receive the result.

## Synthetic Entity Preview (GET Only)

In **sandbox**, when you look up a **catalog test document number** and **no real entity row exists**, Gu1 can return a **synthetic person** instead of `404`:

* `GET /api/entities/by-tax-id/{taxId}`
* `GET /api/entities?taxId={taxId}` (exact filter, zero real matches)

Response includes `sandboxMock: true`, `id: null`, and `metadata.sandboxKycOutcome` (expected KYC mock outcome for that number). **Nothing is written to the database.**

<Warning>
  The synthetic preview is for **discovery and documentation**. To run `POST /api/kyc/validations` or `POST /api/kyc/biometric/sessions` with `entityTaxId`, you must **create a real person entity** first (same test `taxId`). KYC/biometric endpoints resolve against persisted rows only.
</Warning>

**RENAPER in sandbox:** If you send `doubleCheckRenaper: true` when creating the validation and the outcome is approved (or a RENAPER-related rejection), the response and webhook payload will include `metadata.responseDoubleChecks.renaper` with the same structure as in production.

## Default Test Values

We provide a fixed set of test document numbers in four formats. Each number maps to one **outcome**. The lookup key is the **normalized** value (no dots, dashes, or spaces).

### Outcome List (What Each Number Returns)

| #  | Outcome                                     | Result                                                                                      |
| -- | ------------------------------------------- | ------------------------------------------------------------------------------------------- |
| 01 | `approved`                                  | KYC approved. If you requested RENAPER double-check, the response includes RENAPER success. |
| 02 | `approved_with_renaper`                     | Same as approved; RENAPER in the response only if requested in the creation.                |
| 03 | `cancelled`                                 | Validation cancelled.                                                                       |
| 04 | `rejected`                                  | Generic rejection.                                                                          |
| 05 | `rejected_document_mismatch`                | Rejection due to document number not matching the entity.                                   |
| 06 | `rejected_renaper_tramite_not_match`        | Rejection: transaction number does not match registry.                                      |
| 07 | `rejected_renaper_dni_not_match`            | Rejection: document number does not match registry.                                         |
| 08 | `rejected_renaper_verification_unavailable` | Rejection: registry verification unavailable.                                               |
| 09 | `rejected_renaper_dni_missing`              | Rejection: no document number available for registry check.                                 |
| 10 | `rejected`                                  | Generic rejection (second number for testing).                                              |

### Argentina – DNI (8 digits)

Use any of these as the entity’s `taxId` (with or without dots). Normalized value is used for matching.

| Example value          | Normalized | Outcome                                                                                                                   |
| ---------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------- |
| 99.990.001 or 99990001 | 99990001   | approved                                                                                                                  |
| 99.990.002 or 99990002 | 99990002   | approved\_with\_renaper                                                                                                   |
| 99.990.003             | 99990003   | cancelled                                                                                                                 |
| 99.990.004             | 99990004   | rejected                                                                                                                  |
| 99.990.005             | 99990005   | rejected\_document\_mismatch                                                                                              |
| 99.990.006             | 99990006   | rejected\_renaper\_tramite\_not\_match                                                                                    |
| 99.990.007             | 99990007   | rejected\_renaper\_dni\_not\_match                                                                                        |
| 99.990.008             | 99990008   | rejected\_renaper\_verification\_unavailable                                                                              |
| 99.990.009             | 99990009   | rejected\_renaper\_dni\_missing                                                                                           |
| 99.990.010             | 99990010   | rejected                                                                                                                  |
| 99.990.011             | 99990011   | approved (KYC); biometric mock defaults to **rejected** — see [Embedded biometric mock](#embedded-biometric-sandbox-mock) |

### Argentina – CUIT (11 digits)

Format: `20-XXXXXXXX-X`. Example: `20-99990001-9`.

| Example value | Normalized  | Outcome                                                 |
| ------------- | ----------- | ------------------------------------------------------- |
| 20-99990001-9 | 20999900019 | approved                                                |
| 20-99990002-9 | 20999900029 | approved\_with\_renaper                                 |
| 20-99990003-9 | 20999900039 | cancelled                                               |
| 20-99990004-9 | 20999900049 | rejected                                                |
| 20-99990005-9 | 20999900059 | rejected\_document\_mismatch                            |
| 20-99990006-9 | 20999900069 | rejected\_renaper\_tramite\_not\_match                  |
| 20-99990007-9 | 20999900079 | rejected\_renaper\_dni\_not\_match                      |
| 20-99990008-9 | 20999900089 | rejected\_renaper\_verification\_unavailable            |
| 20-99990009-9 | 20999900099 | rejected\_renaper\_dni\_missing                         |
| 20-99990010-9 | 20999900109 | rejected                                                |
| 20-99990011-9 | 20999900119 | approved (KYC); biometric mock defaults to **rejected** |

### Brazil – CPF (11 digits)

Format: `XXX.XXX.XXX-XX`. Example: `999.900.001-01`.

| Example value  | Normalized  | Outcome                                      |
| -------------- | ----------- | -------------------------------------------- |
| 999.900.001-01 | 99990000101 | approved                                     |
| 999.900.001-02 | 99990000102 | approved\_with\_renaper                      |
| 999.900.001-03 | 99990000103 | cancelled                                    |
| 999.900.001-04 | 99990000104 | rejected                                     |
| 999.900.001-05 | 99990000105 | rejected\_document\_mismatch                 |
| 999.900.001-06 | 99990000106 | rejected\_renaper\_tramite\_not\_match       |
| 999.900.001-07 | 99990000107 | rejected\_renaper\_dni\_not\_match           |
| 999.900.001-08 | 99990000108 | rejected\_renaper\_verification\_unavailable |
| 999.900.001-09 | 99990000109 | rejected\_renaper\_dni\_missing              |
| 999.900.001-10 | 99990000110 | rejected                                     |

### Brazil – CNPJ (14 digits)

Format: `XX.XXX.XXX/XXXX-XX`. Example: `99.990.000/0001-01`.

| Example value      | Normalized     | Outcome                                      |
| ------------------ | -------------- | -------------------------------------------- |
| 99.990.000/0001-01 | 99990000000101 | approved                                     |
| 99.990.000/0001-02 | 99990000000102 | approved\_with\_renaper                      |
| 99.990.000/0001-03 | 99990000000103 | cancelled                                    |
| 99.990.000/0001-04 | 99990000000104 | rejected                                     |
| 99.990.000/0001-05 | 99990000000105 | rejected\_document\_mismatch                 |
| 99.990.000/0001-06 | 99990000000106 | rejected\_renaper\_tramite\_not\_match       |
| 99.990.000/0001-07 | 99990000000107 | rejected\_renaper\_dni\_not\_match           |
| 99.990.000/0001-08 | 99990000000108 | rejected\_renaper\_verification\_unavailable |
| 99.990.000/0001-09 | 99990000000109 | rejected\_renaper\_dni\_missing              |
| 99.990.000/0001-10 | 99990000000110 | rejected                                     |

## Example: Approved with RENAPER

1. Create a **person** entity in sandbox with `taxId`: `99990001` (or `99.990.001`).
2. Call **POST /api/kyc/validations** with `entityId` and `doubleCheckRenaper: true` (body or query).
3. The API returns **201** with the validation; shortly after, the status is **approved** and the webhook `kyc.validation_approved` is sent.
4. The webhook payload includes the full validation object, including **`metadata.responseDoubleChecks.renaper`** with `verified: true`, `matchResult: "match"`, `personalNumber`, `idTramitePrincipal`, and `renaperData` (mock registry response).

## Example Response (Mock Approved)

The response body and webhook payload follow the same structure as a real validation. Example shape for an approved mock (relevant fields):

```json theme={null}
{
  "id": "uuid",
  "entityId": "uuid",
  "status": "approved",
  "verifiedAt": "2026-02-21T12:00:00.000Z",
  "extractedData": {
    "firstName": "Sandbox",
    "lastName": "User",
    "fullName": "Sandbox User",
    "dateOfBirth": "1990-01-15",
    "documentNumber": "99990001",
    "documentType": "Identity Card",
    "nationality": "AR",
    "gender": "M",
    "ejemplar": "A",
    "age": 34
  },
  "verifiedFields": ["identity_document", "liveness_check", "face_match"],
  "warnings": [],
  "metadata": {
    "doubleChecks": { "renaper": true },
    "responseDoubleChecks": {
      "renaper": {
        "verified": true,
        "matchResult": "match",
        "personalNumber": "99990001",
        "idTramitePrincipal": "987654321",
        "verifiedAt": "2026-02-21T12:00:00.000Z",
        "comparisonResults": {
          "dni": { "field": "dni", "compared": true, "passed": true, "ocrValue": "99990001", "renaperValue": "99990001" },
          "tramite": { "field": "tramite", "compared": true, "passed": true, "ocrValue": "99990001", "renaperValue": "987654321" },
          "ejemplar": { "field": "ejemplar", "compared": true, "passed": true, "ocrValue": "A", "renaperValue": "A" }
        },
        "renaperData": {
          "id_tramite_principal": "987654321",
          "id_tramite_tarjeta_reimpresa": "112233445",
          "ejemplar": "A",
          "vencimiento": "2030-05-20",
          "emision": "2015-05-20",
          "apellido": "User",
          "nombres": "Sandbox",
          "fecha_nacimiento": "1990-01-15",
          "cuil": "20-99990001-9",
          "calle": "Av. Corrientes",
          "numero": "1234",
          "piso": "5",
          "departamento": "B",
          "codigo_postal": "1043",
          "barrio": "San Nicolás",
          "monoblock": "",
          "ciudad": "Ciudad Autónoma de Buenos Aires",
          "municipio": "Comuna 1",
          "provincia": "Buenos Aires",
          "pais": "Argentina",
          "nacionalidad": "Argentina",
          "codigo_fallecido": "",
          "mensaje_fallecido": "",
          "fecha_fallecimiento": "",
          "id_ciudadano": "99990001",
          "codigo": "",
          "mensaje": ""
        }
      }
    }
  }
}
```

When RENAPER double-check is not requested, `metadata.responseDoubleChecks` is not present for approved; when it is requested, it is present as above. For `renaperData` on rejections or service errors, see [`renaperData` shape](/en/use-cases/kyc/create-validation#renaperdata-shape).

## Embedded Biometric (Sandbox Mock)

After an **approved** KYC mock for the same entity, you can create an **embedded biometric session** (`POST /api/kyc/biometric/sessions`) that also runs in **mock mode** in sandbox—no hosted capture UI; Gu1 returns the result immediately.

<Info>
  Mock biometric uses the **same sandbox organization** and **same test `taxId` map** as KYC mock. Validations created via mock include `metadata.sandboxMock: true`. Biometric sessions created via mock include `metadata.sandboxMock: true` and `metadata.sandboxMockOutcome` (`approved` or `rejected`).
</Info>

### Prerequisites

1. Organization in **sandbox** mode (same as KYC mock).
2. Person entity with a **test `taxId`** whose KYC outcome is **`approved`** or **`approved_with_renaper`** (e.g. `99990001`, `99990002`, `99990011`).
3. **Approved KYC** for that entity (create via `POST /api/kyc/validations` first).

### Default Biometric Outcomes by Test Document

| Example `taxId`          | Normalized             | KYC mock                | Biometric mock (default) |
| ------------------------ | ---------------------- | ----------------------- | ------------------------ |
| 99990001 / 20-99990001-9 | 99990001 / 20999900019 | approved                | **approved** (immediate) |
| 99990002 / 20-99990002-9 | 99990002 / 20999900029 | approved\_with\_renaper | **approved** (immediate) |
| 99990011 / 20-99990011-9 | 99990011 / 20999900119 | approved                | **rejected** (immediate) |

For documents whose KYC mock is `rejected` or `cancelled`, you cannot create a biometric session (`NO_KYC`).

### Override Outcome on the Same Entity

On any eligible mock entity, send `metadata.sandboxMockOutcome` in the create body:

```json theme={null}
POST /api/kyc/biometric/sessions
{
  "entityId": "uuid",
  "metadata": {
    "sandboxMockOutcome": "rejected"
  }
}
```

Allowed values: `approved`, `rejected`. This only applies when the request qualifies for sandbox mock (sandbox org + approved KYC mock, or `metadata.sandboxMock: true` on the source KYC).

### Example: Mock Approved

1. Create person entity with `taxId`: `99990001`.
2. `POST /api/kyc/validations` → wait for webhook `kyc.validation_approved` (or poll GET until `approved`).
3. `POST /api/kyc/biometric/sessions` with `{ "entityId": "..." }`.

Response `201`:

```json theme={null}
{
  "id": "uuid",
  "entityId": "uuid",
  "status": "approved",
  "sessionUrl": "https://kyc-v2-onboarding.gueno.io/session/sandbox-mock-bio-...",
  "hostedSessionId": "sandbox-mock-bio-...",
  "mode": "face_match",
  "iframeAllow": "camera; microphone; fullscreen; autoplay; encrypted-media"
}
```

Webhooks: `biometric.session_approved` (org webhook and optional per-request `webhookUrl`). No iframe step is required for mock sessions.

### Example: Mock Rejected

**Option A** — dedicated test document `99990011` (KYC approved, biometric rejected by default).

**Option B** — same entity as `99990001` with `"metadata": { "sandboxMockOutcome": "rejected" }`.

Response `status` is `rejected`; webhook event is `biometric.session_rejected`.

### Real (Non-Mock) Biometric in Sandbox

If the entity `taxId` is **not** in the test map, or the organization is not sandbox, `POST /api/kyc/biometric/sessions` follows the **production path**: hosted capture UI, `status: pending`, and a Gu1-assigned `hostedSessionId`. Requires a valid reference portrait from approved KYC.

### Retries and Active Sessions

* If the latest biometric session for the entity is still `pending` or `in_progress`, create returns **`409 ACTIVE_SESSION_EXISTS`** with `activeSessionId`. Cancel it with `POST /api/kyc/biometric/sessions/:id/cancel` before creating another.
* If a previous create succeeded but your client retried, Gu1 reuses the existing row when the same `hostedSessionId` is returned (idempotent create).

See also: [Embedded Biometric Session](/en/use-cases/kyc/embedded-biometric).

## Custom Mock Data

The default set above is available to all sandbox organizations with no configuration.

<Warning>
  **Adding or changing mock document numbers for your sandbox:**\
  If you need additional test documents or different outcomes for specific numbers, contact the **Gu1 team**. Custom mock data for sandbox is managed by Gu1 and cannot be configured by the client.
</Warning>

## See Also

* [Create KYC Validation](/en/use-cases/kyc/create-validation) – How to call the API
* [Embedded Biometric Session](/en/use-cases/kyc/embedded-biometric) – Hosted re-authentication after KYC
* [Webhook Integration](/en/use-cases/kyc/webhook-integration) – Receive validation events in real time
