Documentation
5 minQuickstart
Mint a sandbox key and move your first dollar in under ten minutes.
This walks you from an empty account to a settled sandbox payment. It takes about ten minutes and requires no production funds.
1. Mint a sandbox key#
Open the dashboard, switch the environment selector to Sandbox, and create a key. Keys are shown once.
export JUICEPAY_KEY="jp_test_9f2KxQ7mLp4Vn8Rt"
export JUICEPAY_URL="https://api.sandbox.juicepay.test"Scope the key to what your service actually does. A checkout service needs payment_intents:write, not payouts:write.
2. Check your balance#
curl -s "$JUICEPAY_URL/v1/balances" \
-H "Authorization: Bearer $JUICEPAY_KEY" | jq{
"object": "list",
"data": [
{
"asset": "USDC",
"available": "25000.000000",
"pending": "0.000000",
"chains": ["base", "solana", "arbitrum"]
}
]
}Sandbox accounts are seeded with 25,000 USDC. If the list is empty, confirm you are using the sandbox base URL.
3. Create a payment intent#
A payment intent is your request for someone to pay you. It returns a hosted URL and a set of accepted assets.
curl -s -X POST "$JUICEPAY_URL/v1/payment_intents" \
-H "Authorization: Bearer $JUICEPAY_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: qs-first-intent-001" \
-d '{
"amount": "125.00",
"asset": "USDC",
"reference": "INV-1042",
"accepted_chains": ["base", "solana"],
"expires_in": 3600
}' | jqThe response contains hosted_url and a status of requires_payment.
The
Idempotency-Keyheader is optional in sandbox but treat it as mandatory in your code from day one. Retrying this request without it creates a second intent.
4. Simulate the payment#
Sandbox exposes a trigger endpoint that moves an intent to a terminal state without any chain interaction.
curl -s -X POST "$JUICEPAY_URL/v1/sandbox/payment_intents/pi_9fK2xQ/succeed" \
-H "Authorization: Bearer $JUICEPAY_KEY"Available triggers are succeed, fail, and expire. You can also trigger underpay and overpay to exercise your reconciliation logic.
5. Confirm the settled state#
curl -s "$JUICEPAY_URL/v1/payment_intents/pi_9fK2xQ" \
-H "Authorization: Bearer $JUICEPAY_KEY" | jq '.status, .settled_amount'"succeeded"
"125.000000"Your balance now reflects the payment in the asset you requested, regardless of which chain the simulated customer used.
6. Receive the webhook instead#
Polling is fine for a first look; production should use webhooks. Point a local listener at a tunnel and register it:
juicepay listen --forward-to localhost:3000/webhooks/juicepayThe CLI prints a signing secret. Store it and verify every delivery — see Handle webhooks reliably.
Next steps#
- Accept a payment — turn the intent above into a real checkout flow.
- Sandbox — the full set of deterministic triggers.
- Go-live checklist — what to verify before production.