Sandbox Mode
Test the full Oris payment pipeline without moving real funds. Same API, same infrastructure. Use test keys to activate sandbox mode.
Getting Test Keys
When you create a developer account, you receive two key pairs: live and test. Test keys use the oris_sk_test_ and oris_pk_test_ prefixes. All API calls go to the same base URL. No separate sandbox endpoint exists.
from oris import OrisClient
# Sandbox client - same URL, test keys
client = OrisClient(
api_key="oris_sk_test_your_key_here",
api_secret="oris_pk_test_your_secret_here",
)
print(client.is_sandbox) # True
import { OrisClient } from '@oris/sdk';
const client = new OrisClient({
apiKey: 'oris_sk_test_your_key_here',
apiSecret: 'oris_pk_test_your_secret_here',
});
console.log(client.isSandbox); // true
The SDK detects the key prefix automatically. Mixing a test key with a live secret (or vice versa) returns a 401 error.
How Sandbox Works
Sandbox runs on the same database and the same containers as production. A boolean is_sandbox flag on every record separates test data from live data. Row-level security policies enforce this at the database level. A sandbox query can never return live data, and a live query can never return sandbox data.
The auth middleware reads your API key prefix and sets the sandbox flag for the entire request lifecycle. No downstream service re-parses the key.
Pre-Funded Wallets
Sandbox wallets are created with a 10,000 USDC balance. You can add more test funds at any time.
wallet = client.wallets.create(agent_id=agent_id, chain="polygon")
print(wallet["cached_balance_usdc"]) # 10000.0
# Add more test funds
client.wallets.fund(wallet["id"], amount=5000.0, stablecoin="USDC")The POST /oris/wallets/{id}/fund endpoint only works for sandbox wallets. Calling it with a live wallet returns 403.
Magic Numbers
The sandbox payment adapter uses the cents portion of the amount to determine the outcome. This follows the same pattern as Stripe test cards.
| Cents | Result | Description |
|---|---|---|
| .00 | Success | Normal approval |
| .01 | Failed | insufficient_funds |
| .02 | Failed | card_expired |
| .03 | Failed | 5s delay, then network_timeout |
| .04 | Failed | compliance_blocked |
| .05 | Pending | Never settles (resolve via webhook trigger) |
| .99 | Partial | Half the amount is approved |
| Other | Success | Normal approval |
# Successful payment
tx = client.payments.send(
agent_id=agent_id, to_address="0xTest",
amount=25.00, chain="polygon", token="USDC"
)
print(tx["tx_hash"]) # "0xsandbox_..."
# Insufficient funds
tx = client.payments.send(
agent_id=agent_id, to_address="0xTest",
amount=25.01, chain="polygon", token="USDC"
)
print(tx["failure_reason"]) # "insufficient_funds"
# Pending (for webhook testing)
tx = client.payments.send(
agent_id=agent_id, to_address="0xTest",
amount=25.05, chain="polygon", token="USDC"
)
print(tx["status"]) # "pending"All sandbox transaction hashes use the 0xsandbox_ prefix.
Webhook Testing
Sandbox provides three endpoints to test your webhook integration end to end.
1. Configure your webhook URL:
curl -X POST https://api.useoris.xyz/api/v1/oris/sandbox/webhooks/configure \
-H "Authorization: Bearer oris_sk_test_..." \
-H "Content-Type: application/json" \
-d '{"url": "https://myapp.dev/webhooks/oris", "events": ["payment.completed", "payment.failed"]}'2. Trigger a pending transaction:
curl -X POST https://api.useoris.xyz/api/v1/oris/sandbox/webhooks/trigger \
-H "Authorization: Bearer oris_sk_test_..." \
-H "Content-Type: application/json" \
-d '{"transaction_id": "sandbox_abc123", "target_status": "confirmed"}'Your configured webhook URL receives a payment.completed event with an X-Oris-Signature HMAC-SHA256 header for verification.
3. Check delivery logs:
curl https://api.useoris.xyz/api/v1/oris/sandbox/webhooks/log \
-H "Authorization: Bearer oris_sk_test_..."Returns the last 50 webhook deliveries with event type, HTTP status, payload, and attempt count.
Sandbox vs Live
| Feature | Sandbox | Live |
|---|---|---|
| API key prefix | oris_sk_test_ | oris_sk_live_ |
| Wallet initial balance | 10,000 USDC | 0 (fund via on-ramp) |
| On-chain execution | Simulated (no gas cost) | ERC-4337 UserOp via Alto bundler |
| Compliance screening | Skipped (instant allow) | Veris AML pre-screen (fail-closed) |
| Transaction hashes | 0xsandbox_ prefix | Real on-chain hashes |
| Solana | Devnet (real chain, test tokens) | Mainnet |
| Billing | Not metered | Metered and invoiced via Stripe |
| KYB verification | Auto-approved | Required before live key activation |
| Webhook delivery | Via sandbox trigger endpoint | Real-time from payment pipeline |
Go Live
When your integration is ready, switch from test keys to live keys. No code changes are needed beyond replacing the key values. The SDK handles the rest.
