Procedure: Upsert a Record
Create a new record, or update an existing one if the client provides its rkey.
Lexicon type: procedure
function handle()
local rkey = input.rkey or TID()
local uri = "at://" .. caller_did .. "/" .. collection .. "/" .. rkey
local r = Record.load(uri)
if r then
-- Update existing record
r.status = input.status
r.updatedAt = now()
r:save()
else
-- Create new record
r = Record(collection, {
status = input.status,
createdAt = now(),
updatedAt = now(),
})
r:set_rkey(rkey)
r:save()
end
return { uri = r._uri, cid = r._cid }
end
How it works
- Use the client-provided
input.rkeyif present, otherwise generate a newTID(). This means omittingrkeyalways creates, while providing one enables updates. - Build the AT URI from the caller's DID, the target collection, and the rkey, then try to load it with
Record.load. - If the record exists, update its fields and save. Since
_uriis already set,r:save()callsputRecord. - If it doesn't exist, create a new record, set the rkey explicitly with
r:set_rkey(), and save. This callscreateRecordwith the specified rkey.
Usage
# Create: no rkey, so a new TID is generated
curl -X POST http://localhost:3000/xrpc/xyz.statusphere.setStatus \
-H "X-Client-Key: $CLIENT_KEY" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "status": "hello" }'
# → { "uri": "at://did:plc:abc/xyz.statusphere.status/3abc123", "cid": "bafyrei..." }
# Update: pass the rkey back to update the same record
curl -X POST http://localhost:3000/xrpc/xyz.statusphere.setStatus \
-H "X-Client-Key: $CLIENT_KEY" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "rkey": "3abc123", "status": "updated" }'
# → { "uri": "at://did:plc:abc/xyz.statusphere.status/3abc123", "cid": "bafyrei..." }
Use case
This is useful when the client knows whether it's creating or editing, but you want a single endpoint for both. The client omits rkey for new records and includes it when editing an existing one. The rkey from the initial create response acts as the record's stable identifier for future updates.