Primeros pasos · 5 minutos
Tu primera llamada
En cinco pasos: configura la llave, crea el cliente, valida la llave y sus scopes, consulta un afiliado y radica un crédito en el sandbox con su Idempotency-Key.
En esta página
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í.
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', ...]import { CompenseClient } from "@compense/sdk";
const client = new CompenseClient({ apiKey: process.env.COMPENSE_API_KEY!, environment: "sandbox" });
const health = await client.system.health();
console.log(health.status, health.tenant, health.scopes);<?php
require __DIR__ . '/vendor/autoload.php';
use Compense\Sdk\CompenseClient;
$client = new CompenseClient(apiKey: getenv('COMPENSE_API_KEY'), environment: 'sandbox');
$health = $client->system->health();
echo $health->status, ' ', $health->tenant, ' ', implode(',', $health->scopes), PHP_EOL;using Compense.Sdk;
using Compense.Sdk.Models;
using var client = new CompenseClient(
Environment.GetEnvironmentVariable("COMPENSE_API_KEY")!, CompenseEnvironment.Sandbox);
GatewayHealth health = await client.System.HealthAsync();
Console.WriteLine($"{health.Status} {health.Tenant} {string.Join(",", health.Scopes)}");package main
import (
"context"
"fmt"
"log"
"os"
compense "github.com/Appiasoft/compense-saas-sdk-go"
)
func main() {
ctx := context.Background()
client, err := compense.NewClient(os.Getenv("COMPENSE_API_KEY"),
compense.WithEnvironment(compense.Sandbox))
if err != nil {
log.Fatal(err)
}
health, err := client.System.Health(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(health.Status, health.Tenant, health.Scopes)
}curl https://sandbox.dev.compense.co/gw/v1/gateway/health/ \
-H "X-API-Key: $COMPENSE_API_KEY"
# {"status":"ok","tenant":"horizonte","scopes":["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)import { NotFoundError } from "@compense/sdk";
try {
const lookup = await client.affiliates.get("1032456789");
console.log(lookup.exists, lookup.affiliate.category);
} catch (err) {
if (err instanceof NotFoundError) console.log("No es afiliado:", err.status, err.traceId);
else throw err;
}use Compense\Sdk\Exception\NotFoundException;
try {
$lookup = $client->affiliates->get('1032456789');
echo var_export($lookup->exists, true), ' ', $lookup->affiliate['category'] ?? '-', PHP_EOL;
} catch (NotFoundException $e) {
echo 'No es afiliado: ', $e->status, ' ', $e->traceId, PHP_EOL;
}try
{
AffiliateLookup lookup = await client.Affiliates.GetAsync("1032456789");
Console.WriteLine($"{lookup.Exists} {lookup.Affiliate["category"]}");
}
catch (NotFoundException e)
{
Console.WriteLine($"No es afiliado: {e.Status} {e.TraceId}");
}lookup, err := client.Affiliates.Get(ctx, "1032456789")
switch {
case compense.IsNotFound(err):
var apiErr *compense.APIError
errors.As(err, &apiErr)
fmt.Println("No es afiliado:", apiErr.StatusCode, apiErr.TraceID)
case err != nil:
log.Fatal(err)
default:
fmt.Println(lookup.Exists, lookup.Affiliate["category"])
}curl https://sandbox.dev.compense.co/gw/v1/gateway/affiliates/1032456789/ \
-H "X-API-Key: $COMPENSE_API_KEY"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…const tx = await client.credits.submitApplication({
affiliate: { document_type: "CC", document_number: "1000000001" },
productCode: "LIBRANZA_12M",
amount: "3500000",
termMonths: 12,
externalReference: "HORIZONTE-CRED-2026-000123",
idempotencyKey: "horizonte-cred-2026-000123",
});
console.log(tx.transactionId, tx.status, tx.idempotentReplay, tx.data);use Compense\Sdk\Model\AffiliateRef;
$tx = $client->credits->submitApplication(
affiliate: new AffiliateRef('CC', '1000000001'),
productCode: 'LIBRANZA_12M',
amount: '3500000',
termMonths: 12,
externalReference: 'HORIZONTE-CRED-2026-000123',
idempotencyKey: 'horizonte-cred-2026-000123',
);
echo $tx->transactionId, ' ', $tx->status, ' ', var_export($tx->idempotentReplay, true), PHP_EOL;Transaction tx = await client.Credits.SubmitApplicationAsync(
affiliate: new AffiliateRef("CC", "1000000001"),
productCode: "LIBRANZA_12M",
amount: "3500000",
termMonths: 12,
externalReference: "HORIZONTE-CRED-2026-000123",
idempotencyKey: "horizonte-cred-2026-000123");
Console.WriteLine($"{tx.TransactionId} {tx.Status} {tx.IdempotentReplay}");tx, err := client.Credits.SubmitApplication(ctx, &compense.CreditApplicationParams{
Affiliate: compense.AffiliateRef{DocumentType: "CC", DocumentNumber: "1000000001"},
ProductCode: "LIBRANZA_12M",
Amount: "3500000",
TermMonths: 12,
ExternalReference: "HORIZONTE-CRED-2026-000123",
}, compense.WithIdempotencyKey("horizonte-cred-2026-000123"))
if err != nil {
log.Fatal(err)
}
fmt.Println(tx.TransactionID, tx.Status, tx.IdempotentReplay)curl -X POST https://sandbox.dev.compense.co/gw/v1/gateway/credits/application/ \
-H "X-API-Key: $COMPENSE_API_KEY" \
-H "Idempotency-Key: horizonte-cred-2026-000123" \
-H "Content-Type: application/json" \
-d '{
"afiliado": {"document_type": "CC", "document_number": "1000000001"},
"product_code": "LIBRANZA_12M",
"amount": "3500000",
"term_months": 12,
"external_reference": "HORIZONTE-CRED-2026-000123"
}'La respuesta de toda escritura es el sobre de transacción:
{
"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)const status = await client.transactions.get(tx.transactionId);
console.log(status.module, status.status, status.history);$status = $client->transactions->get($tx->transactionId);
echo $status->module, ' ', $status->status, PHP_EOL;TransactionStatus status = await client.Transactions.GetAsync(tx.TransactionId);
Console.WriteLine($"{status.Module} {status.Status} {string.Join(" → ", status.History)}");status, err := client.Transactions.Get(ctx, tx.TransactionID)
if err != nil {
log.Fatal(err)
}
fmt.Println(status.Module, status.Status, status.History)curl https://sandbox.dev.compense.co/gw/v1/gateway/transactions/$TX_ID/ \
-H "X-API-Key: $COMPENSE_API_KEY"Lo que sigue #
compense.