Skip to main content

Use sandbox keys for all development

Never develop against production. Use edp_test_ sandbox keys during development, CI, and staging.
# .env.local
EDPIRE_API_KEY=edp_test_<your-sandbox-key>

# .env.production
EDPIRE_API_KEY=edp_live_<your-production-key>
See Sandbox to create your first sandbox key and understand what’s pre-seeded.

Test the complete flow end-to-end

Before going live, run through the full learner journey with your chosen integration tier:
  1. Mint an embed token server-side with your sandbox key
  2. Mount the SDK with the token in a test page
  3. Complete the assessment inside the embed
  4. Verify onComplete fires and result.submission_id is present
  5. Fetch the submission to confirm results are stored
  1. Fetch a sandbox assessment with flattenAssessment()
  2. Render each step with EdpireQuestion
  3. After each answer, call your /check proxy — verify feedback shape matches the question type
  4. Confirm correct: true feedback is returned for known-correct answers
  5. After all questions, submit and verify the full submission record
  1. Fetch assessment content with client.getAssessment()
  2. Build a minimal answer payload matching the AssessmentAnswers structure
  3. Call client.submit() and inspect exercise_results[].question_results[].feedback
  4. Verify error responses for malformed answers (should return 422)
  5. Verify the submission.graded webhook fires (check the sandbox echo viewer)

Test webhooks locally

Your local server isn’t reachable from Edpire’s servers directly. Use ngrok or Cloudflare Tunnel to expose a local port:
ngrok http 3000
# Forwarding: https://abc123.ngrok.io -> http://localhost:3000
Register that URL as a sandbox webhook:
curl -X POST https://app.edpire.com/api/v1/webhooks \
  -H "Authorization: Bearer edp_test_<your-sandbox-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://abc123.ngrok.io/webhooks/edpire",
    "events": ["submission.graded"]
  }'
Store the secret from the response. Complete an assessment in the sandbox — the webhook fires to your local handler in real time.
You can also skip running a receiver entirely and use the sandbox echo viewer (Settings → Sandbox → Events) to inspect payloads. It captures all sandbox webhook events automatically.

Verify signature verification

Confirm your signature verification logic rejects tampered requests:
// Send a request with a wrong signature — your handler should return 401
const fakeSignature = "sha256=0000000000000000000000000000000000000000000000000000000000000000"
const res = await fetch("http://localhost:3000/webhooks/edpire", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Edpire-Signature": fakeSignature,
  },
  body: JSON.stringify({ event: "submission.graded", submission_id: "test" }),
})
assert(res.status === 401)

Test idempotency

The same webhook event can be delivered more than once. Your handler must be safe to call twice with the same payload:
  1. Complete a sandbox assessment — your handler processes the submission.graded event
  2. Replay the exact same POST body to your webhook handler (copy from ngrok’s request log or the echo viewer)
  3. Verify your database has exactly one record, not two
// Good — idempotent check before write
if (await db.submissionExists(req.body.submission_id)) {
  return res.sendStatus(200) // already processed
}
await db.saveSubmission(...)

Test error paths

Don’t only test the happy path. Verify your integration handles:
ScenarioHow to trigger
Invalid API keyUse a wrong or revoked key — expect 401
Missing scopeUse a key without read:results on a submissions call — expect 403
Assessment not foundRequest a non-existent assessment ID — expect 404
Max attempts exceededSubmit the same assessment more than its allowed attempt count — expect 409
Rate limitSend 101+ requests per minute — expect 429 with Retry-After header

Pre-production checklist

Before switching to production keys:
  • All API calls go through your server — no edp_live_ keys in the browser
  • return_url and back_url are on registered Allowed Origins
  • Webhook signature verification is enabled and tested
  • Idempotency check is in place for submission.graded
  • Error responses are handled (retry on 429/500, alert on persistent 5xx)
  • learner_ref is your stable internal user ID — not email, not username
  • EDPIRE_API_KEY is in environment variables, not committed to source control
See the full Security checklist before going live.