{
"id": "pet.trezy.collectCoins",
"defs": {
"main": {
"type": "procedure",
"input": {
"schema": {
"type": "object",
"required": [
"amount"
],
"properties": {
"amount": {
"type": "integer",
"minimum": 1
}
}
},
"encoding": "application/json"
},
"output": {
"schema": {
"type": "object",
"required": [],
"properties": {
"error": {
"type": "string",
"description": "Present instead of collected/lastUpdated/balance when the claim was refused for an expected reason. A stable machine code the client branches on — add codes, never rename them. Its presence is why nothing here is `required`: a refusal carries none of the three, and requiring even one would fail response validation and turn the refusal back into a 500.",
"knownValues": [
"invalid-amount",
"insufficient-accrual",
"wallet-unsigned",
"wallet-invalid"
]
},
"balance": {
"type": "integer"
},
"message": {
"type": "string",
"description": "A sentence to show the player, accompanying `error`. Free to reword; do not branch on it."
},
"collected": {
"type": "integer"
},
"lastUpdated": {
"type": "string",
"format": "datetime",
"description": "THE ACCRUAL ANCHOR, NOT A WRITE TIME. Income is measured FROM this moment, so it is where the next payout starts rather than when this record was last saved. The two usually coincide, because a settle banks everything and moves the anchor to now — but a PARTIAL collect advances it only as far as the coins actually taken, leaving it EARLIER than the write that produced it. Reading it as \"when the wallet was last written\" has already cost this project one wrong diagnosis. It is deliberately NOT renamed: it sits inside the signed payload, so changing it would invalidate every wallet attestation ever issued and require rewriting records in players' repos. This is the anchor AFTER the collect — where the next window starts."
}
}
},
"encoding": "application/json"
}
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1
}