Data export

A person downloads everything Gemmein holds about them.

What it is. A "download my data" button for the people in your app. One call returns everything a person holds in your app, so you can meet a request for their data (GDPR right of access and portability) without building it.

What it does.

  • Collects. g.account.export() returns one JSON document: their profile; the records they wrote or that name them, grouped by collection; their likes and flags; their files as download links; purchases, plan, credits and the credit ledger; access grants; AI calls and runs; the emails your app sent them; their conversations with your support inbox; their sessions, with the IP address each signed in from and was last seen on, and their sign-ins, sign-outs, checkouts started and exports, each with its time and IP address. An address is there for 30 days.
  • Opens with a cover. The about object at the top says what the document is, your app's name, when it was generated, whether the person or you produced it, the sections it holds (their caps are in limits), what it leaves out and why (your tool prompts, your team's identities, other people's data, and on the person's own copy the notes your team wrote, which they ask you for), your Terms of Service link if Payments has one (termsUrl), your support address if you have one (ownerContact), and one line on their rights: they can ask you to correct or delete their data.
  • Stays bounded. Each section has a cap: 5,000 records; 1,000 files, likes and flags, purchases and AI calls; 199 runs and credit ledger lines; 99 emails; 500 sessions and sign-ins; 200 support conversations. Records, AI calls, runs and support messages together stop at 25 MB. A section is named in limits.truncated only when something in it was left out. Sign-ins are read from the newest 10,000 entries of the person's account history, and named when the history runs longer.
  • Follows your rules. It holds what that person may read under your safety rules, and nothing another person keeps private: no tool prompt of yours, no note you wrote, no sender address on your replies. People named on a group message appear as ids, as they do on the record.
  • Works from the dashboard. On a customer's page, Export their data downloads the same document, plus ownerNotes: the notes your team wrote about the person (a comp's note, an access grant's note, the reason your server or an automation gave on a credit change), with when each was written and never who wrote it. The notes stop at 199 (limits.caps.ownerNotes), and ownerNotes is named in limits.truncated when one was left out. They are flagged for review: they are usually the person's data, but you may withhold one case by case, for example where it reveals someone else. In Live it asks for a code from your email first, and the export is recorded on their history: who exported it, and when.
  • Has a limit. A person exports their own data once every 30 days, counted from their last export; an attempt that fails or is never handed out does not count. You export a person's data from the dashboard once a day, counted from the last export, on a separate count, so you can always answer a formal access request.

What it does not do.

  • Keep file links. A private file's link works for 5 minutes; a file in a collection anyone can read keeps its permanent public link. The file stays in your app.
  • Run from your server with a secret key. A person exports their own data, or you export it from the dashboard.

When you need something else.

  • To delete the data rather than copy it: g.account.delete(), below.

Example. A settings screen with a download button.

const data = await g.account.export()
const file = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" })
// hand it to the browser as my-data.json

What happens if…

If…What happensWhat you do
A person runs account.export()One JSON document of their data comes back, and the export is on their history in LogsSave it as a file for them
A collection is locked to a plan they no longer hold, or a rule hides it from themThose records and files are left out of the exportNothing
A section passes its cap, or the 25 MB of text is reachedThe export stops there, and limits.truncated names each section that was cutNothing
They export again within 30 days of their last export429 export_rate_limited with resetAt, a sentence giving the date and saying they can still ask you for their data, and ownerContact: your support address, or null when you have none. The refused export is in Logs. Your exports from the dashboard count separately, once a day per personShow the message; try again after resetAt
They ask again while their export is still being prepared429 export_rate_limited at once, with resetAt a couple of minutes away and a sentence saying an export is already being prepared. One export of a person is prepared at a time on each side, theirs and the dashboard'sWait for the first to arrive, or try again after resetAt
The export's row in Logs cannot be written503 audit_unavailable, and nothing is handed outTry again
A private file's link in the export has expiredThe link no longer opens after 5 minutes. The file is unchanged. A file in a collection anyone can read has a permanent link and no expiryExport again, or open the file in the app
account.export() is called while signed out401 authentication_requiredSign the person in first
You export them from the Customers pageThe same document downloads. In Live, it asks for a code from your email first. Logs shows who exported it and whenNothing
The person has deleted their accountThere is nothing to export: their own export is 401, and the Customers page no longer lists themNothing
Was this page helpful?

Last updated