Todo en el sandbox es determinista: el resultado lo decide el documento que envías, algunos montos y los ids que te devuelve el propio sandbox. Esta página reúne esos valores para que escribas pruebas automáticas que cubran el camino feliz y cada error documentado. Recuerda que el sandbox no guarda estado: el estado viaja en los ids y una escritura no cambia lo que devuelven las lecturas siguientes (Sandbox).

Afiliados, créditos y subsidios #

Cinco documentos (tipo CC) con un perfil fijo. El perfil decide el resultado de cada paso, sin importar lo que envíes en la decisión.

DocumentoPerfilConsulta de afiliado¹Al radicarAl decidirAl desembolsar
1000000001ElegibleNo simulada201 RECEIVEDAPPROVED200 DISBURSED
1000000002InelegibleNo simulada201 REJECTED (NOT_ELIGIBLE)REJECTED (NOT_ELIGIBLE)409 (no desembolsable)
1000000003Revisión manualNo simulada201 RECEIVEDIN_REVIEW (MANUAL_REVIEW)409
1000000004Con deudasNo simulada201 REJECTED (OUTSTANDING_DEBT)REJECTED (OUTSTANDING_DEBT)409
9999999999No existeNo simulada404——
Cualquier otroElegible—Como 1000000001Como 1000000001Como 1000000001

¹ La consulta, el cruce y la carga de afiliados (affiliates.get, cross, upload) no se simulan: con cualquier llave leen y escriben el registro de afiliados real del tenant. Para probar la consulta, carga antes tus afiliados de prueba con affiliates.cross; un documento que no esté en tu registro responde 404.

Umbral de monto: 50.000.000. Una solicitud del perfil elegible por más de 50.000.000 queda REJECTED con AMOUNT_EXCEEDS_LIMIT desde la radicación, y sigue rechazada (y no desembolsable) en la decisión, la consulta y el desembolso. Úsalo para tu caso de “monto demasiado alto”.

Cómo leer los ids:

  • La solicitud recibe un id sbx-<código>-<hash>. El código es la letra del perfil (E elegible, I inelegible, M revisión manual, D con deudas) más una X si superó el umbral (sbx-EX-…).
  • El mismo tenant y la misma external_reference producen siempre el mismo id (sin external_reference, cuenta el documento).
  • La consulta de una solicitud (GET) responde el estado decidido (APPROVED, REJECTED, IN_REVIEW), aunque la radicación haya respondido RECEIVED.
  • El desembolso de una solicitud aprobada devuelve un disbursement_id dsb-….
  • Las bandejas de créditos y de subsidios listan 4 solicitudes, una por cada documento de 1000000001 a 1000000004 (el inexistente no aparece), y aplican los filtros status, search (documento o nombre) y la paginación.

Los subsidios siguen exactamente las mismas reglas, para cualquier tipo de subsidio de la ruta.

Un test por perfil #

Radicar con cada documento de prueba
import os
from compense_gateway import CompenseClient, NotFoundError

client = CompenseClient(api_key=os.environ["COMPENSE_API_KEY"], environment="sandbox")

ESPERADO = {"1000000001": "RECEIVED", "1000000002": "REJECTED",
            "1000000003": "RECEIVED", "1000000004": "REJECTED"}

for doc, estado in ESPERADO.items():
    tx = client.credits.submit_application(
        affiliate={"document_type": "CC", "document_number": doc},
        product_code="LIBRANZA_12M", amount="3500000", term_months=12,
        external_reference=f"HORIZONTE-TEST-{doc}",
    )
    assert tx.data["status"] == estado, (doc, tx.data)

try:
    client.affiliates.get("9999999999")
except NotFoundError:
    print("9999999999 no existe, como se esperaba")

Cuota monetaria #

DocumentoAl generarAl pagar la cuota generada
1000000001 (o cualquier otro)201 GENERATED, eligible: true, monto 50.000200 DISBURSED
1000000003201 GENERATED, eligible: true, monto 50.000409 (el perfil queda en revisión)
1000000002201 NOT_ELIGIBLE (NOT_ELIGIBLE), monto 0409
1000000004201 NOT_ELIGIBLE (OUTSTANDING_DEBT), monto 0409
9999999999404—
  • La cuota recibe un disbursement_id mad-<código>-<hash>; el mismo afiliado y período dan el mismo id.
  • Sin period, se usa el mes en curso (AAAA-MM).
  • El listado devuelve una sola fila GENERATED de 50.000 para el período.

Billetera #

Saldo, P2P, Bre-B, facturas y recargas #

Moneda: COP. El saldo disponible depende del perfil del titular (el document de la petición):

Documento del titularSaldoComportamiento
1000000001500.000Todo funciona.
1000000003500.000Todo funciona.
10000000020422 INSUFFICIENT_FUNDS en cualquier envío.
1000000004100422 INSUFFICIENT_FUNDS en casi cualquier envío.
9999999999—404 MEMBER_NOT_FOUND.
Cualquier otro500.000Como 1000000001.
CasoValor de pruebaResultado
Resolver alias P2P o llave Bre-B inexistente9999999999200 con {"found": false}
P2P a uno mismoalias igual al document del pagador422 SELF_TRANSFER
Enviar sin resolver antessin resolution_token400 RESOLUTION_REQUIRED
Token de otro flujotoken de Bre-B en P2P o al revés400 RESOLUTION_INVALID
Rechazo del banco destino (Bre-B)monto 11111422 TRANSFER_REJECTED (reason_code AC04)
Monto cero o negativo0422 INVALID_AMOUNT
Factura ya pagadareferencia que termina en 0409 BILL_ALREADY_PAID
Convenio desconocidootro biller_code404 BILLER_NOT_FOUND
Pagar un monto distinto al consultadocualquier otro monto422 AMOUNT_MISMATCH
Celular inválidoque no tenga 10 dígitos o no empiece por 3400 INVALID_PHONE
Operador desconocidofuera de la lista404 OPERATOR_NOT_FOUND
Recarga fuera de rangomenos de 1.000 o más de 200.000400 INVALID_AMOUNT
  • Convenios simulados: EPM (energía), ACUEDUCTO (agua), VANTI (gas) y ETB (internet). El valor de cada factura está entre 50.000 y 95.000 según la referencia, vence el 2026-11-15 y es del período 2026-10: consúltala antes de pagarla para conocer el monto exacto.
  • Operadores de recarga: CLARO, MOVISTAR, TIGO y WOM, de 1.000 a 200.000.
  • Movimientos: 3 fijos por titular (1, 5 y 10 de octubre de 2026: un abono de subsidio de 150.000, una transferencia de 20.000 y una recarga de 10.000), paginables y filtrables por fecha; su id sirve para consultar el detalle de la transacción.
  • Los ids de transacción son wtx-… y se repiten con la misma petición.

Bolsillos, tarjetas y FX #

CasoResultado
Listar cuentasUna billetera principal (con el saldo del perfil) y un bolsillo en 0.
Moneda por defectoDOP si no envías currency.
Emitir tarjeta a 1000000002422 NOT_ELIGIBLE.
Cambiar estado de tarjetaACTIVE, FROZEN o BLOCKED; otro valor → 422 INVALID_STATUS.
Movimientos de una tarjetaUna compra (PURCHASE) de 1.000, SETTLED.
Cotizar o convertir FXTasas fijas: DOP→USD 0,017 · USD→DOP 58,5 · DOP→COP 68,0 · COP→DOP 0,0147. Otro par → 422 UNSUPPORTED_CURRENCY_PAIR.
Convertir más que el saldo422 INSUFFICIENT_FUNDS.

Cartera #

DocumentoPréstamo simulado
10000000011 préstamo ACTIVE, al día (cuotas 1 a 3 pagadas).
10000000031 préstamo IN_ARREARS: cuota 4 en mora de 12 días.
10000000041 préstamo DEFAULTED: cuotas 3 a 5 en mora (95 días).
1000000002Sin préstamos (lista vacía).
9999999999404 (el afiliado no existe).
  • Todos los préstamos de prueba son de 5.000.000 a 12 cuotas, tasa del 1,8 % mensual, con la primera cuota el 15 de julio de 2026 (fechas fijas).
  • El loan_id (lna-…) sale de listar los préstamos del documento.
  • Los recaudos validan como el motor: channel en CASH, ACH_LIBRANZA, BANK_FILE o MANUAL (también acepta alias como EFECTIVO, LIBRANZA, TRANSFERENCIA o CHEQUE; otro valor → 422 INVALID_CHANNEL), reference obligatoria (422 REFERENCE_REQUIRED), monto positivo (422 INVALID_AMOUNT) y no mayor que la deuda (422 AMOUNT_EXCEEDS_DEBT), monto del pago total igual a la cotización (422 PAYOFF_AMOUNT_MISMATCH) y mode del abono en reduce_term o reduce_installment (422 INVALID_MODE).
  • La misma reference devuelve el mismo receipt_id, y replayed siempre es false. Registrar un pago no cambia lo que devuelven las lecturas.

Salud #

CasoValor de pruebaResultado
ProfesionalesD1 (medicina general, Sede Sandbox Centro) y D2 (pediatría, Sede Sandbox Norte)En el catálogo y la disponibilidad
Cuposslt-<médico>-<AAAAMMDD>-<HHMM>, horas 08:00, 08:20, 08:40, 10:00, 10:20 y 10:40La disponibilidad no lista los de minuto 40
Cupo ya tomadominuto 40 (p. ej. slt-D1-20261103-0840)409 SLOT_NOT_AVAILABLE al agendar o reprogramar
Disponibilidad en fecha pasadaayer o antes400
Paciente inexistentedocumento 9999999999404 HEALTH_PATIENT_NOT_FOUND; con new_patient se “registra”
Cancelar sin motivoreason de menos de 5 caracteres422 HEALTH_REASON_REQUIRED
Asistenciacompleted / no_showCita futura → 422 HEALTH_STATUS_NOT_ALLOWED; pasada → 200
Facturasinv-R-120000-… (RADICADA, $120.000) e inv-C-53500-… (CUV_OK, $53.500)Las dos facturas de prueba
Pago del pagadormedio TRANSFERENCIA, CONSIGNACION, GIRO_DIRECTO o RETENCIONOtro medio → 422 HEALTH_PAYMENT_METHOD
Pago sin referenciareference vacía422 HEALTH_PAYMENT_REFERENCE
Pago mayor que el netomás de $120.000 o $53.500422 PAYMENT_EXCEEDS_BALANCE

Las citas tienen ids aps-<médico>-<AAAAMMDD>-<HHMM>-<hash>; reprogramar devuelve otro id.

Administrativo #

CasoValor de pruebaResultado
Colaboradores existentesCC 1000000001 (Laura Sandbox, Operaciones) y CC 1000000002 (Andrés Sandbox, Tesorería)Un upsert responde created: false
Colaborador nuevocualquier otro documentoSe “crea”
Colaborador inexistenteCC 9999999999404 en las lecturas
Datos bancarios en el upsertbank_name, bank_account_type, bank_account_number422
Periodo abiertoper-O-… (octubre de 2026)Recibe novedades
Periodo cerradoper-C-… (septiembre de 2026, aprobado)409 PERIOD_CLOSED al cargar novedades
Conceptos que calcula el motorSALARIO, SALUD, PENSION, PRIMA, CESANTIAS…422
ComprobantescualquieraSiempre DRAFT; mismo external_id → mismo id; post: true → 422
Tercero existenteNIT 900000001created: false
Tesoreríarecaudos, egresos, cuentas de cobroDRAFT; valor <= 0 → 422; el cruce automático responde matched: 0

PQRS #

CasoResultado
Radicar con document de 1000000001 a 1000000004201; el mismo cuerpo produce el mismo id y radicado.
Radicar con document 9999999999422 AFFILIATE_NOT_FOUND.
Responder la PQRS PQRS-2026-999999 (cerrada)409.
Cambiar de estado PQRS-2026-999999409, salvo a closed (200, sin cambios).
Id que no es pqr-… ni un radicado404 PQRS_NOT_FOUND.
Listar y estadísticasBandeja fija de 5 PQRS de los documentos de prueba (aplica filtros y paginación).

Las transiciones permitidas son las mismas del motor (opened → in_progress, escalated, resolved o closed; resolved solo → closed). Una escritura devuelve el estado nuevo, pero un GET posterior vuelve a opened.

Webhooks #

CasoResultado
Crear un endpointId whe_sbx_<hash> (misma URL → mismo id) y secreto whsec_sbx_<hash>.
Rotar el secretoOtro whsec_sbx_… fijo.
Cualquier id whe_sbx_…Existe (detalle, editar, borrar, rotar, probar).
Cualquier otro id de endpoint404 WEBHOOK_ENDPOINT_NOT_FOUND.
URL http://, localhost o IP privada422 WEBHOOK_INVALID_URL.
events vacío o con formato inválido422 WEBHOOK_INVALID_EVENTS (solo se valida el formato recurso.evento).
Enviar pruebadelivery_id whd_sbx_test_…, event_id test-sbx-…, "simulated": true.
Entrega whd_sbx_ok_…success, credits.decision, 2026-10-01; replay → 409.
Entrega whd_sbx_fail_…failed (HTTP 500), wallets.cashin.confirmed, 2026-10-02; replay → 201 (whd_sbx_retry_…).
Entrega whd_sbx_aban_…abandoned (HTTP 503), credits.disbursed, 2026-10-03; replay → 201 (whd_sbx_retry_…).
Catálogo9 eventos de muestra con "sample": true.

No hay envío HTTP real: para recibir entregas firmadas usa una llave de producción en dev (Probar tus webhooks).

Relojes y simuladores #

HerramientaValores
Relojes de pruebaId tcl-…; avance de 0 a 63 días (5.443.200 s) por llamada; nunca hacia atrás.
SimuladoresMonto 22.22 → FAILED; 33.33 → RETURNED; 11.11 o cualquier otro → SETTLED / DISBURSED.

Prefijos de ids del sandbox #

PrefijoQué es
sbx-Solicitud de crédito o subsidio
dsb-Desembolso de crédito
mad-Cuota monetaria
wtx-Transacción de billetera (P2P, Bre-B, recarga, movimiento)
crd-Tarjeta
lna-Préstamo de cartera
slt- / aps- / inv-Cupo, cita y factura de salud
per-O- / per-C-Periodo de nómina abierto / cerrado
pqr-PQRS
whe_sbx_ / whd_sbx_Endpoint y entrega de webhooks
tcl-Reloj de prueba