Vas a hablar con el sandbox: el gateway responde con el motor simulado, de forma determinista y sin dinero real. Necesitas una llave de sandbox y el SDK instalado. Elige tu lenguaje en cualquier pestaña: la elección se recuerda en todo el sitio.

1. Configura la llave #

Guarda la llave en una variable de entorno; todos los ejemplos la leen de ahí.

Shell
export COMPENSE_API_KEY="cmp_..."        # PowerShell: $env:COMPENSE_API_KEY = "cmp_..."

2. Crea el cliente y valida la llave #

system.health no toca el motor: confirma que la llave es válida y devuelve el tenant al que pertenece y sus scopes. Es la primera llamada de cualquier integración (y un buen health check para tu monitoreo).

import os
from compense_gateway import CompenseClient

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

health = client.system.health()
print(health.status, health.tenant, health.scopes)
# ok horizonte ['affiliates:read', 'credits:submit', ...]

Si ves un 401, falta la cabecera; un 403 significa llave inválida, revocada, de otro entorno o sin el scope. Revisa Autenticación.

3. Consulta un afiliado #

affiliates.get cruza un documento contra el registro de afiliados de tu entidad. Esta consulta no se simula: lee los afiliados que tu entidad ya cargó (por el panel o con affiliates.cross). Usa un documento de tu base; uno que no esté responde 404, y cada SDK lo convierte en su excepción de “no encontrado”.

from compense_gateway import NotFoundError

try:
    lookup = client.affiliates.get("1032456789")
    print(lookup.exists, lookup.affiliate.get("category"))
except NotFoundError as e:
    print("No es afiliado:", e.status, e.trace_id)

4. Radica un crédito (tu primera escritura) #

Los créditos sí se simulan en el sandbox, con documentos de comportamiento fijo: CC 1000000001 es elegible (aprobado y desembolsable), 1000000002 inelegible, 1000000003 va a revisión manual y 9999999999 no existe. La tabla completa está en Datos de prueba.

Toda escritura lleva una Idempotency-Key: si la petición se corta y la reenvías con la misma llave, el gateway devuelve la respuesta original en vez de radicar dos veces. Los SDK generan una automáticamente, pero cuando tú controlas los reintentos conviene darle una estable por operación de negocio (por ejemplo, derivada de tu número de solicitud). Más en Idempotencia.

tx = client.credits.submit_application(
    affiliate={"document_type": "CC", "document_number": "1000000001"},
    product_code="LIBRANZA_12M",
    amount="3500000",               # montos como texto decimal
    term_months=12,
    external_reference="HORIZONTE-CRED-2026-000123",
    idempotency_key="horizonte-cred-2026-000123",
)
print(tx.transaction_id, tx.status, tx.idempotent_replay)
print(tx.data)                      # cuerpo del motor: id de la solicitud, estado…

La respuesta de toda escritura es el sobre de transacción:

JSON
{
  "status": "success",
  "transaction_id": "a1b2c3d4-0000-4a1b-9c2d-000000000001",
  "module": "credits",
  "data": { "application_id": "sbx-…", "module": "credits", "status": "RECEIVED", "profile": "eligible", "environment": "sandbox" }
}

Vuelve a ejecutar el mismo código: verás el mismo transaction_id y idempotent_replay: true. Esa es la garantía que te permite reintentar sin miedo a duplicar.

5. Consulta el estado de la transacción #

Guarda el transaction_id en tu sistema: es la referencia para soporte y para conciliar.

status = client.transactions.get(tx.transaction_id)
print(status.module, status.status, status.history)

Lo que sigue #