Exporting your data
Everything your org holds, on request, in two calls. Including the raw observations behind every rate โ because handing you only our summary would be handing you our conclusion instead of your evidence.
The full export
GET /me/export
authorization: Bearer <your-token>
Returns one JSON document containing:
- account and organization โ your own name, email, role, join date, and the org record. A data-rights export that omits the person is the one thing it can't do.
- projects, audits (scores + subscores over time), scoreHistory.
- visibility โ the weekly per-engine aggregates: visibility rate, citation rate, share of voice.
- visibilityObservations โ the raw per-answer rows. Engine, model version, whether you were mentioned or cited, which competitors were named, cited sources, sentiment, timestamp, and each row's status.
- prompts, fixes (with the artifact and its before/after โ the artifact is the fix; a row saying "schema, proposed" would be a receipt), content metadata, contentBriefs, citations, keywordGaps, alerts.
success, unavailable or parse_error โ the same distinction the rates are built on. You can recompute our intervals from these rows and check our arithmetic, which is the whole premise we sell. See Reading the numbers.observationsTruncated object saying so โ ask support for the complete set. (2) The weekly visibility aggregates carry the point rates only; their stored interval bounds aren't in this payload yet. The raw observations are, so the bands are recomputable โ but you have to do the arithmetic.If your account is restricted
A member limited to specific projects exports only those projects. The response says so explicitly:
"scope": {
"restricted": true,
"note": "Your account is limited to specific projects, so this export covers only those."
}
A silently-narrowed export is a data-rights answer that looks complete and isn't. It tells you the scope rather than leaving you to wonder why a site is missing.
Post bodies (NDJSON)
Generated post bodies live in object storage and are far too large to inline โ the JSON above would have to hold every one of them in memory at once. So they stream separately, one post per line:
GET /me/export/posts.ndjson
authorization: Bearer <your-token>
{"type":"meta","exportedAt":1800000000000,"org":"...","posts":42,"scoped":false}
{"type":"post","id":"...","title":"...","slug":"...","status":"published","markdown":"# ...","jsonld":"...","createdAt":1800000000000}
{"type":"post","id":"...","title":"...","markdown":null,"error":"the stored body is missing"}
The first line is a meta line with the count and whether the export was scoped. Each following line is one post with its markdown. If a body can't be read, that line carries an explicit error field rather than a silent null โ you can tell "empty post" apart from "we lost it", which is the same distinction as unavailable vs 0%.