Payday Public API
    • Proceso de Venta
    • Autenticacion y Firma HMAC
    • Proceso de Venta
      • Cotizacion - crear
        POST
      • Referencias - solicitar
        POST
      • Ofertas - previsualizar
        POST
      • Ofertas - seleccionar
        POST
      • Contrato - renderizar
        POST
      • Contrato - firma
        POST
      • Validar ICCID
        POST
      • Validar IMEI
        POST
      • Validar ICCID + IMEI
        POST
      • Finalizar venta
        POST
    • Productos
      • Marcas
        GET
      • Modelos y Prefijos por marca
        GET
    • Medios de Notificacion
      • Registrar Webhook para cotizacion
        POST
      • Polling Cotizacion
        GET
      • Historial de Eventos
        GET
    • Eventos Webhook
      • Evento quote.updated
      • reference.requested
      • reference.accepted
      • imei.validated
      • contract.signed
      • offer.selected
      • offer.previewed
    • Health check
      GET

    Proceso de Venta

    Public API - Proceso de Venta#

    Este documento describe el flujo completo de venta por medio de la Public API de Payday para integraciones externas. El objetivo es que un integrador pueda recorrer la venta de punta a punta, entender en que estado se encuentra cada cotizacion, saber cuando esperar un webhook o hacer polling, y resolver dudas operativas sin revisar el codigo fuente.

    1. Alcance del flujo#

    Este contrato publico cubre el flujo principal de venta:
    1.
    Crear cotizacion.
    2.
    Esperar validacion de identidad y buro.
    3.
    Solicitar referencias.
    4.
    Esperar validacion de referencias.
    5.
    Consultar catalogo y previsualizar ofertas.
    6.
    Seleccionar oferta.
    7.
    Renderizar contrato.
    8.
    Firmar contrato.
    9.
    Validar ICCID e IMEI.
    10.
    Finalizar venta con tag.
    Reglas base del contrato publico actual:
    1.
    El progreso de la cotizacion se interpreta principalmente por cotizacion.process.next_action.
    2.
    La API expone notificaciones por webhook y tambien permite polling.

    2. URL base y autenticacion#

    Base path del flujo:
    /public-api/v1/sales-process
    Todas las llamadas bajo este prefijo requieren:
    1.
    X-Api-Key
    2.
    X-Timestamp
    3.
    X-Nonce
    4.
    X-Signature
    Headers minimos:

    2.1 Canonical string para la firma#

    La firma HMAC se calcula sobre el canonical string:
    METHOD
    /public-api/v1/ruta/exacta?query=exacta
    TIMESTAMP
    NONCE
    SHA256_HEX_DEL_BODY_CRUDO
    Consideraciones importantes:
    1.
    La ruta firmada debe ser exactamente la misma que viaja en la request.
    2.
    Para POST, PATCH y cualquier request con body, la firma se calcula con el body crudo exacto.
    3.
    Si el cliente firma un JSON pretty pero envia otro serializado distinto, la API respondera INVALID_SIGNATURE.
    4.
    La forma mas segura de integrarse es enviar JSON minificado y firmar ese mismo string.
    5.
    El nonce no se puede reutilizar.

    3. Modelo de estado del proceso#

    La mayoria de las respuestas del flujo devuelven este nodo:
    {
      "process": {
        "state": "waiting",
        "next_action": "wait_identity_validation",
        "pause_reason": "identity_validation_pending",
        "can_continue": false,
        "checkpoints": {
          "referencias_validadas": false,
          "oferta_seleccionada": false,
          "contrato_firmado": false,
          "imei_validado": false
        }
      }
    }

    3.1 Significado de cada campo#

    1.
    state: estado general del flujo.
    2.
    next_action: accion siguiente esperada por el integrador.
    3.
    pause_reason: motivo por el que el flujo esta esperando o bloqueado.
    4.
    can_continue: indica si ya existe una accion disponible para continuar.
    5.
    checkpoints: avance por hitos del proceso.

    3.2 Valores esperados de state#

    stateSignificado
    waitingEl flujo depende de un proceso externo o de una confirmacion pendiente.
    action_requiredLa integracion ya puede invocar el siguiente endpoint.
    completedLa venta termino correctamente.
    blockedLa cotizacion ya no permite continuar.

    3.3 Valores mas importantes de next_action#

    next_actionSignificado operativo
    wait_identity_validationEl cliente debe completar verificacion de identidad y/o buro.
    wait_reference_validationYa se solicitaron referencias o aun no se cumple el minimo.
    select_offerYa se puede previsualizar y seleccionar una oferta.
    wait_contract_signatureLa oferta ya fue seleccionada y el contrato debe firmarse.
    wait_imei_validationEl contrato ya fue firmado y falta validar ICCID/IMEI.
    continueEl flujo ya puede pasar al siguiente endpoint operativo.
    completedLa venta fue finalizada.
    rejectedLa cotizacion quedo rechazada o bloqueada.

    4. Estrategias de seguimiento: webhook o polling#

    Despues de crear la cotizacion, Payday recomienda elegir una de estas dos estrategias para monitorear el proceso:
    1.
    Registrar un webhook en cuanto exista la cotizacion.
    2.
    Consultar periodicamente el resumen de la cotizacion por polling.

    4.1 Endpoint de polling principal#

    Este endpoint devuelve el resumen operativo de la cotizacion y es el que debe usar la integracion para saber si ya puede avanzar al siguiente paso.

    4.2 Endpoint de historial de eventos#

    Este endpoint devuelve el historial de eventos del flujo publico registrados sobre la cotizacion.

    4.3 Eventos disponibles por webhook#

    Actualmente los eventos mas utiles del flujo son:
    1.
    quote.created
    2.
    quote.updated
    3.
    reference.requested
    4.
    reference.accepted
    5.
    reference.rejected
    6.
    offer.previewed
    7.
    offer.selected
    8.
    contract.signed
    9.
    imei.validated

    5. Resumen del flujo end to end#

    PasoEndpoint principalResultado esperado
    1POST /cotizacionesSe crea la cotizacion y se entrega la URL de verificacion de identidad.
    2POST /cotizaciones/:id/notificaciones/webhooks o GET /cotizaciones/:idSe define si el seguimiento sera por webhook o polling.
    3Sin endpoint directo del integradorEl cliente final completa la validacion de identidad.
    4POST /cotizaciones/:id/referenciasSe solicita una referencia y el flujo espera confirmacion.
    5GET /catalogs/... y POST /cotizaciones/:id/ofertas/previsualizarSe obtienen catalogos y se generan ofertas disponibles.
    6POST /cotizaciones/:id/ofertas/seleccionarSe elige un plan y el flujo pasa a contrato.
    7POST /cotizaciones/:id/contrato/renderSe obtiene el PDF o base64 del contrato.
    8POST /cotizaciones/:id/contrato/firmaSe registra evidencia de firma.
    9POST /cotizaciones/:id/iccid-imei/validarSe validan linea y equipo para continuar.
    10POST /cotizaciones/:id/tag/finalizarSe completa la venta, dispositivo, financiamiento y recibo.

    6. Paso 1 - Crear cotizacion#

    Objetivo#

    Crear una nueva cotizacion en el flujo publico y obtener la URL de verificacion de identidad que debe abrir el cliente final.

    Endpoint#

    Regla principal#

    El body valido para crear una cotizacion es:
    {
      "terminos_buro": true
    }
    Notas importantes:
    1.
    terminos_buro es obligatorio.
    2.
    Debe ser booleano y debe venir en true.
    3.
    No se deben enviar campos extra; el schema es estricto.

    Ejemplo de request#

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}"
      },
      "identity_verification": {
        "url": "https://verificacion.paydaymx.com/verificacion/{{COTIZACION_ID}}?query={{JWT_DE_SESION}}&isMobile=false&api=true"
      }
    }

    Que hacer despues de este paso#

    1.
    Guardar cotizacion.id.
    2.
    Redirigir al cliente final a identity_verification.url.
    3.
    Registrar webhook o comenzar polling inmediatamente.

    7. Paso 2 - Registrar notificaciones o comenzar polling#

    Este paso define como seguira la integracion el proceso.

    Opcion A - Registrar webhook#

    Endpoint#

    Body esperado#

    {
      "url": "https://tu-sistema.com/webhooks/payday-sales-process",
      "events": [
        "quote.created",
        "quote.updated",
        "reference.requested",
        "reference.accepted",
        "reference.rejected",
        "offer.previewed",
        "offer.selected",
        "contract.signed",
        "imei.validated"
      ],
      "active": true
    }
    Notas:
    1.
    url es obligatoria.
    2.
    events es opcional; si no se envia, el backend puede registrar *.
    3.
    secret es opcional y puede omitirse o enviarse vacio.
    4.
    Si ya existe un webhook con la misma URL, el backend lo actualiza.

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "process": {
          "state": "waiting",
          "next_action": "wait_identity_validation",
          "pause_reason": "identity_validation_pending",
          "can_continue": false,
          "checkpoints": {
            "referencias_validadas": false,
            "oferta_seleccionada": false,
            "contrato_firmado": false,
            "imei_validado": false
          }
        }
      },
      "webhook": {
        "id": "{{WEBHOOK_ID}}",
        "url": "https://tu-sistema.com/webhooks/payday-sales-process",
        "events": [
          "quote.created",
          "quote.updated",
          "reference.requested",
          "reference.accepted",
          "reference.rejected",
          "offer.previewed",
          "offer.selected",
          "contract.signed",
          "imei.validated"
        ],
        "active": true,
        "created_at": "2026-05-05T23:29:31.958Z",
        "updated_at": "2026-05-05T23:29:31.958Z"
      }
    }

    Opcion B - Polling del resumen de la cotizacion#

    Endpoint#

    Ejemplo de respuesta inicial#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "status": "Iniciando Verificacion",
        "rating": null,
        "score": 0,
        "venta_con_inventario": false,
        "referencias": {
          "total": 0,
          "aceptadas": 0,
          "rechazadas": 0,
          "pendientes": 0,
          "minimo_cumplido": false
        },
        "producto": null,
        "pricing": null,
        "plan": null,
        "process": {
          "state": "waiting",
          "next_action": "wait_identity_validation",
          "pause_reason": "identity_validation_pending",
          "can_continue": false,
          "checkpoints": {
            "referencias_validadas": false,
            "oferta_seleccionada": false,
            "contrato_firmado": false,
            "imei_validado": false
          }
        },
        "notifications": {
          "webhooks_registrados": 1
        },
        "updated_at": "2026-05-05T23:29:31.959Z"
      }
    }

    8. Paso 3 - Validacion de identidad y buro#

    Este paso no se dispara con un endpoint adicional del integrador. La accion correcta es abrir la URL entregada en identity_verification.url y esperar a que el flujo interno de Payday complete la verificacion.

    Como saber si ya termino este paso#

    La integracion debe esperar a que ocurra una de estas condiciones:
    1.
    Llega un webhook de actualizacion del flujo.
    2.
    El polling deja de mostrar next_action = wait_identity_validation.
    3.
    La cotizacion avanza hacia referencias.

    Senal operativa esperada#

    Cuando ya se puede pasar a referencias, la cotizacion seguira mostrando state = waiting, pero next_action cambiara a:
    {
      "process": {
        "next_action": "wait_reference_validation"
      }
    }

    Que no debe hacer la integracion en este punto#

    1.
    No debe forzar stage ni step.
    2.
    No debe intentar asignar rating o score manualmente.
    3.
    No debe enviar referencias antes de que la cotizacion haya avanzado al tramo correcto.

    9. Paso 4 - Solicitar referencias#

    Objetivo#

    Enviar una solicitud de referencia para que un tercero confirme o rechace la referencia del cliente.

    Endpoint#

    Reglas de negocio#

    1.
    Solo puede usarse cuando la cotizacion esta en etapa referencias.
    2.
    Si el flujo no esta en esa etapa, la API responde 409.
    3.
    El minimo actual para continuar es al menos 1 referencia aceptada.
    4.
    El telefono se normaliza automaticamente con prefijo 52.
    5.
    No se puede repetir el mismo telefono dentro de la misma cotizacion.

    Body de ejemplo#

    {
      "telefono": "5568726342",
      "referencia": "Maria Lopez",
      "bodyVariables": ["Nombre del cliente"]
    }

    Ejemplo de request#

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "status": "Analisis crediticio cache completado",
        "rating": "A",
        "score": 24,
        "venta_con_inventario": false,
        "referencias": {
          "total": 1,
          "aceptadas": 0,
          "rechazadas": 0,
          "pendientes": 1,
          "minimo_cumplido": false
        },
        "producto": null,
        "pricing": null,
        "plan": null,
        "process": {
          "state": "waiting",
          "next_action": "wait_reference_validation",
          "pause_reason": "references_pending",
          "can_continue": false,
          "checkpoints": {
            "referencias_validadas": false,
            "oferta_seleccionada": false,
            "contrato_firmado": false,
            "imei_validado": false
          }
        },
        "notifications": {
          "webhooks_registrados": 1
        },
        "updated_at": "2026-05-05T23:48:21.326Z"
      },
      "referencia": {
        "id": "{{REFERENCIA_ID}}",
        "estado": "pendiente",
        "telefono": "********6342"
      }
    }

    Que sucede despues#

    1.
    El webhook puede recibir reference.requested.
    2.
    El polling mostrara next_action = wait_reference_validation.
    3.
    Cuando la referencia sea aceptada, el flujo avanzara a ofertas.

    Confirmacion publica de la referencia#

    La referencia normalmente confirma desde el link que Payday envia. El formato general es:
    Cuando la referencia acepta:
    1.
    Se emite reference.accepted.
    2.
    El resumen de la cotizacion cambiara para permitir ofertas.

    10. Paso 5 - Obtener catalogo y previsualizar ofertas#

    Antes de previsualizar ofertas se necesitan marcaId, modeloId y prefijoId.

    10.1 Listar marcas#

    10.2 Listar modelos y prefijos por marca#

    10.3 Esperar habilitacion para ofertas#

    La integracion debe esperar a que el resumen de la cotizacion indique:
    {
      "process": {
        "state": "action_required",
        "next_action": "select_offer",
        "pause_reason": null,
        "can_continue": true
      }
    }

    10.4 Previsualizar ofertas#

    Endpoint#

    Reglas de negocio#

    1.
    Solo puede usarse cuando la cotizacion esta en etapa ofertas.
    2.
    Si aun no existe rating, la API responde error de negocio.
    3.
    Se debe enviar precio y enganche.

    Body de ejemplo#

    {
      "marcaId": "{{MARCA_ID}}",
      "modeloId": "{{MODELO_ID}}",
      "prefijoId": "{{PREFIJO_ID}}",
      "precio": 2000,
      "enganche": 500
    }

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "rating": "A",
        "venta_con_inventario": false,
        "process": {
          "state": "action_required",
          "next_action": "select_offer",
          "pause_reason": null,
          "can_continue": true,
          "checkpoints": {
            "referencias_validadas": true,
            "oferta_seleccionada": false,
            "contrato_firmado": false,
            "imei_validado": false
          }
        }
      },
      "producto": {
        "marca_id": "{{MARCA_ID}}",
        "marca": "Samsung",
        "modelo_id": "{{MODELO_ID}}",
        "modelo": "Galaxy A06",
        "prefijo_id": "{{PREFIJO_ID}}",
        "prefijo": "SM-A065M",
        "producto_id": null,
        "precio": 2500,
        "color": null,
        "capacidad": 0,
        "ram": 0,
        "imagen": "https://imagenes-payday.s3.us-east-2.amazonaws.com/A06.jpg"
      },
      "pricing": {
        "precio": 2500,
        "enganche": 500,
        "enganche_minimo": 0,
        "enganche_mode": "manual",
        "porcentaje_enganche_aplicado": 0.08,
        "precio_maximo_por_rating": 7000,
        "price_boost": 2000,
        "fecha_calculo_precios": "2026-05-05T23:56:26.991Z"
      },
      "ofertas": [
        {
          "offer_id": "w13-m3-i1.1-f4200-e500",
          "semanas": 13,
          "meses": 3,
          "enganche": 500,
          "monto_a_financiar": 2000,
          "intereses_calculados": 2200,
          "precio_financiado": 4200,
          "abono_semanal": 323,
          "abono_semanal_ultimo": 324,
          "abono_mensual": 1400,
          "abono_mensual_ultimo": 1400,
          "total_a_pagar": 4700
        },
        {
          "offer_id": "w26-m6-i1.25-f4500-e500",
          "semanas": 26,
          "meses": 6,
          "enganche": 500,
          "monto_a_financiar": 2000,
          "intereses_calculados": 2500,
          "precio_financiado": 4500,
          "abono_semanal": 173,
          "abono_semanal_ultimo": 175,
          "abono_mensual": 750,
          "abono_mensual_ultimo": 750,
          "total_a_pagar": 5000
        },
        {
          "offer_id": "w39-m9-i1.5-f5000-e500",
          "semanas": 39,
          "meses": 9,
          "enganche": 500,
          "monto_a_financiar": 2000,
          "intereses_calculados": 3000,
          "precio_financiado": 5000,
          "abono_semanal": 128,
          "abono_semanal_ultimo": 136,
          "abono_mensual": 555,
          "abono_mensual_ultimo": 560,
          "total_a_pagar": 5500
        }
      ]
    }

    Que sucede despues#

    1.
    Se emite el evento offer.previewed.
    2.
    La integracion debe elegir uno de los offer_id devueltos.

    11. Paso 6 - Seleccionar oferta#

    Endpoint#

    Body esperado#

    {
      "offerId": "w39-m9-i1.5-f5000-e500"
    }

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "status": "Analisis crediticio cache completado",
        "process": {
          "state": "waiting",
          "next_action": "wait_contract_signature",
          "pause_reason": "contract_signature_pending",
          "can_continue": false,
          "checkpoints": {
            "referencias_validadas": true,
            "oferta_seleccionada": true,
            "contrato_firmado": false,
            "imei_validado": false
          }
        }
      },
      "producto": {
        "marca": "Samsung",
        "modelo": "Galaxy A06",
        "prefijo": "SM-A065M"
      },
      "plan": {
        "offer_id": "w39-m9-i1.5-f5000-e500",
        "semanas": 39,
        "meses": 9,
        "enganche": 500,
        "monto_a_financiar": 2000,
        "intereses_calculados": 3000,
        "precio_financiado": 5000,
        "abono_semanal": 128,
        "abono_semanal_ultimo": 136,
        "abono_mensual": 555,
        "abono_mensual_ultimo": 560,
        "total_a_pagar": 5500
      }
    }

    Que sucede despues#

    1.
    Se emite el evento offer.selected.
    2.
    La cotizacion avanza internamente a la etapa contrato.
    3.
    El siguiente paso operativo es renderizar y firmar el contrato.

    12. Paso 7 - Renderizar contrato#

    Objetivo#

    Obtener el contrato en PDF para mostrarlo al cliente antes de registrar la firma.

    Endpoint#

    Reglas de negocio#

    1.
    Solo puede usarse cuando la cotizacion esta en etapa contrato.
    2.
    template.name es el nombre del template de contrato; se recomienda enviarlo explicitamente y debe ser "Contrato Venta".
    3.
    response puede ser base64 o binary.
    4.
    Si se usa base64, la API devuelve un JSON con base64 y data_url.

    Body de ejemplo#

    {
      "template": {
        "name": "Contrato Venta"
      },
      "response": "base64"
    }

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "status": "Analisis crediticio cache completado",
        "rating": "A",
        "score": 24,
        "venta_con_inventario": false,
        "referencias": {
          "total": 1,
          "aceptadas": 1,
          "rechazadas": 0,
          "pendientes": 0,
          "minimo_cumplido": true
        },
        "producto": {
          "marca": "Samsung",
          "modelo": "Galaxy A06",
          "prefijo": "SM-A065M"
        },
        "pricing": {
          "precio": 2500,
          "enganche": 500,
          "porcentaje_enganche_aplicado": 0.08,
          "monto_a_financiar": 2000,
          "precio_financiado": 5000,
          "total_a_pagar": 5500
        },
        "plan": {
          "offer_id": "w39-m9-i1.5-f5000-e500",
          "semanas": 39,
          "meses": 9,
          "total_a_pagar": 5500
        },
        "process": {
          "state": "waiting",
          "next_action": "wait_contract_signature",
          "pause_reason": "contract_signature_pending",
          "can_continue": false,
          "checkpoints": {
            "referencias_validadas": true,
            "oferta_seleccionada": true,
            "contrato_firmado": false,
            "imei_validado": false
          }
        },
        "notifications": {
          "webhooks_registrados": 1
        },
        "updated_at": "2026-05-06T00:04:06.884Z"
      },
      "contrato": {
        "template_name": "Contrato Venta",
        "document": {
          "mime_type": "application/pdf",
          "file_name": "contrato-{{COTIZACION_ID}}.pdf",
          "base64": "JVBERi0xLjQK...",
          "data_url": "data:application/pdf;base64,JVBERi0xLjQK..."
        }
      }
    }

    13. Paso 8 - Firmar contrato#

    Objetivo#

    Registrar la evidencia minima de firma del contrato para que el flujo pueda pasar a validacion de ICCID/IMEI.

    Endpoint#

    Evidencia minima aceptada#

    La API exige estos elementos:
    1.
    contrato_base64
    2.
    contrato_texto
    3.
    firmado_en
    Notas:
    1.
    Se recomienda enviar source para identificar el origen de la firma.
    2.
    Solo puede usarse cuando la cotizacion esta en etapa contrato.

    Body de ejemplo#

    {
      "contrato_base64": "JVBERi0xLjQK...",
      "firmado_en": "2026-04-21T18:30:00.000Z",
      "contrato_texto": {
        "acepto_terminos": true
      },
      "source": "partner-web"
    }

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "status": "Analisis crediticio cache completado",
        "rating": "A",
        "score": 24,
        "venta_con_inventario": false,
        "referencias": {
          "total": 1,
          "aceptadas": 1,
          "rechazadas": 0,
          "pendientes": 0,
          "minimo_cumplido": true
        },
        "producto": {
          "marca": "Samsung",
          "modelo": "Galaxy A06",
          "prefijo": "SM-A065M"
        },
        "pricing": {
          "precio": 2500,
          "enganche": 500,
          "porcentaje_enganche_aplicado": 0.08,
          "monto_a_financiar": 2000,
          "precio_financiado": 5000,
          "total_a_pagar": 5500
        },
        "plan": {
          "offer_id": "w39-m9-i1.5-f5000-e500",
          "semanas": 39,
          "meses": 9,
          "total_a_pagar": 5500
        },
        "process": {
          "state": "waiting",
          "next_action": "wait_imei_validation",
          "pause_reason": "imei_validation_pending",
          "can_continue": false,
          "checkpoints": {
            "referencias_validadas": true,
            "oferta_seleccionada": true,
            "contrato_firmado": true,
            "imei_validado": false
          }
        },
        "notifications": {
          "webhooks_registrados": 1
        },
        "updated_at": "2026-05-06T00:19:13.885Z"
      },
      "contrato": {
        "firmado": true,
        "signed_at": "2026-04-21T18:30:00.000Z"
      }
    }

    Que sucede despues#

    1.
    Se emite contract.signed.
    2.
    El siguiente next_action sera wait_imei_validation.
    3.
    La integracion ya puede pasar al tramo de ICCID/IMEI.

    14. Paso 9 - Validar ICCID e IMEI#

    La forma mas practica de completar este tramo es usar la ruta combinada:

    Reglas de negocio#

    1.
    Solo puede usarse cuando la cotizacion esta en etapa imei.
    2.
    La validacion corre en secuencia: primero ICCID y despues IMEI.
    3.
    Si se envia xcel = false, la validacion del ICCID se maneja en modo manual.
    4.
    En modo manual, telefono_cliente es obligatorio.
    5.
    Para el IMEI, el modelo detectado debe coincidir con el prefijo esperado de la cotizacion.
    6.
    Si el equipo es Samsung, el backend tambien valida el estado de enrolamiento con Knox.
    7.
    Cuando la validacion termina correctamente, la cotizacion queda lista para continuar.

    Body de ejemplo con validacion manual de ICCID#

    {
      "iccid": "",
      "imei": "359706680322897",
      "telefono_cliente": "5512345678",
      "xcel": false
    }

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "status": "Analisis crediticio cache completado",
        "rating": "A",
        "score": 24,
        "venta_con_inventario": false,
        "referencias": {
          "total": 1,
          "aceptadas": 1,
          "rechazadas": 0,
          "pendientes": 0,
          "minimo_cumplido": true
        },
        "producto": {
          "marca": "Samsung",
          "modelo": "Galaxy A06",
          "prefijo": "SM-A065M"
        },
        "pricing": {
          "precio": 2500,
          "enganche": 500,
          "porcentaje_enganche_aplicado": 0.08,
          "monto_a_financiar": 2000,
          "precio_financiado": 5000,
          "total_a_pagar": 5500
        },
        "plan": {
          "offer_id": "w39-m9-i1.5-f5000-e500",
          "semanas": 39,
          "meses": 9,
          "total_a_pagar": 5500
        },
        "process": {
          "state": "action_required",
          "next_action": "continue",
          "pause_reason": null,
          "can_continue": true,
          "checkpoints": {
            "referencias_validadas": true,
            "oferta_seleccionada": true,
            "contrato_firmado": true,
            "imei_validado": true
          }
        },
        "notifications": {
          "webhooks_registrados": 1
        },
        "updated_at": "2026-05-06T00:24:56.905Z"
      },
      "sim": {
        "iccid": "",
        "provider": "manual",
        "valido": true,
        "status": "manual",
        "disponible": true,
        "numero": "525512345678",
        "numero_masked": "********5678",
        "validated_at": "2026-05-06T00:24:42.300Z"
      },
      "imei": {
        "imei": "359706680322897",
        "provider": "xcel",
        "status": null,
        "brand": "Samsung",
        "model": "SM-A065M",
        "expected_model": "SM-A065M",
        "msisdn": null,
        "phone_source": "manual",
        "is_samsung": true,
        "enrollment_status": "Locked",
        "validated_at": "2026-05-06T00:24:56.717Z",
        "valido": true,
        "numero": null,
        "numero_masked": null
      }
    }

    15. Paso 10 - Finalizar venta#

    Objetivo#

    Cerrar la venta publica usando el tag del dispositivo y la clave_acceso correspondiente.

    Endpoint#

    Reglas de negocio#

    1.
    tag es obligatorio.
    2.
    clave_acceso es obligatoria.
    3.
    La cotizacion debe haber completado referencias, oferta, contrato e IMEI.
    4.
    El backend puede finalizar desde etapas tag o configuracion, segun el flujo interno alcanzado.
    5.
    Si Knox o el render del recibo fallan, la venta puede quedar cerrada y esos errores se devuelven dentro de la respuesta.

    Body de ejemplo#

    {
      "tag": "65534223",
      "clave_acceso": "76069701"
    }

    Ejemplo de respuesta#

    {
      "cotizacion": {
        "id": "{{COTIZACION_ID}}",
        "status": "vendido",
        "rating": "A",
        "score": 24,
        "venta_con_inventario": false,
        "referencias": {
          "total": 1,
          "aceptadas": 1,
          "rechazadas": 0,
          "pendientes": 0,
          "minimo_cumplido": true
        },
        "producto": {
          "marca": "Samsung",
          "modelo": "Galaxy A06",
          "prefijo": "SM-A065M"
        },
        "pricing": {
          "precio": 2600,
          "enganche": 600,
          "porcentaje_enganche_aplicado": 0.08,
          "monto_a_financiar": 2000,
          "precio_financiado": 4860,
          "total_a_pagar": 5460
        },
        "plan": {
          "offer_id": null,
          "semanas": 26,
          "meses": 6,
          "total_a_pagar": 5460
        },
        "process": {
          "state": "completed",
          "next_action": "completed",
          "pause_reason": null,
          "can_continue": false,
          "checkpoints": {
            "referencias_validadas": true,
            "oferta_seleccionada": true,
            "contrato_firmado": true,
            "imei_validado": true
          }
        },
        "notifications": {
          "webhooks_registrados": 0
        },
        "updated_at": "2026-05-06T22:30:38.611Z",
        "stage": "vendido",
        "dispositivos": "{{DISPOSITIVO_ID}}",
        "financiamientos": "{{FINANCIAMIENTO_ID}}",
        "ventas": "{{VENTA_ID}}",
        "tag": "65534223"
      },
      "dispositivo": {
        "id": "{{DISPOSITIVO_ID}}",
        "tag": "65534223",
        "status": "disponible",
        "imei": "359706680322897",
        "cotizacion_id": "{{COTIZACION_ID}}",
        "financiamiento_id": "{{FINANCIAMIENTO_ID}}",
        "venta_id": "{{VENTA_ID}}"
      },
      "financiamiento": {
        "id": "{{FINANCIAMIENTO_ID}}",
        "fecha_bloqueo": "2026-05-13T10:30:33.000Z",
        "proceso_finalizado": true,
        "public_api": true,
        "proximo_pago": {
          "fecha": "2026-05-13T04:30:32.000Z",
          "monto": 186
        },
        "venta_id": "{{VENTA_ID}}"
      },
      "venta": {
        "id": "{{VENTA_ID}}",
        "fecha": "2026-05-06T16:30:33.000Z",
        "monto": 2600,
        "tipo_venta": "financiamiento",
        "estado": "completada"
      },
      "samsung": {
        "provider": "knox",
        "success": false,
        "unlock_pin": null,
        "offline_lock_pin": {
          "result": "SUCCESS",
          "objectId": "{{KNOX_OBJECT_ID}}",
          "requestedId": "359706680322897",
          "pinNumber": ["83414641"]
        },
        "error": {
          "message": {
            "code": 4000310,
            "message": "DEVICE_STATE_INVALID",
            "reason": "Current status is 'Unlocking'."
          },
          "status": 400,
          "data": {
            "result": "FAIL",
            "error": {
              "code": 4000310,
              "message": "DEVICE_STATE_INVALID",
              "reason": "Current status is 'Unlocking'."
            }
          }
        }
      },
      "recibo": {
        "template_name": "Recibo Venta",
        "document": {
          "mime_type": "application/pdf",
          "file_name": "recibo-venta-{{VENTA_ID}}.pdf",
          "base64": "JVBERi0xLjQK...",
          "data_url": "data:application/pdf;base64,JVBERi0xLjQK..."
        }
      }
    }

    Resultado esperado#

    1.
    cotizacion.process.state queda en completed.
    2.
    cotizacion.process.next_action queda en completed.

    16. Errores y respuestas esperadas#

    16.1 409 Conflict#

    La API devuelve 409 cuando se intenta usar un endpoint en una etapa incorrecta del flujo. Ejemplos comunes:
    1.
    Enviar referencias antes de terminar identidad.
    2.
    Previsualizar ofertas cuando aun no hay referencias aceptadas.
    3.
    Firmar contrato antes de seleccionar oferta.
    4.
    Finalizar venta antes de validar IMEI.
    Mensaje esperado:
    No se puede acceder a esta accion en la etapa actual de la cotizacion

    16.2 422 Unprocessable Entity#

    La API devuelve 422 cuando el body es valido en forma, pero incumple reglas de negocio. Ejemplos:
    1.
    Crear cotizacion sin terminos_buro = true.
    2.
    Intentar generar ofertas sin rating.
    3.
    Enviar telefono_cliente faltante cuando xcel = false en ICCID.
    4.
    Intentar validar un IMEI cuyo modelo no coincide con el prefijo seleccionado.

    16.3 404 Not Found#

    Puede ocurrir cuando:
    1.
    La cotizacion no pertenece a la empresa de la API key.
    2.
    El prefijoId, marcaId o modeloId no existen o no estan relacionados.

    16.4 401 o 403#

    Puede ocurrir cuando:
    1.
    La API key no existe o esta deshabilitada.
    2.
    La firma HMAC es invalida.
    3.
    La key no tiene permisos sales-process:read o sales-process:write.
    4.
    La empresa resuelta por la key no es valida.

    18. Recomendaciones de integracion#

    1.
    Crear la cotizacion y registrar el webhook en el mismo flujo transaccional del integrador.
    2.
    Guardar siempre cotizacion.id, offer_id, tag y venta.id en el sistema externo.
    3.
    Usar next_action como fuente principal de control del flujo en vez de inferir el avance por status.
    4.
    No intentar saltar pasos.
    5.
    Si la integracion usa polling, consultar el resumen de cotizacion y no solo el historial de eventos.
    6.
    Para POST y PATCH, firmar el body crudo exacto que se envia.
    7.
    Tratar samsung.error y recibo.error como informacion operativa adicional; no necesariamente significan que la venta no se cerro.

    19. Checklist operativo rapido#

    1.
    Crear cotizacion.
    2.
    Guardar cotizacion.id.
    3.
    Registrar webhook o iniciar polling.
    4.
    Redirigir al cliente a identity_verification.url.
    5.
    Esperar wait_reference_validation.
    6.
    Solicitar referencia.
    7.
    Esperar reference.accepted o next_action = select_offer.
    8.
    Consultar catalogos.
    9.
    Previsualizar ofertas.
    10.
    Seleccionar oferta.
    11.
    Renderizar contrato.
    12.
    Registrar firma.
    13.
    Validar ICCID/IMEI.
    14.
    Confirmar next_action = continue.
    15.
    Finalizar con tag y clave_acceso.
    16.
    Verificar process.state = completed.
    Modificado en 2026-05-07 00:17:35
    Siguiente
    Autenticacion y Firma HMAC
    Built with