Testing

Build and verify your integration end-to-end before going live — without creating real members or awarding real points. Everything runs against an isolated test environment keyed by your sk_test_* API key.

Test vs live keys

  • sk_test_* keys hit a fully isolated environment. Members, campaigns, transactions, and rewards created here never touch production data.
  • sk_live_* keys operate on production. Keep them secret and server-side.
  • Test keys are rate-limited to 60 req/min; live keys to 600. See Authentication.

Simulate before you commit

POST /transactions/simulate runs the full earn-rule engine and returns the same shape as evaluate() — but writes nothing, creates no member, and awards no points. Use it for "you would earn X" previews and campaign QA. It is available on test keys only.

cURL
# Preview an earn without writing anything — sk_test_* only
curl -X POST ".../tenants/$TENANT_ID/transactions/simulate" \
  -H "X-API-Key: sk_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "memberRef": "customer_001", "amount": 25000 }'

Debugging why a campaign didn't fire

When evaluate() or simulate() returns an empty campaigns array on a test key, the response includes a _debug object explaining why each active campaign skipped. (This field is never returned on live keys.)

200 OK (sk_test_*)
{
  "pointsAwarded": 0,
  "pointsBalance": 450,
  "campaigns":     [],
  "state":         "PROCESSED",
  "_debug": {
    "activeCampaigns": 1,
    "campaignChecks": [
      {
        "campaignId":   "5a7b3c9d-...",
        "campaignName": "Gold Members Only",
        "matched":      false,
        "reason":       "SEGMENT_MISMATCH: member not in target segment"
      }
    ]
  }
}

Common skip reasons: CAMPAIGN_NOT_ACTIVE, SEGMENT_MISMATCH, BELOW_MIN_SPEND, DATE_RANGE, and STORE_MISMATCH.

A typical test loop

  1. Create and activate a campaign with your sk_test_* key.
  2. simulate() a basket to confirm the rule matches and the points/rewards are right.
  3. evaluate() the same basket to record it, then fetch the member to confirm the balance and any rewardIds.
  4. Point a webhook at a tunnel (e.g. ngrok) and verify the signed transaction.processed / reward.issued deliveries.
  5. Swap the test key for a live key — no code changes required.
See the simulate reference for the full request/response contract and a side-by-side comparison with evaluate().
Testing — Loyalty Engine Docs