Which Sume Format run receipt fields to store in your database

Store id, format, status, created_at, finished_at, model, usage.debited_usd_micros, output and artifacts. Fetch the rest, because URLs and expires_at change.

4 min readSume
All posts

Keep the run id, the Format identity, status, the three timestamps, model, the cost in usage.debited_usd_micros, and the output and artifacts you show to users. Do not store the poll URLs or expires_at as facts, because those describe the live run.

A receipt is large, and most of it is useful only while the run is in flight.

Columns worth having

Field names are from the Runs and results page (read 2026-10-03).

Format run receipt fields and whether to persist them (read 2026-10-03)
FieldStore?Why
idYesPrimary key; webhooks carry it as request_id
format.id, format.slug, format.versionYesWhich Format version produced the output
statusYescompleted, failed, canceled or skipped once terminal
created_at, started_at, finished_atYesLatency and ordering
modelYesThe orchestrator id that actually ran
usage.debited_usd_microsYesThe real cost of the run
output, output_error, artifactsYesWhat the user gets; copy media you must keep
status_url, result_url, events_url, cancel_urlNoDerivable from id
expires_at, next_action, cancelableNoOnly true while the run is live

Two traps

usage is null when spend could not be read, which is different from zero, so store null as null. Older receipts also leave the wallet fields null. See the cost helper for totalling.

Media URLs on media.sume.com are durable but public to anyone holding the URL. If you show them to your own customers, copy the file or proxy it.

import json, sqlite3

db = sqlite3.connect("runs.db")
db.execute("create table if not exists runs(id text primary key,"
           " fmt text, status text, model text, micros integer, body text)")

def save(run):
    u = run.get("usage") or {}
    db.execute("insert or replace into runs values(?,?,?,?,?,?)",
               (run["id"], run["format"]["slug"], run["status"],
                run.get("model"), u.get("debited_usd_micros"),
                json.dumps({"output": run.get("output"),
                            "artifacts": run.get("artifacts")})))
    db.commit()

save({"id": "run_1", "format": {"slug": "teaser"}, "status": "completed",
      "model": "gpt-6-sol", "usage": None, "output": {}, "artifacts": []})

Keep the raw receipt too

If storage is cheap, keep the terminal receipt as JSON next to the columns. Fields are added over time, and a raw copy lets you backfill without calling the API for runs that may have aged out.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume