Skip to content

Conversation Export API

The Conversation Export API provides access to conversation history stored in Arbitex. It supports single-conversation retrieval, filtered list queries, and asynchronous bulk exports for compliance, analytics, and audit use cases.

All endpoints require admin authentication unless otherwise noted.

Base URL: https://api.arbitex.ai

Authentication: Authorization: Bearer $ARBITEX_API_KEY


interface Conversation {
id: string; // UUID — conversation ID
user_id: string;
user_email: string;
org_id: string;
model_id: string;
provider_id: string;
started_at: string; // ISO 8601 UTC
last_message_at: string; // ISO 8601 UTC
message_count: number;
total_input_tokens: number;
total_output_tokens: number;
total_cost_usd: number;
dlp_findings_count: number; // Total DLP findings across all messages
policy_actions: PolicyActionSummary[];
tags: string[]; // Custom tags, if set
metadata: Record<string, string>; // Custom metadata, if set
}
interface PolicyActionSummary {
action: "allow" | "redact" | "block" | "flag";
count: number;
rule_names: string[];
}

Returns a paginated list of conversations for the authenticated org.

GET /api/admin/conversations
Authorization: Bearer $ARBITEX_API_KEY

Query parameters:

ParameterTypeDefaultDescription
user_idstringFilter by user ID
user_emailstringFilter by user email (exact match)
model_idstringFilter by model ID
fromISO 8601Start of time range (inclusive)
toISO 8601End of time range (inclusive)
has_dlp_findingsbooleantrue to return only conversations with DLP findings
policy_actionstringFilter by policy action taken: block, redact, flag, allow
pageinteger1Page number (1-based)
page_sizeinteger50Results per page (max 500)
sortstringlast_message_at:descSort: started_at, last_message_at, total_cost_usd, dlp_findings_count

Response 200 OK:

{
"conversations": [
{
"id": "conv_abc123",
"user_id": "user_xyz",
"user_email": "alice@example.com",
"org_id": "org_abc",
"model_id": "gpt-4o",
"provider_id": "openai",
"started_at": "2026-03-12T09:00:00Z",
"last_message_at": "2026-03-12T09:15:00Z",
"message_count": 8,
"total_input_tokens": 12500,
"total_output_tokens": 4200,
"total_cost_usd": 0.124,
"dlp_findings_count": 2,
"policy_actions": [
{ "action": "allow", "count": 8, "rule_names": [] }
],
"tags": [],
"metadata": {}
}
],
"total": 1482,
"page": 1,
"page_size": 50,
"pages": 30
}

Returns a conversation record without message content.

GET /api/admin/conversations/{conversation_id}
Authorization: Bearer $ARBITEX_API_KEY

Response 200 OK: Single Conversation object. Returns 404 if not found.


Returns the full message history for a conversation, including request and response content.

GET /api/admin/conversations/{conversation_id}/messages
Authorization: Bearer $ARBITEX_API_KEY

Query parameters:

ParameterTypeDefaultDescription
include_redactedbooleanfalseInclude redacted text with redaction markers
pageinteger1
page_sizeinteger100Messages per page (max 500)

Response 200 OK:

{
"conversation_id": "conv_abc123",
"messages": [
{
"id": "msg_001",
"sequence": 1,
"role": "user",
"content": "Can you help me analyze this data?",
"timestamp": "2026-03-12T09:00:01Z",
"tokens": 12,
"dlp_findings": [],
"policy_action": "allow",
"policy_rule_name": null
},
{
"id": "msg_002",
"sequence": 2,
"role": "assistant",
"content": "Of course! Please share the data you'd like to analyze.",
"timestamp": "2026-03-12T09:00:03Z",
"tokens": 16,
"dlp_findings": [],
"policy_action": "allow",
"policy_rule_name": null
},
{
"id": "msg_003",
"sequence": 3,
"role": "user",
"content": "Customer: John Smith, SSN: [SSN], DOB: 1985-04-12",
"content_redacted": true,
"original_content_hash": "sha256:abc123...",
"timestamp": "2026-03-12T09:01:30Z",
"tokens": 18,
"dlp_findings": [
{
"entity_type": "ssn",
"confidence": 0.97,
"span_start": 27,
"span_end": 38,
"replacement": "[SSN]"
},
{
"entity_type": "person",
"confidence": 0.91,
"span_start": 10,
"span_end": 20,
"replacement": null
}
],
"policy_action": "redact",
"policy_rule_name": "redact-ssn-data"
}
],
"total_messages": 8,
"page": 1,
"page_size": 100
}

Content access note: Message content (content field) is only returned if:

  1. The requesting API key belongs to an admin with conversation:read permission
  2. The org’s data retention policy has not moved the content to cold-tier (cold-tier conversations are metadata-only via this API)

Creates an asynchronous export job for bulk conversation data. Use for compliance exports, analytics pipelines, or archival purposes.

POST /api/admin/conversations/export
Authorization: Bearer $ARBITEX_API_KEY
Content-Type: application/json
{
"format": "jsonl",
"filters": {
"from": "2026-01-01T00:00:00Z",
"to": "2026-03-31T23:59:59Z",
"user_id": null,
"has_dlp_findings": false,
"policy_action": null
},
"include_message_content": true,
"include_dlp_findings": true,
"include_metadata": true,
"notification_email": "admin@example.com"
}

Request body:

FieldTypeDefaultDescription
format"jsonl" | "csv" | "parquet""jsonl"Export file format
filters.fromISO 8601Start date filter (required)
filters.toISO 8601End date filter (required)
filters.user_idstringFilter to one user
filters.has_dlp_findingsbooleanOnly export conversations with DLP findings
filters.policy_actionstringFilter by policy action
include_message_contentbooleantrueInclude full message text
include_dlp_findingsbooleantrueInclude DLP finding detail
include_metadatabooleanfalseInclude conversation metadata and tags
notification_emailstringEmail to notify when export is ready

Response 202 Accepted:

{
"export_id": "exp_xyz789",
"status": "queued",
"estimated_conversations": 8420,
"created_at": "2026-03-12T17:00:00Z",
"check_status_url": "/api/admin/conversations/export/exp_xyz789"
}

GET /api/admin/conversations/export/{export_id}
Authorization: Bearer $ARBITEX_API_KEY

Response 200 OK:

{
"export_id": "exp_xyz789",
"status": "completed",
"format": "jsonl",
"filters": {
"from": "2026-01-01T00:00:00Z",
"to": "2026-03-31T23:59:59Z"
},
"conversations_exported": 8420,
"file_size_bytes": 248572016,
"download_url": "https://storage.arbitex.ai/exports/exp_xyz789/export.jsonl.gz?sig=...",
"download_url_expires_at": "2026-03-13T17:00:00Z",
"created_at": "2026-03-12T17:00:00Z",
"completed_at": "2026-03-12T17:04:38Z"
}

Status values:

StatusDescription
queuedJob is waiting to be processed
runningExport is in progress
completedExport is ready; download_url is available
failedExport failed; see error field
expiredDownload URL has expired (download within 24 hours)

The download_url is a pre-signed URL valid for 24 hours. The exported file is gzip-compressed (.gz extension).


GET /api/admin/conversations/export
Authorization: Bearer $ARBITEX_API_KEY

Query parameters:

ParameterTypeDefaultDescription
statusstringFilter by status
pageinteger1
page_sizeinteger20

Response 200 OK:

{
"exports": [
{
"export_id": "exp_xyz789",
"status": "completed",
"format": "jsonl",
"conversations_exported": 8420,
"created_at": "2026-03-12T17:00:00Z",
"completed_at": "2026-03-12T17:04:38Z"
}
],
"total": 5
}

One JSON object per line. Each line is a complete conversation with nested messages:

{"id":"conv_abc123","user_email":"alice@example.com","model_id":"gpt-4o","started_at":"2026-03-12T09:00:00Z","messages":[{"role":"user","content":"...","timestamp":"...","dlp_findings":[]},{"role":"assistant","content":"...","timestamp":"..."}]}
{"id":"conv_def456","user_email":"bob@example.com","model_id":"claude-3-5-sonnet-20241022","started_at":"2026-03-12T10:00:00Z","messages":[...]}

One row per message (not per conversation). Conversation-level fields are repeated on each message row:

conversation_id,user_email,model_id,started_at,message_id,role,content,timestamp,tokens,dlp_findings_count,policy_action
conv_abc123,alice@example.com,gpt-4o,2026-03-12T09:00:00Z,msg_001,user,"Can you help me...",2026-03-12T09:00:01Z,12,0,allow

Columnar format. Recommended for analytics use cases (BigQuery, Snowflake, Redshift, pandas). Schema mirrors the JSONL structure with messages as a nested repeated field.


GDPR right-to-erasure: delete user conversations

Section titled “GDPR right-to-erasure: delete user conversations”

Deletes all conversation content for a specific user. This is a hard delete — message content is permanently removed. Conversation metadata (token counts, timestamps, policy action counts) is retained for billing and audit purposes.

DELETE /api/admin/conversations/user/{user_id}
Authorization: Bearer $ARBITEX_API_KEY
Content-Type: application/json
{
"reason": "GDPR right-to-erasure request — ticket #1234",
"confirm": true
}

Request body:

FieldTypeRequiredDescription
reasonstringYesAudit log annotation (required for compliance)
confirmbooleanYesMust be true to proceed

Response 200 OK:

{
"user_id": "user_xyz",
"conversations_affected": 47,
"messages_deleted": 312,
"deletion_id": "del_abc123",
"completed_at": "2026-03-12T17:00:00Z",
"audit_log_entry": "audit_456"
}

Returns 409 Conflict if the user has a legal hold applied. See Data Retention & Archival for legal hold procedures.


Full-text search across conversation content. Returns conversations where message content matches the query.

POST /api/admin/conversations/search
Authorization: Bearer $ARBITEX_API_KEY
Content-Type: application/json
{
"query": "quarterly earnings report",
"filters": {
"from": "2026-01-01T00:00:00Z",
"to": "2026-03-31T23:59:59Z",
"user_id": null
},
"page": 1,
"page_size": 20
}

Response 200 OK:

{
"conversations": [
{
"id": "conv_abc123",
"user_email": "alice@example.com",
"model_id": "gpt-4o",
"started_at": "2026-02-15T14:00:00Z",
"relevance_score": 0.94,
"matching_messages": [
{
"message_id": "msg_005",
"role": "user",
"excerpt": "...analyze the [quarterly earnings report] for Q4 2025...",
"timestamp": "2026-02-15T14:02:00Z"
}
]
}
],
"total": 23,
"page": 1,
"page_size": 20
}

Full-text search is available only for conversations in the hot tier (last 90 days by default). Cold-tier conversations require export for content search.


OperationRequired permission
List conversationsconversation:list
Get conversationconversation:read
Get message contentconversation:read
Exportconversation:export
Delete user conversationsconversation:delete
Searchconversation:read

Default admin API keys have all conversation permissions. Scoped API keys can be configured with specific permissions via Admin → API Keys.