Documentation
API REFERENCE

Rate Limits

Every developer-facing limit in one place: per-minute request limits on the LRS, request and document size caps, portal action limits, and the storage quotas behind uploads. All of them are set well above what a real game or classroom generates — if you are hitting one, batch more or contact developers@edu.games.

LRS endpoints (lrs.edu.games)

EndpointLimitKeyed byNotes
POST /xapi/statements120 / mincredentialUp to 250 statements per request; body ≤ 2 MB. Its own bucket, separate from PUT.
PUT /xapi/statements120 / mincredentialOne statement per request; body ≤ 2 MB. Its own bucket, separate from POST.
GET /xapi/statementsno per-minute limitlimit query param capped at 500 rows per page (default 50).
PUT /xapi/activities/state120 / mincredential + actorDocument ≤ 512 KB.
GET /xapi/activities/state240 / mincredential + actor
DELETE /xapi/activities/state120 / mincredential + actor
GET / PUT / DELETE /xapi/activities/profile120 / min (shared)credential + actorAll three methods share one bucket. Document ≤ 512 KB.
GET / PUT / DELETE /xapi/agents/profile120 / min (shared)credential + actorAll three methods share one bucket. Document ≤ 512 KB.
GET /xapi/agents, GET /xapi/activities, GET /xapi/aboutno per-minute limit

“Credential” is the per-game xAPI credential, whether you authenticate with its key/secret or with a launch token minted for it. “Credential + actor” means each learner session gets its own bucket for document endpoints, so one busy student cannot starve another.

What a 429 looks like

LRS routes answer with the standard xAPI error shape and CORS headers; there is no Retry-After header. Each bucket is a fixed 60-second window that starts on the first request and resets in full when it expires, so the longest you ever need to wait is one minute.

http
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-Experience-API-Version: 1.0.3
Access-Control-Allow-Origin: *

{"error":"Rate limit exceeded"}

Other rejections you may see on the statements endpoints, for completeness:

http
413  {"error":"Too many statements in one request (max 250)"}
413  {"error":"Request body too large"}          // body over 2 MB (512 KB for documents)
401  Unauthorized                                 // missing/invalid Authorization

The limiter counts requests per running server instance rather than globally, so it blunts scripted abuse without being a precise global meter — treat the numbers as the floor of what you are guaranteed, not a hard ceiling to tune against.

Retry guidance

  • Batch instead of firing per event. Queue statements and POST every 5–10 seconds; the official SDK does this (5 s, or whenever 20 are queued) and retries 429/5xx responses automatically.
  • Retry the identical batch, ids included. The LRS dedupes by statement id, so a retried batch that partially landed still succeeds — see Sending Statements.
  • Back off. Wait a few seconds and grow the delay on repeated 429s; there is nothing to gain from hammering inside the same window. Drop 4xx errors other than 429 — they mean the batch is malformed, and resending it will not help.
  • Keepalive flushes are size-bound anyway. Browsers cap keepalive bodies at ~64 KB, so a final pagehide flush should carry at most ~20 statements — nowhere near the request limit.
  • Upload cap hit? The daily build-upload budget is about iteration churn, not storage: debug in the sandbox rather than re-uploading, and the budget resets at 00:00 UTC.

Developer portal actions

ActionLimitKeyed byNotes
Request an upload URL (any file type)60 / mindeveloperHTTP 429 {"error":"Too many requests"}.
Game-build upload URLs (new build or replacement, browser or desktop)20 / UTC daydeveloperChecked last, after size/quota validation, so a rejected request never spends a slot. Resets at 00:00 UTC. HTTP 429 with a message linking to the packaging docs.
Finalize an upload (Save as Draft)10 / mindeveloperReturns the error "Too many requests. Please wait a moment and try again." in the form.
Open a sandbox session10 / mindeveloperReturns "Too many sandbox sessions requested…" in the form.
Studio contact form (public, studios.edu.games)5 / 10 minsender IPAlso protected by a CAPTCHA.

Storage and game quotas

QuotaLimit
Games per developer account (drafts included)20
Total build storage per developer account25 GB
Single game build (browser zip or desktop package)1 GB
Entries in a browser zip (files + folders)10,000
Per-file decompression ratio in a browser zip100:1
Gallery images per game10, each ≤ 5 MB
Teaching-note documents per game5, each ≤ 10 MB
Studio logo≤ 5 MB

Game count and storage are checked when you request a build upload URL; exceeding either returns a 400 with a message linking to the rule. Storage counts each game’s live build plus staged or in-grace desktop builds. Layout, entry-count and zip-bomb rules are explained in Packaging Your Game; build replacement and archiving in Review & Game Lifecycle.

ActivitiesSDK & Libraries