Skip to main content

Security best practices

Cheggout integrations issue things of monetary value. These practices are what separates a demo-quality integration from one you can run in production at a bank.

Credentials

Keys and secrets live on your backend. A private key or API secret in a mobile binary, a JavaScript bundle, or a repository is compromised — assume extraction and rotate.

CredentialWhere it belongsNever
RSA private keySecret manager, backend onlyApp package, JS, source control
APP_KEY / SEC_KEYSecret manager, backend onlyClient of any kind
Reference tokenBackend onlyAny client — it is channel-wide
User tokenBackend, or the client surface that needs itLogs, URLs, analytics
CHANNELIDAnywhere— (identifier, not a secret)

Separate credentials per environment, and make sure UAT credentials cannot reach production.

Request integrity

  • Sign exactly what you send. Compute BDATA once, sign that string, transmit that string.
  • Verify Cheggout's response signature before acting on the payload.
  • Treat a signature failure as fatal. Never fall back to trusting an unverified body.

TBD The envelope carries no nonce or timestamp today, so it does not itself prevent replay. Compensate with IP whitelisting, TLS, and idempotency keys — and do not build a flow whose safety depends on a request being unrepeatable.

Issue rewards from your server, not your client

This is the single most important design decision in a rewards integration.

If a client can ask for a scratch card directly, anyone who can call that endpoint can mint reward eligibility without transacting. Put the request behind your backend, and verify the underlying order or payment before asking Cheggout for a card.

Where a server-to-server variant of an endpoint exists, prefer it. The GetScratchCardForBank flow exists specifically so issuance originates from your backend after order validation.

Practical rules:

  • Bind the reward request to a verified transaction you can prove happened.
  • Derive virtualId from your authenticated session — never from a client-supplied parameter.
  • Make extTransactionId your real transaction reference so it can be reconciled and disputed.

Identity and PII

  • virtualId must be pseudonymous — no email, mobile number, account number or name.
  • Never put virtualId or tokens in URLs you control. Query strings end up in access logs, referrer headers and analytics.
  • Keep the mapping from virtualId to your real customer on your side only.
  • Collect any additional personal data (a mobile number for a wallet link, for instance) directly with the customer's consent — do not route it through Cheggout unnecessarily.

Tokens

  • Short-lived, refreshed on 401, never on a business failure.
  • Single-flight refresh to avoid stampedes.
  • Never log them. Redact Authorization headers in your logging pipeline.
  • Never place a channel-scoped reference token on a client.

Client-side surfaces

The web widget and mobile SDKs necessarily hold a user token in the browser or app. Accept the implications:

  • Anything in localStorage or sessionStorage is readable by every script on the page. Keep your page's third-party script surface tight.
  • A user token can act as that user. Keep lifetimes short.
  • Do not put reward decisions in the client. The client renders what the server decided.

Idempotency and double-issuance

  • extTransactionId must be globally unique and never reused.
  • Read the idempotency guarantees — they hold in the common case but have documented exceptions. Do not rely on them as your only defence against double-issuance.
  • Where money or inventory is involved, keep your own ledger of what you requested and what you received, and reconcile.

Coin-burn ordering

If you run your own points or coin economy with the Deals Store, the ordering is prescribed:

  1. Burn coins in your wallet, atomically.
  2. Request the coupon from Cheggout.
  3. On failure, either retry with the same extTransactionId or refund the coins.

Never deliver a coupon before the burn is committed, and never leave a burn without either a coupon or a refund.

Logging and monitoring

Log enough to debug, never enough to leak.

LogDon't log
extTransactionId, rewardId, orderIdTokens, signatures, keys
Endpoint, latency, statusFull request bodies containing coupon codes
Error codes and messagesvirtualId in systems that also hold customer identity

Alert on: signature failures (a spike means a key or config problem), authentication failures, and a sudden change in reward-issuance rate.

Incident response

If a key, secret or token is exposed:

  1. Contact Cheggout immediately via Support.
  2. Request rotation of the affected credential.
  3. Review issuance logs for the exposure window.
  4. Rotate anything that shared the exposure path.

Checklist

  • Private key and API secrets in a secret manager, backend only
  • Separate credentials per environment
  • Response signatures verified; unsigned error bodies handled without crashing
  • Reward requests originate from your backend after order verification
  • virtualId derived from your authenticated session, never client input
  • virtualId contains no PII
  • extTransactionId unique, persisted, reconcilable
  • Tokens refreshed on 401 only, single-flight, never logged
  • Authorization redacted in logs
  • Alerting on signature and auth failure rates

Next