Skip to content

Test mode

What the sandbox mirrors, how to reset it, and how to write integration tests against it.

Updated 2026-09-28

Every programme has a sandbox: a second, invisible programme that mirrors the live one. A sticky_test_… key writes there and nowhere else.

What the sandbox mirrors

Copied from liveNot copied
Active earning rules and boosts, tiersMembers, orders, ledgers, balances
Programme settings: return windows, redemption and expiry policyCampaigns (a boost that belongs to a campaign is copied without its campaign dates and audience)
The programme's name, currency and points nameWebhook endpoints (register test ones separately)
Branding (when the sandbox is first created)Portal links and the hosted rewards page
Your plan and its limits (the sandbox follows live)

So an order.paid that earns 250 points in test will earn 250 in live, provided the rules have not changed since the last wipe and no campaign applies.

Wiping it

On the Developers page of the admin, the Test sandbox card's Wipe test data button deletes every sandbox member, event, ledger entry and redemption, then re-copies the current live rules, tiers and programme settings. Use it before a test run so you start from a known state — and after you change rules in live, so the sandbox matches again. The data wipe is one atomic operation; nothing partial is ever left behind.

Writing integration tests against it

  1. Keep a sticky_test_… key in your CI secrets, never a live one.
  2. Give each test run a unique customer namespace — email: "ci-<run id>-<n>@example.test" — so parallel runs never collide and you never need to wipe mid-run.
  3. Send the event, then poll GET /v1/events/{id} until status is completed rather than sleeping: processing is asynchronous.
  4. Assert on GET /v1/members/{id} balances, not on the 202 response.
  5. A test endpoint receiving webhooks from the sandbox is the only reliable way to test your handler end to end; POST /v1/webhook_endpoints/{id}/test sends a webhook.test delivery on demand.
Wait for an event
ID=$(curl -s https://stickytier.com/v1/events -H "Authorization: Bearer $TEST_KEY" \
  -H "Content-Type: application/json" -d @order.json | jq -r .data.id)
until [ "$(curl -s https://stickytier.com/v1/events/$ID -H "Authorization: Bearer $TEST_KEY" | jq -r .data.status)" = completed ]; do sleep 0.5; done

Things that behave differently in test

  • POST /v1/members/{id}/portal-links answers 409 — there is no sandbox rewards page. The reason is no_portal_domain when the sandbox has no rewards-page address (it usually doesn't; that check comes first), otherwise test_mode.
  • There is no sandbox rewards page, so member sign-in cannot be tested there; drive members through the API.
  • Plan limits apply in the sandbox as they do in live.
  • The welcome bonus is never paid in the sandbox.
Test mode — StickyTier API