Sending feedback from inside a game
The contract for a game that lets its players report a bug, send an idea, or complain. Both of this site's games use it: TGSC (Touching Grass Simulator Coop, on PC) and Touch Grass (on Android). They are separate games with similar names, and each has its own address and its own queue.
One call, one form, and the site sorts it. There is no account and no token - a game cannot ask a player to sign in to a website before telling you the game crashed.
Base address: https://dasmaffin.com.
Send one
POST /TouchGrass/api/report (Touch Grass, Android)
POST /Tgsc/api/report (TGSC, PC)
Content-Type: multipart/form-data
The address decides the queue. Nothing in the body says which game this is; the site stamps it from the endpoint you posted to. A client cannot file into the other game's queue, by accident or otherwise.
Both addresses are the same endpoint under a different name: a module on this site declares that it
takes feedback, and the site answers POST /{module}/api/report for it.
A third game would appear here without a line of new intake code, and would behave exactly as these
two do.
The fields
| Field | Touch Grass | TGSC | Meaning |
|---|---|---|---|
playerId |
required | - | Who is sending. The Unity Gaming Services player id, the same one the save is filed under |
steamId |
- | required | Who is sending. A SteamID64, digits only |
summary |
required | required | One line. Up to 300 characters |
description |
required | required | What happened, in their words. Up to 8,000 |
kind |
optional | optional | Bug, Idea or Other. Anything else becomes Other |
playerName |
optional | optional | What they call themselves in game. A label, not identity |
build |
optional | optional | Your version string |
scene |
optional | optional | Where they were - the screen or level |
facts |
optional | optional | Device, OS, settings, anything else worth knowing. Up to 8,000 |
edition, role, world |
- | optional | PC game concepts; leave them out |
Anything longer than its limit is cut, not refused - a report is worth having with a truncated log.
summary and description are both required. An empty report costs nothing to send, arrives
looking like feedback, and can only be answered by guessing.
Attachments
One field per kind, and each takes as many files as you like. The field name says what a file
is; the file name is only a label for whoever reads the report afterwards. A part sent as logs
carrying whatever.json is a log. A part sent as notes carrying screenshot.png is not a
picture.
| Send it as | What it is | Where it appears on the report |
|---|---|---|
images |
Pictures | Shown, full size on click |
logs |
Log files | The first is shown as text on the page; every one is downloadable |
charts |
Measurements over time | Plotted - see charts. Also downloadable |
saves |
A save or world file | Under Files, as a download |
benchmarks |
A finished benchmark run | Shown as text |
files |
Anything else | Under Files, as a download |
Repeat a field to send several: two parts both named logs are two logs, and there is no numbering
scheme to follow. Multipart allows a repeated field name, so nothing has to be invented per file.
curl -X POST https://dasmaffin.com/TouchGrass/api/report \
-F "playerId=..." -F "summary=..." -F "description=..." \
-F "logs=@session.json;type=application/json" \
-F "logs=@previous-session.json;type=application/json" \
-F "images=@shot1.png;type=image/png" \
-F "images=@shot2.png;type=image/png" \
-F "charts=@metrics.json;type=application/json"
A field name that is not on that list lands under Files, as a plain download. Nothing is guessed from the file's name or its content: a file the site was not told the kind of is one it will not describe. It used to guess "picture", which put a game's second log in the Pictures section as a broken image.
The older names still work, because both of this site's games send them and neither should
break before it ships a new build: shot, log, metrics, save, benchmark. That is the whole
list - exactly what those two emit, not a set of spellings that might be accepted. Anything new
should use the fields in the table, which are the kinds themselves.
Set Content-Encoding: gzip on a part and it is unpacked before it is stored, so what somebody
opens is the plain thing. Compress for the upload's sake, not for the reader's.
Charts
A file part named metrics is plotted on the report's page. Its shape is its own document:
charts.
What comes back
{ "id": 412 }
| Code | Meaning |
|---|---|
200 |
Stored. The id is the report's |
400 |
No sender id, or a missing summary or description |
403 |
That player is barred from sending. Body: {"banned":true,"reason":"..."} - show the reason |
413 |
Everything together came to more than 16 MB |
429 |
More than 12 reports from that player in the last hour |
A 403 is worth handling properly: the reason is written for the player and is the only explanation
they will get. Touch Grass has no ban list today, so it will not see one - the code is documented
because the endpoint can answer it the moment there is one, and a client that treats an unknown
status as "it worked" is a client that silently loses reports.
An example
curl -f -X POST \
-F "playerId=Ax7Bq2Kd9Lm4Np6Rs8Tv0Wx2Yz4A" \
-F "summary=Garden resets after closing the app" \
-F "description=Planted three plots, closed the app from recents, came back and the garden was empty." \
-F "kind=Bug" \
-F "playerName=Someone" \
-F "build=1.0.4" \
-F "scene=Garden" \
-F "facts=Pixel 7a, Android 15, English" \
-F "log=@player.log;type=text/plain" \
https://dasmaffin.com/TouchGrass/api/report
Reading them back
There is a private read API for programs on the project's side - not for game clients. It needs a private API key, and so does its documentation: reading.
What happens to it
It lands in that game's queue on this site, where somebody reads it, can answer it, and can close it. Reports are deleted after 120 days.
The player id is what the game claimed, not something this site proved, and it is treated that way: it is good for grouping one person's reports together and for answering them, and for nothing else. Send the id you already have rather than inventing one per report, or two reports from the same person cannot be recognised as such.
Nothing here needs an account, on either side. What a player types is what arrives.