Skip to main content

HTTP status codes

StatusMeaningAction
400Bad request — validation error, invalid parametersFix the request
401Invalid, expired, or missing API keyCheck your API key
403Missing required scopeAdd the needed scope to your API key
404Resource not found or not in your orgVerify the ID
409Conflict — max attempts, duplicate webhook, etc.Check business logic constraints
422Grading failed — invalid answer formatCheck answer structure matches question type
429Rate limit exceededWait for Retry-After seconds, then retry
500Internal server errorRetry after a short delay

Retry strategies

For transient errors (429, 500, 502, 503, 504):
import { EdpireError } from "@edpire/sdk/client"

async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn()
    } catch (err) {
      if (err instanceof EdpireError && [429, 500, 502, 503, 504].includes(err.status)) {
        if (attempt === maxRetries) throw err
        const delay = Math.min(1000 * Math.pow(2, attempt), 30000)
        await new Promise((r) => setTimeout(r, delay))
        continue
      }
      throw err // non-retryable
    }
  }
  throw new Error("unreachable")
}

const assessment = await withRetry(() => client.getAssessment("id"))

Production security checklist

Before going live, verify each item:
Never expose edp_live_ keys to the browser or commit them to version control. Use environment variables.
Use POST /embed/token to mint short-lived tokens for browser-side rendering. These expire in 1 hour and are single-use.
Reject any incoming webhook that fails HMAC-SHA256 verification. Use timingSafeEqual to prevent timing attacks.
Each API key has only the scopes it needs. A key that only reads data should not have write:submissions.
Only your production domains are in the embed allow list. Remove localhost/staging before launch.
Never let the client construct or choose the learner_ref. Always generate it server-side from your auth session.
Duplicate events do not cause duplicate records. Check submission_id uniqueness before writing.
Your code respects Retry-After headers and backs off on 429 responses.
API responses never contain answer keys. Feedback contains only correctness signals — do not attempt to reverse-engineer correct answers from it.
Webhook URLs must use HTTPS. HTTP is only permitted for localhost during development.