Skip to main content

Security Best Practices

Hilt’s security model is intentionally split by role:

  • browsers and merchant app sessions use JWTs
  • servers and automation use API keys
  • provider callbacks use signed webhook secrets
  • Telegram and Discord connect flows use dedicated connector credentials

The easiest way to stay safe is to keep those boundaries sharp.

Keep API keys server-side only

Treat X-Hilt-Key as a backend credential.

Best practice:

  • create the key in the dashboard or merchant app
  • store the raw key in a secret manager
  • only use it from your backend, job runner, or support tooling
  • rotate it when people or deployments change

Do not:

  • embed it in browser JavaScript
  • ship it inside mobile apps
  • paste it into client-side analytics or support widgets

Use JWTs only for user-facing sessions

JWTs are the right choice for:

  • merchant app login
  • browser-side workspace actions
  • account settings
  • support and billing actions inside the hosted app

API keys are the right choice for:

  • product automation
  • membership lookup from your backend
  • receipt retrieval in support tooling
  • buyer handoff creation from your own bot or app

Verify webhooks against the raw body

Hilt expects provider signatures to be verified against the raw request body, not a re-serialized JSON payload.

Current webhook secrets in the Hilt stack:

  • helius_auth_secret for helius-signature
  • stripe_webhook_secret for Stripe-Signature
  • checkout_telegram_webhook_secret for Telegram’s webhook secret header
  • connector_handoff_secret for trusted connector handoff calls

If you proxy or transform incoming webhook bodies before verification, signature validation can fail.

Lock down OAuth callbacks

Keep local and production callback URLs explicit and minimal.

Best practice:

  • register only the callback URLs you actually use
  • separate local and production callbacks cleanly
  • use the app domain for browser sign-in flows
  • keep the API domain for provider callbacks that resolve on the backend

Keep connector secrets out of merchant-facing code

Telegram connect, Discord connect, and signed buyer handoff flows should be driven by:

  • the shared Hilt connector flow
  • a merchant-owned backend
  • or a bot/app that already knows who the buyer is

The browser should never hold the secret that can mint trusted handoff tokens.

Treat payment retries carefully

For buyer-facing flows:

  • keep the original payment_id
  • keep the original tx_signature
  • use GET /v1/payments/{payment_id} during confirmation
  • only ask the buyer to pay again if the original session actually failed

This avoids duplicate payment attempts and confused support trails.

Rate limits and quotas

Hilt exposes standard rate-limit headers on /v1/* routes:

  • X-RateLimit-Limit
  • X-RateLimit-Remaining
  • X-RateLimit-Reset
  • Retry-After

Treat the headers as the source of truth instead of hard-coding assumptions in your client.

Current plan-level API key quotas from the merchant plan model:

PlanMax API keys
Free10
Starter25
Growth50
Scale100
EnterpriseUnlimited by default contract

Watch key activity and rotate with intent

Hilt stores API key usage summaries and recent activity.

Use that for:

  • spotting unexpected routes
  • confirming whether an integration is still alive
  • deciding when to revoke an old key

Good rotation moments:

  • deployment changes
  • contractor offboarding
  • bot or worker replacement
  • suspicious or unexplained activity

Prefer the app for sensitive setup

The merchant app is the safest place to:

  • create keys
  • configure billing
  • set checkout branding
  • set support and delivery defaults

The API is strongest once the workspace is already shaped correctly.

Incident posture

If something looks wrong:

  1. stop issuing new keys or rotate the affected one
  2. confirm payment state from receipts and memberships, not just wallet screenshots
  3. inspect support history and key activity
  4. re-run delivery only through the dedicated retry route
  5. escalate billing-only issues through Stripe history, not buyer payment records

That keeps the merchant operating trail intact while you fix the problem.