Test environment
An sk_test_… key operates in test mode: it does not move real money. The
contract is identical to production —same routes, fields, errors and webhook
signature—.
curl -s $BASE/v1/tenant/me -H "x-api-key: $KEY"# { "mode": "test", ... }With per-ticket prefunding, your test account has no wallet: your test
prefunding already comes loaded with simulated Bs (GET /v1/prefondeos).
Where to test
Section titled “Where to test”In QA (https://qa.bolivarconnect.com) with the sk_test_ key of your
test account (environment: "sandbox" in GET /v1/tenant/me). Your payments
go out through simulated payment networks: they never touch a real network
or anyone’s money. To move to production you change the URL and the key; the
contract does not change.
# Test beneficiaries and, depending on your funding model, simulated balancecurl -s -X POST $BASE/v1/test-helpers/seed -H "x-api-key: $KEY"Test beneficiaries
Section titled “Test beneficiaries”Fictitious: they belong to nobody. POST /v1/test-helpers/seed registers them,
or you send them inline in beneficiary.
| Name | National ID | Bank | Phone | Account | Method |
|---|---|---|---|---|---|
| Prueba Pago Movil | V10000001 |
0102 |
04140000001 |
— | Pago móvil |
| Prueba Transferencia | V10000002 |
0134 |
04140000002 |
01340000000000000002 |
Bank transfer |
| Prueba Otro Banco | V10000003 |
0105 |
04240000003 |
01050000000000000003 |
Bank transfer |
For an immediate rejection: bank 9999 (reason: bank_unreachable) or a
fullName starting with NO TITULAR (reason: beneficiary_mismatch).
Triggering the hard scenarios
Section titled “Triggering the hard scenarios”They are chosen payment by payment, in the reference (payment concept)
of POST /v1/payouts. They do not affect any other payment, yours or
another account’s, even if you repeat them many times in a row (neither do
the 9999 and NO TITULAR rejections).
reference |
Response | What you should see next |
|---|---|---|
(none) or TEST:SETTLED |
settled |
payment.settled webhook |
TEST:SUBMITTED |
submitted |
Nothing until you resolve it: settled or failed |
TEST:UNKNOWN |
unknown |
Nothing until you resolve it: settled or failed. Do not retry |
TEST:TIMEOUT_AFTER_SUBMIT |
unknown |
The network paid and the response was cut off: it resolves on its own to settled in under a minute. The dangerous case |
More text can follow after a space (TEST:UNKNOWN lote 7).
To close a payment in progress or return a settled one:
curl -s -X POST $BASE/v1/test-helpers/payments/<paymentId>/resolve -H "x-api-key: $KEY" \ -H 'content-type: application/json' -d '{"outcome":"failed"}'outcome |
On | Ends up | Webhook |
|---|---|---|---|
settled |
submitted or unknown |
settled |
payment.settled |
failed |
submitted or unknown (not if the network already paid: 409) |
failed, reversed |
payment.failed |
returned |
settled |
reversed, reversed including the fee |
payment.reversed |
/v1/test-helpers/* only responds to an sk_test_ key of a test account
(403 test_account_required with any other) and does not exist in
production (404).
With an own account
Section titled “With an own account”If your model is own_account (funding.model in GET /v1/tenant/capabilities),
your test account behaves like the live one:
- The payment does not settle on the spot. With no scenario (or with
TEST:SETTLED) it respondssubmittedand settles by itself in about 20 s, with thepayment.settledwebhook.TEST:SUBMITTEDleaves it in flight until you resolve it;TEST:UNKNOWNandTEST:TIMEOUT_AFTER_SUBMITwork as above. - The same data as in production. The sender (
sender) is required, and the beneficiary needs first and last name. Pago móvil requires the beneficiary’s mobile; on a bank transfer, if you don’t send it, the sender’s is used (if it is Venezuelan). - USD 500 cap per operation, at the day’s rate, on top of your account’s
Bs limit. Above it:
failedwithreason: amount_above_limit. - Your balance is your inventory (
GET /v1/treasury/inventory, notposition). Each payment lowers it by the amount plus the payment network’s fee, shown asnetworkFeeBsinGET /v1/treasury/volume. In the sandbox the simulated network fee is 0.3%; in production the payment network sets it and you get it in the report. If it is not enough:failedwithreason: payout_insufficient_balanceand the inventory stays the same. If an in-flight payment endsfailed, the amount comes back; the fee does not. - To have a balance:
seedleaves a sample USDT selling rate (1,000.00) and, if your inventory is at zero, a Bs 1,000,000.00 exchange at that rate. For more, record your own USD to Bs exchanges:
curl -s -X POST $BASE/v1/test-helpers/fundings -H "x-api-key: $KEY" \ -H 'content-type: application/json' \ -d '{"amountUsd":100000,"amountBs":100000000,"reference":"cambio-0001"}'In production our team records and approves that exchange; here it is
approved right away and enters the average cost used to value each payment.
Repeating the referencia with the same amounts returns the same exchange;
with others, 409 funding_reference_reused. Requires payments:write.
Local only: global chaos
Section titled “Local only: global chaos”If you run the platform on your machine with SANDBOX_ENABLED=true, you also
get /sandbox/*, which affects all payments on the server. It does not
exist in QA or in production.
curl -s -X POST $BASE/sandbox/chaos -H 'content-type: application/json' \ -d '{"mode":"timeout_after_submit","method":"pago_movil"}'mode |
What it simulates | What you should see |
|---|---|---|
reject |
The payment network rejects without moving money | It goes out through another channel or payment network, or status: "failed" with reason |
timeout |
No response before executing | status: "unknown", not compensated |
timeout_after_submit |
It pays and the response is cut off | status: "unknown", not compensated. The dangerous case |
slow |
Adds latency | Everything the same, but slow |
off |
Normal operation |
method is optional: without it, the scenario applies to both methods. With
it you reproduce “pago móvil down, bank transfer working” and see the method
switch (methodChanged: true).
curl -s $BASE/sandbox/chaos # active scenariocurl -s -X POST $BASE/sandbox/chaos/resetSimulating the bank (local only)
Section titled “Simulating the bank (local only)”All with content-type: application/json:
POST |
Body | What it simulates |
|---|---|---|
/sandbox/bank/payout-settled |
{"paymentId":"89920401-…"} |
The payment network confirms a payout in doubt late |
/sandbox/bank/payout-returned |
{"paymentId":"89920401-…"} |
The bank returns a settled payout days later |
/sandbox/bank/prefunding-wire |
{"amount":100000000,"asset":"BS"} |
Your funding transfer arrives |
Testing your webhook receiver (local only)
Section titled “Testing your webhook receiver (local only)”In QA, use POST /v1/tenant/webhook/test against your URL.
| Endpoint | What for |
|---|---|
GET /sandbox/webhooks |
Sink: what we have sent you, with signature and headers |
POST /sandbox/webhooks/failing |
A receiver that always returns 500 |
GET /sandbox/outbox |
The queue with attempts and status |
GET /sandbox/canales |
Status and chaos scenario of each channel |
Combine it with the real failed queue, GET /v1/events?status=dead and
POST /v1/events/retry-dead. See webhooks.
Demo console
Section titled “Demo console”/demo/consola runs the scenarios end to end with real API responses: normal
payment, channel down, payment in doubt, total rejection, open circuit and
permission checks.