- Guides
- Recipes
Batch save
Create several records from one request.
Trigger: xrpc.procedure:<nsid>. Needs: happyview-record.
local json = require("internal.json")local record = require("happyview.record")
function handle(input, ctx) local uris = {} for _, item in ipairs(input.items) do local ref = record.create(ctx.collection, item) uris[#uris + 1] = ref.uri end return { uris = json.to_array(uris) }endimport record from "happyview.record";
export default async function handle(input, ctx) { const uris = []; for (const item of input.items) { const ref = await record.create(ctx.collection, item); uris.push(ref.uri); } return { uris };}import record from "happyview.record";
interface Input { items: Record<string, unknown>[];}
export default async function handle(input: Input, ctx: { collection: string }) { const uris: string[] = []; for (const item of input.items) { const ref = await record.create(ctx.collection, item); uris.push(ref.uri); } return { uris };}How it works
Section titled “How it works”- Iterate over
input.itemsand create each one withrecord.createonhappyview.record. - Collect the resulting AT URIs and return them. In Lua,
json.to_arraykeepsurisa JSON array whenitemsis empty.
Writes happen one at a time, in order. If one fails, the records before it exist and the ones after it don’t, and the app gets an error response: a 500, or a 401 when the caller’s PDS session has ended. To report partial progress instead, wrap record.create in pcall (Lua) or try/catch (JavaScript and TypeScript).
The DPoP proof is signed per request; an app built on the HappyView SDK gets this from its session.
const response = await fetch("http://127.0.0.1:3000/xrpc/xyz.statusphere.batchCreate", { method: "POST", headers: { "X-Client-Key": CLIENT_KEY, Authorization: `DPoP ${ACCESS_TOKEN}`, DPoP: DPOP_PROOF, "Content-Type": "application/json", }, body: JSON.stringify({ items: [ { text: "First", createdAt: "2025-01-01T00:00:00Z" }, { text: "Second", createdAt: "2025-01-01T00:01:00Z" }, ], }),});const data = await response.json();const response = await fetch("http://127.0.0.1:3000/xrpc/xyz.statusphere.batchCreate", { method: "POST", headers: { "X-Client-Key": CLIENT_KEY, Authorization: `DPoP ${ACCESS_TOKEN}`, DPoP: DPOP_PROOF, "Content-Type": "application/json", }, body: JSON.stringify({ items: [ { text: "First", createdAt: "2025-01-01T00:00:00Z" }, { text: "Second", createdAt: "2025-01-01T00:01:00Z" }, ], }),});const data = await response.json();let response = client .post("http://127.0.0.1:3000/xrpc/xyz.statusphere.batchCreate") .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {access_token}")) .header("DPoP", dpop_proof) .json(&serde_json::json!({ "items": [ { "text": "First", "createdAt": "2025-01-01T00:00:00Z" }, { "text": "Second", "createdAt": "2025-01-01T00:01:00Z" } ] })) .send() .await?;clientKey := "hvc_..." // your API client keyaccessToken := "..." // DPoP access tokendpopProof := "..." // DPoP proof JWT
body := `{ "items": [ { "text": "First", "createdAt": "2025-01-01T00:00:00Z" }, { "text": "Second", "createdAt": "2025-01-01T00:01:00Z" } ]}`req, err := http.NewRequest("POST", "http://127.0.0.1:3000/xrpc/xyz.statusphere.batchCreate", bytes.NewBufferString(body))if err != nil { log.Fatal(err)}req.Header.Set("X-Client-Key", clientKey)req.Header.Set("Authorization", "DPoP "+accessToken)req.Header.Set("DPoP", dpopProof)req.Header.Set("Content-Type", "application/json")resp, err := http.DefaultClient.Do(req)if err != nil { log.Fatal(err)}defer resp.Body.Close()curl -X POST http://127.0.0.1:3000/xrpc/xyz.statusphere.batchCreate \ -H "X-Client-Key: $CLIENT_KEY" \ -H "Authorization: DPoP $ACCESS_TOKEN" \ -H "DPoP: $DPOP_PROOF" \ -H "Content-Type: application/json" \ -d '{ "items": [ { "text": "First", "createdAt": "2025-01-01T00:00:00Z" }, { "text": "Second", "createdAt": "2025-01-01T00:01:00Z" } ] }'Use case
Section titled “Use case”Use a batch save when a single user action should create several records, such as importing data or finishing a multi-step form.
© HappyProto

