A player tells you something went wrong, or has an idea, from inside the game. No sign-in needed: a game cannot ask somebody to sign in before telling you it crashed. When the player is signed in, send their session token as usual and the report is theirs - only then can they read your answers in the game. Nothing in the form can say who sent it; only the token can.
POST /reports
Authorization: Bearer mgds_... (optional)
Content-Type: multipart/form-data
| Field | Meaning | |
|---|---|---|
summary |
required | One line. Up to 300 characters |
description |
required | What happened, in their words. Up to 8,000 |
kind |
optional | Bug, Idea or Other. Anything else is Other |
build |
optional | Your version string |
scene |
optional | Where they were: a scene, a screen, a level |
playerName |
optional | A name, when nobody is signed in. A signed-in player's own name is used instead |
Longer text is cut, not refused. Answers 201 { "id": 12, "playerId": "..." }. playerId is
null when no working session came with it: the report is still taken, as nobody's, so a session
that expired a minute ago never costs you a crash report. If you want it to be theirs, refresh first.
Attachments
The field a file is sent under says what it is. Each field takes as many files as you send; repeat it for several. The file's name is only a label.
| Field | What it is | On the dashboard |
|---|---|---|
logs |
A log: { "entries": [ ... ] } as below, or plain text |
A table you can filter by level, each line's stack folded under it |
images |
PNG, JPEG, GIF or WebP | Shown |
videos |
MP4 or WebM | Played |
graphs |
Measurements over time, in the charts format | Plotted |
info |
A JSON object of facts: the device, the settings, anything | A table, nested names joined with dots |
| anything else | A file | A download |
A log made of entries:
{ "entries": [
{ "frame": 1520, "at": 31.4, "level": "Error", "message": "NullReferenceException: ...", "stack": "at Map.Open () ..." },
{ "frame": 1521, "at": 31.4, "level": "Warning", "message": "Retrying" }
] }
level is Unity's: Log, Warning, Error, Exception, Assert. frame, at (seconds) and
stack are optional. Info:
{ "device": { "model": "Pixel 7a", "os": "Android 15", "memoryMb": 8192 }, "language": "en" }
Pictures and videos of any other type are kept and offered as a download, not shown: what the game
says a file is cannot be trusted to show safely. Executables are refused. Set
Content-Encoding: gzip on a part and it is unpacked before it is kept.
One report carries up to 64 MB, unpacked. Attachments over 2 MB are kept on our file storage, encrypted. 12 reports an hour per signed-in player, or per address for everybody else.
Answers, in the game
A signed-in player's own reports, and the conversation on them:
GET /me/reports { "unread": 1, "reports": [ { "id", "kind", "summary", "receivedAt", "open", "unread", "messages" } ] }
GET /me/reports/{id} the report and its messages; this is what marks your answers read
POST /me/reports/{id}/messages { "body": "Still happens on 1.2.4" }
POST /me/reports/{id}/close
{ "id": 12, "kind": "Bug", "summary": "...", "description": "...", "receivedAt": "...", "closedAt": null, "open": true,
"messages": [ { "fromDeveloper": true, "body": "Which device?", "writtenAt": "..." } ] }
unread counts your answers written after they last opened it, which is what a badge wants. A
closed report takes no more messages (409) until you open it again on the dashboard. Text only:
nothing here hands attachments back.
On the dashboard
Under the project's Reports: the queue, each report with everything it carried, your answers, close and open again, delete. Its settings say how many days reports are kept (or until you delete them) and whether you are emailed when one arrives.