Skip to main content

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.
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
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.

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.
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.
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)

#OutcomeResult
01approvedKYC approved. If you requested RENAPER double-check, the response includes RENAPER success.
02approved_with_renaperSame as approved; RENAPER in the response only if requested in the creation.
03cancelledValidation cancelled.
04rejectedGeneric rejection.
05rejected_document_mismatchRejection due to document number not matching the entity.
06rejected_renaper_tramite_not_matchRejection: transaction number does not match registry.
07rejected_renaper_dni_not_matchRejection: document number does not match registry.
08rejected_renaper_verification_unavailableRejection: registry verification unavailable.
09rejected_renaper_dni_missingRejection: no document number available for registry check.
10rejectedGeneric 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 valueNormalizedOutcome
99.990.001 or 9999000199990001approved
99.990.002 or 9999000299990002approved_with_renaper
99.990.00399990003cancelled
99.990.00499990004rejected
99.990.00599990005rejected_document_mismatch
99.990.00699990006rejected_renaper_tramite_not_match
99.990.00799990007rejected_renaper_dni_not_match
99.990.00899990008rejected_renaper_verification_unavailable
99.990.00999990009rejected_renaper_dni_missing
99.990.01099990010rejected
99.990.01199990011approved (KYC); biometric mock defaults to rejected — see Embedded biometric mock

Argentina – CUIT (11 digits)

Format: 20-XXXXXXXX-X. Example: 20-99990001-9.
Example valueNormalizedOutcome
20-99990001-920999900019approved
20-99990002-920999900029approved_with_renaper
20-99990003-920999900039cancelled
20-99990004-920999900049rejected
20-99990005-920999900059rejected_document_mismatch
20-99990006-920999900069rejected_renaper_tramite_not_match
20-99990007-920999900079rejected_renaper_dni_not_match
20-99990008-920999900089rejected_renaper_verification_unavailable
20-99990009-920999900099rejected_renaper_dni_missing
20-99990010-920999900109rejected
20-99990011-920999900119approved (KYC); biometric mock defaults to rejected

Brazil – CPF (11 digits)

Format: XXX.XXX.XXX-XX. Example: 999.900.001-01.
Example valueNormalizedOutcome
999.900.001-0199990000101approved
999.900.001-0299990000102approved_with_renaper
999.900.001-0399990000103cancelled
999.900.001-0499990000104rejected
999.900.001-0599990000105rejected_document_mismatch
999.900.001-0699990000106rejected_renaper_tramite_not_match
999.900.001-0799990000107rejected_renaper_dni_not_match
999.900.001-0899990000108rejected_renaper_verification_unavailable
999.900.001-0999990000109rejected_renaper_dni_missing
999.900.001-1099990000110rejected

Brazil – CNPJ (14 digits)

Format: XX.XXX.XXX/XXXX-XX. Example: 99.990.000/0001-01.
Example valueNormalizedOutcome
99.990.000/0001-0199990000000101approved
99.990.000/0001-0299990000000102approved_with_renaper
99.990.000/0001-0399990000000103cancelled
99.990.000/0001-0499990000000104rejected
99.990.000/0001-0599990000000105rejected_document_mismatch
99.990.000/0001-0699990000000106rejected_renaper_tramite_not_match
99.990.000/0001-0799990000000107rejected_renaper_dni_not_match
99.990.000/0001-0899990000000108rejected_renaper_verification_unavailable
99.990.000/0001-0999990000000109rejected_renaper_dni_missing
99.990.000/0001-1099990000000110rejected

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):
{
  "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.

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.
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).

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 taxIdNormalizedKYC mockBiometric mock (default)
99990001 / 20-99990001-999990001 / 20999900019approvedapproved (immediate)
99990002 / 20-99990002-999990002 / 20999900029approved_with_renaperapproved (immediate)
99990011 / 20-99990011-999990011 / 20999900119approvedrejected (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:
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:
{
  "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.

Custom Mock Data

The default set above is available to all sandbox organizations with no configuration.
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.

See Also