Developers › File formats Beta
Review return
Format textshelf-review-return, version 1. Written by the Mac app, read by
the web. Status: v1, beta. It keeps to
the rules every format follows.
A review return carries one reviewer's scores from the Mac app back to the web
shelf a review packet came from. The reviewer uploads it on
the page the packet's source.uploadUrl names. It carries no identity: the web
applies every row as the signed-in reviewer who uploads it.
The file
{
"formatVersion": 1,
"kind": "textshelf-review-return",
"source": {
"host": "textshelf.com",
"contestId": 42
},
"generatedAt": "2026-09-24T09:12:00.000Z",
"app": {
"version": "1.1 (52)"
},
"reviews": [
{
"sourcePk": 91,
"nativeReviewId": "5C0F7E2A-4D1B-4E7A-9C36-0A1B2C3D4E5F",
"modifiedAt": "2026-09-23T21:40:11.000Z",
"values": {
"web-criterion-3f2a9c1e-7b44-4d0a-9d4e-2b8f1a6c5e01": 4,
"web-move-forward": 3,
"web-assessment": 4,
"web-notes": "Strong opening; pacing flags in the middle third."
},
"baseline": {
"web-assessment": 4,
"web-notes": "Strong opening."
}
}
]
}
source— copied from the manifest. The web refuses a file whosehostisn't itself or whosecontestIdisn't the page's.reviews— one per entry the reviewer reviewed on the Mac.values— the Mac review'sweb-*scores, keyed by field id. Keys the manifest didn't define are refused. A field the reviewer cleared is absent.baseline— copied from the manifest entry, unchanged.- Identity — deliberately absent. Every row is applied as the signed-in user.
How the web applies a row
For each field f in values ∪ baseline, with mac = values[f],
base = baseline[f] and web = the field's current database value:
| Condition | Result |
|---|---|
mac == base |
Not written. |
mac == web |
Not written: already there. This is also why uploading the same file twice is harmless. |
mac != base and web == base |
Written. |
mac != base and web != base and web != mac |
Written; the replaced web value goes in ReviewImport; the review is flagged "edited on the web and the Mac". |
- A field cleared on the Mac (in
baseline, absent fromvalues) clears it on the web: a criterion'sRubricScoreis deleted, and the others are set to null or empty. - When a conflict is declared: a non-empty
web-coisetshas_coiandcoi_description, and no other field of that row is applied. - Refused rows are reported with a reason. The rest of the file still applies. The reasons:
- the entry isn't in the contest;
reviewer_may_openfails;- the field is unknown or refers to an inactive criterion;
- a value is out of range or not among the choices.
This specification is licensed under CC BY 4.0, and its example and schema files under the MIT licence. Anyone may implement these formats in their own software. CC BY 4.0