Getting started · 5 minutes
Your first call
In five steps: set up the key, create the client, validate the key and its scopes, look up an affiliate and submit a credit application in the sandbox with its Idempotency-Key.
On this page
You’ll be talking to the sandbox: the gateway responds with the simulated engine, deterministically and with no real money. You need a sandbox key and the SDK installed. Pick your language in any tab: your choice is remembered across the whole site.
1. Set up the key #
Store the key in an environment variable; every example reads it from there.
export COMPENSE_API_KEY="cmp_..." # PowerShell: $env:COMPENSE_API_KEY = "cmp_..."2. Create the client and validate the key #
system.health doesn’t touch the engine: it confirms the key is valid and returns the tenant it
belongs to and its scopes. It’s the first call of any integration (and a good health check
for your monitoring).
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", ...]}If you see a 401, the header is missing; a 403 means the key is invalid, revoked, from another environment or missing
the scope. See Authentication.
3. Look up an affiliate #
affiliates.get matches a document against your entity’s affiliate registry. This lookup
isn’t simulated: it reads the affiliates your entity has already loaded (through the dashboard or with
affiliates.cross). Use a document from your own base; one that isn’t there responds
404, and each SDK turns it into its “not found” exception.
from compense_gateway import NotFoundError
try:
lookup = client.affiliates.get("1032456789")
print(lookup.exists, lookup.affiliate.get("category"))
except NotFoundError as e:
print("Not an affiliate:", 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("Not an affiliate:", 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 'Not an affiliate: ', $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($"Not an affiliate: {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("Not an affiliate:", 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. Submit a credit application (your first write) #
Credits are simulated in the sandbox, with documents that have fixed behavior: CC 1000000001
is eligible (approved and disbursable), 1000000002 is ineligible, 1000000003 goes to manual
review and 9999999999 doesn’t exist. The full table is in Test data.
Every write carries an Idempotency-Key: if the request gets cut off and you resend it with the same
key, the gateway returns the original response instead of submitting twice. The SDKs generate one
automatically, but when you control the retries it’s best to give it a stable one per business
operation (for example, derived from your application number). More in Idempotency.
tx = client.credits.submit_application(
affiliate={"document_type": "CC", "document_number": "1000000001"},
product_code="LIBRANZA_12M",
amount="3500000", # amounts as decimal strings
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) # engine body: application id, status…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"
}'The response to every write is the transaction envelope:
{
"status": "success",
"transaction_id": "a1b2c3d4-0000-4a1b-9c2d-000000000001",
"module": "credits",
"data": { "application_id": "sbx-…", "module": "credits", "status": "RECEIVED", "profile": "eligible", "environment": "sandbox" }
}Run the same code again: you’ll see the same transaction_id and idempotent_replay: true.
That’s the guarantee that lets you retry without fear of duplicates.
5. Check the transaction status #
Store the transaction_id in your system: it’s the reference for support and for reconciliation.
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"What’s next #
compense CLI.