Testing
Don't ship to production untested. The sandbox environment is a full clone of the production API with mock payment gateways, instant settlement, and replayable webhooks.
Sandbox setup
Email [email protected] and request:
- Sandbox
LINK_SIGNING_SECRET - Sandbox
WEBHOOK_SECRET - Sandbox seller UUID (we'll provision a test seller)
You'll get separate credentials from production. Never use production secrets in your test environment — and never commit either to git.
Sandbox base URLs
| Resource | URL |
|---|---|
| API | https://sandbox-api.rekberpay.com |
| Web app | https://sandbox.rekberpay.com |
| Status | https://status.rekberpay.com |
Everything else (paths, auth model, response shapes) is identical to production.
Test users
Create test buyers in the sandbox via the regular signup flow at https://sandbox.rekberpay.com/register. Pre-provisioned test accounts:
| Password | Role | |
|---|---|---|
[email protected] | BuyerSandbox123! | Buyer with KYC verified |
[email protected] | BuyerSandbox123! | Buyer without KYC |
[email protected] | SellerSandbox123! | Seller with KYC verified |
Mock payment
In the sandbox, the QRIS gateway is wired to a mock that auto-confirms after 2 seconds. You don't need to scan anything — just click "Pay with QRIS" and the webhook fires shortly after.
For tighter test loops, hit the dev-only mock-pay endpoint:
curl -X POST https://sandbox-api.rekberpay.com/api/escrows/<id>/mock-pay \
-H "Cookie: rekberpay_session=<test-buyer-session>"This skips the gateway entirely. State goes from pending_payment → paid instantly and the webhook fires.
mock-pay is rejected in production with 404 NOT_FOUND. Don't build it into your production code paths.
Scenarios you should cover
A good test suite covers the happy path plus the most likely failure modes.
1. Happy path
- Sign a link with valid params
- POST to
/api/escrows/from-link - Verify response: 201,
escrow_urlpresent - Trigger mock-pay
- Receive
payment.completedwebhook - Verify your system marked the order as paid
2. Invalid signature
- Sign a link
- Tamper with
amountafter signing - POST → expect
403 INVALID_SIGNATURE
This catches accidental field reordering, encoding bugs, and wrong-secret deploys before they hit production.
3. Expired link
- Set
expiresto 5 minutes in the past - POST → expect
400 LINK_EXPIRED
4. Duplicate ref
- Create an escrow with
ref: TEST_001 - Create another with the same
ref→ expect409 DUPLICATE_REF
The second escrow should not be created.
5. Idempotency replay
- Create an escrow with
Idempotency-Key: <uuid-1> - Repeat the request with the same key
- Verify both responses have the same
escrow.id - Verify the second response includes
Idempotent-Replay: trueheader
6. Webhook signature verification
Send your handler a forged webhook (POST with no signature field, or with signature: "00000..."). Verify your handler returns 401 and does not process the event.
7. Webhook retry
Have your handler return 500 once. Verify RekberPay retries within ~1 second. Then return 200 — verify the second attempt succeeds and the event is processed.
In sandbox, you can replay any webhook from the dashboard at https://sandbox.rekberpay.com/dashboard/webhooks/<event-id>/replay.
8. Out-of-order webhooks
In rare cases, webhooks can arrive out of order (e.g., escrow.received before escrow.sent if your handler is slow on the first event). Verify your handler can recover from out-of-order delivery — typically by trusting the status field in the payload over your local state.
9. Concurrent escrows
Create 10 escrows in parallel for the same seller. Verify all succeed and that no race condition causes duplicate ref values.
10. Partial failures
Disconnect the network mid-request. Verify your retry logic kicks in with the same Idempotency-Key.
Replaying webhooks
Every webhook delivery is logged in the sandbox dashboard. To replay:
- Open
https://sandbox.rekberpay.com/dashboard/webhooks - Find the event
- Click Replay
Useful for testing changes to your handler without re-running the full payment flow.
Load testing
The sandbox API is rate-limited (1000 req/min per IP). For load testing:
- Start small (10 RPS) and ramp up
- Use distinct
refvalues per request - Use distinct
Idempotency-Keyvalues per attempt - Don't hammer the same escrow with multiple state transitions in parallel
If you need higher limits, email [email protected] — we can raise sandbox limits temporarily.
CI integration
A typical CI flow:
# .github/workflows/integration.yml
test:
steps:
- run: pnpm install
- run: pnpm test:unit
- run: pnpm test:integration
env:
REKBERPAY_API_BASE: https://sandbox-api.rekberpay.com
LINK_SIGNING_SECRET: ${{ secrets.SANDBOX_LINK_SIGNING_SECRET }}
WEBHOOK_SECRET: ${{ secrets.SANDBOX_WEBHOOK_SECRET }}
TEST_SELLER_ID: ${{ secrets.SANDBOX_SELLER_ID }}Store secrets in GitHub Secrets / GitLab CI variables / your CI's vault. Never commit them.
Going to production
When you're ready:
- Email [email protected] with evidence your integration is stable (test results, error rate, etc.)
- Sign the partner agreement
- Receive production
LINK_SIGNING_SECRETandWEBHOOK_SECRET - Update environment variables (no code changes needed)
- Configure production webhook URL in the partner dashboard
- Run a single live transaction with a small amount before opening the floodgates
Even after you go live, your sandbox credentials keep working. Use it for ongoing development and CI tests.
Common testing gotchas
| Gotcha | Fix |
|---|---|
| Signature works in test, fails in prod | Different secret. Verify your env var resolution. |
| Tests pass locally, fail in CI | Network egress to sandbox-api.rekberpay.com is blocked. Whitelist the domain. |
| Webhooks don't arrive in CI | CI doesn't have a public URL. Use smee.io or ngrok tunnel, or mock the webhook handler in tests. |
| Idempotency cache hits when you don't want them | Use a fresh UUID per test run; don't hardcode keys. |
| Mock-pay returns 404 in prod | Expected — only available in sandbox. Use real payment in prod e2e. |
Next steps
- Quickstart — wire up the integration
- Reference — every endpoint, every error code