---
title: "Export Shared Data User"
method: GET
path: "/api/admin/shared-data/users/{user_id}/export"
tags: ["admin"]
---

# Export Shared Data User

`GET /api/admin/shared-data/users/{user_id}/export`

One-shot export bundle for a consenting user.

Designed for CLI / offline analysis: a single audit-logged request
returns identity + profile + memory + heartbeat history + activity
counts + tool usage rollup, all PII-redacted. Without this, an
admin investigating "what's wrong with this user's experience?"
has to walk seven separate endpoints by hand.

The window only applies to time-bucketed sub-resources. The
profile / memory / consent fields are always the current value.

Bodies live in two places:
* The agent's persistent text (soul, user, heartbeat directives,
  memory) returns in the corresponding sections.
* Per-message transcripts only return when ``include_turns=true``.
  They are the heaviest field (one row per message + tool call).

## Path parameters

- `user_id` string, required

## Query parameters

- `days` integer — Window size in days, ending now. Scopes the time-bucketed subresources (conversations, heartbeat-logs, compaction-events, LLM-usage, reports, and the tool-call rollup). Identity, profile, and memory are point-in-time and not scoped by the window.
- `include_turns` boolean — When true, attach turn-grouped transcripts for every conversation in the window. Off by default because turns are expensive both to compute and to ship; flip on when you want full body content.

## Response `200`

Successful Response

- SharedDataExportResponse — Composite per-user export. Sections: * ``user``: identity + profile config (timezone, channel, consent timestamp). * ``window``: the date range applied to time-windowed sub-resources. * ``summary``: the aggregate-counts rollup. * ``conversations``: per-session metadata for sessions active in the window (no bodies; bodies live in ``turns`` if requested). * ``heartbeat_logs``: per-event rows including PII-redacted ``message_text`` / ``reasoning`` / ``tasks``. * ``compaction_events``: per-event metadata (no content; the content is in ``memory.history_text``). * ``profile``: soul / user / heartbeat directives text, PII-redacted. * ``memory``: working memory + compacted history, PII-redacted. * ``turns``: turn-grouped transcripts (only when ``include_turns=true``).
  - `user_id` string, required
  - `user` object, required
  - `window` object, required
  - `summary` SharedDataExportSummary, required — Aggregate counts for one user over the requested window. Mirrors the per-user activity rollup an admin would otherwise derive by walking the conversations / heartbeat-logs / compaction endpoints. Counts only; bodies and memory text live in the other fields of the export response.
    - `session_count` integer, required
    - `message_count` integer, required
    - `inbound_count` integer, required
    - `outbound_count` integer, required
    - `heartbeats_total` integer, required
    - `heartbeats_by_action` object, required
    - `compactions_count` integer, required
    - `llm_calls_total` integer, required
    - `llm_calls_by_purpose` object, required
    - `llm_cost_usd` string, required
    - `llm_input_tokens` integer, required
    - `llm_output_tokens` integer, required
    - `llm_cache_read_tokens` integer, required
    - `tool_calls_total` integer, required
    - `tool_calls_error_count` integer, required
    - `tool_calls_top` SharedDataExportTopTool[], required
      - `name` string, required
      - `call_count` integer, required
      - `error_count` integer, required
    - `reports_total` integer, required
  - `conversations` SharedDataConversationItem[], required
    - `session_id` string, required
    - `channel` string, required
    - `created_at` string, nullable, required
    - `last_message_at` string, nullable, required
    - `message_count` integer, required
    - `last_trim_seq` integer, nullable
  - `heartbeat_logs` SharedDataHeartbeatLogItem[], required
    - `id` integer, required
    - `action_type` string, required
    - `channel` string, required
    - `message_text` string, required
    - `reasoning` string, required
    - `tasks` string, required
    - `created_at` string, nullable, required
  - `compaction_events` SharedDataCompactionEventItem[], required
    - `id` integer, required
    - `triggered_at` string, nullable, required
    - `duration_ms` integer, required
    - `trimmed_count` integer, required
    - `trimmed_chars` integer, required
    - `input_tokens` integer, required
    - `output_tokens` integer, required
    - `min_message_seq` integer, nullable, required
    - `max_message_seq` integer, nullable, required
    - `status` string, required
    - `memory_updated` boolean, required
    - `user_profile_updated` boolean, required
    - `soul_updated` boolean, required
    - `summary_len` integer, required
    - `memory_text_before` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `memory_text_after` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `history_text_before` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `history_text_after` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `user_text_before` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `user_text_after` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `soul_text_before` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `soul_text_after` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `prompt` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `raw_response` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
    - `parsed_response` SharedDataCompactionSnapshot, required — One before/after memory-file snapshot from a compaction event. OSS stores eight envelope-encrypted text columns on ``compaction_events`` (memory/history/user/soul x before/after). The ORM decrypts to plaintext on read. When the underlying file exceeded ``settings.compaction_event_snapshot_max_bytes_per_file`` the column instead carries a JSON truncation record (``head``, ``tail``, ``size_bytes``, ``sha256``); we surface that here as ``truncated=True`` so the admin UI can render "truncated, N KB" with the head and tail visible inline rather than dumping the JSON verbatim into a body cell. ``None`` plaintext (``text`` is None and ``truncated`` is False) means the field was unchanged by this event (skip-if-unchanged optimization), the row is still ``'pending'``, or the row predates the feature.
      - `text` string, nullable
      - `truncated` boolean
      - `size_bytes` integer, nullable
      - `head` string, nullable
      - `tail` string, nullable
      - `sha256` string, nullable
  - `profile` SharedDataProfileResponse, required — User profile + agent personality text for one consenting user. All three text fields go through ``redact_pii`` before serialization so phone numbers / emails / tokens that the user pasted into their soul or memory directives don't surface verbatim. ``soul_text`` (agent personality), ``user_text`` (synthesized profile), and ``heartbeat_text`` (proactive directives) used to live on ``GET /admin/users/{id}`` until the slimming PR (#336); this is the consent-gated home for them.
    - `user_id` string, required
    - `consent_at` string, nullable, required
    - `soul_text` string, required
    - `user_text` string, required
    - `heartbeat_text` string, required
    - `heartbeat_opt_in` boolean, required
    - `heartbeat_frequency` string, required
    - `heartbeat_max_daily` integer, required
  - `memory` SharedDataMemoryDocumentResponse, required — Working memory + accumulated compaction history for a consenting user. ``memory_text`` is the agent's working memory file; ``history_text`` is the chronological log of what compaction extracted from older sessions. Per-event metadata (when, sizes, costs, what got updated) lives in ``compaction_events`` and is exposed via the sibling ``/compaction-events`` endpoint; this response is the working memory itself.
    - `user_id` string, required
    - `consent_at` string, nullable, required
    - `memory_text` string, required
    - `history_text` string, required
    - `updated_at` string, nullable, required
  - `turns` SharedDataConversationTurnsResponse[], nullable
    - `session_id` string, required
    - `user_id` string, required
    - `consent_at` string, nullable, required
    - `turns` SharedDataTurn[], required
      - `turn_index` integer, required
      - `user_message` SharedDataMessageItem — One message inside a consenting user's conversation, PII-redacted. ``body`` has been passed through :func:`pii_redaction.redact_pii` before serialization. The original plaintext is never returned by this endpoint. ``thinking`` carries the LLM's extended-thinking output for outbound messages (see OSS migration 033); it is empty for inbound messages and for outbound rows persisted before the capture path was wired up. ``thinking`` runs through the same shape-based redaction as ``body`` (emails, phones, cards, tokens masked by regex). Names and other free-form identifiers are not masked because the redactor has no shape to match them against, same caveat as ``body``.
        - `seq` integer, required
        - `direction` string, required
        - `body` string, required
        - `thinking` string
        - `timestamp` string, nullable, required
      - `agent_reply` SharedDataMessageItem — One message inside a consenting user's conversation, PII-redacted. ``body`` has been passed through :func:`pii_redaction.redact_pii` before serialization. The original plaintext is never returned by this endpoint. ``thinking`` carries the LLM's extended-thinking output for outbound messages (see OSS migration 033); it is empty for inbound messages and for outbound rows persisted before the capture path was wired up. ``thinking`` runs through the same shape-based redaction as ``body`` (emails, phones, cards, tokens masked by regex). Names and other free-form identifiers are not masked because the redactor has no shape to match them against, same caveat as ``body``.
        - `seq` integer, required
        - `direction` string, required
        - `body` string, required
        - `thinking` string
        - `timestamp` string, nullable, required
      - `tool_calls` SharedDataToolCall[]
        - `tool_call_id` string, required
        - `name` string, required
        - `args` object
        - `result` string
        - `is_error` boolean
        - `receipt` SharedDataReceipt — Tool receipt redacted for admin display. Mirrors ``StoredToolReceipt`` from ``backend/app/agent/context.py`` but each string field is passed through :func:`pii_redaction.redact_pii` before serialization.
          - `action` string
          - `target` string
          - `url` string, nullable
      - `started_at` string, nullable
      - `finished_at` string, nullable
    - `total` integer, required
    - `last_trim_seq` integer, nullable

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/mozilla-ai/apis/clawbolt.md) · [All operations](https://skmtc.net/mozilla-ai/apis/clawbolt/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/mozilla-ai/clawbolt/revisions/0e52fe5f8d33/schema)
