# Step 5: Export phone data Exports run in the background. You start one, wait for it to finish, then download the file. ## Start an export `POST /case/{caseId}/export` For phone data: - `source`: `conversation`. This covers messages and chats collected from phones. - `type` (required): the output format, for example `pdf`, `rsmf`, `csv`, `text` or `doc`. The full list is in the reference. - `sortBy` (required): `old-to-new` or `new-to-old`. - **Limit the export to one phone:** set `device` to the device id (the `sourceId` from data-status-v2). - **Limit it to specific conversations:** set `conversations` to a list of conversation ids. You can find them with `GET /conversation/search`, filtered by `case` and `devices`. - Optional: - `tags`: only messages with these tags. Send tag **ids**, not names (see Step 4). - `startDate` and `endDate`: a date window. - `excludeConversations`: conversations to skip. - `excludeDeviceSources`: message sources to skip within a device, such as `call_log` or `voicemail`. - `chunkType`: split the export by `day`, `week`, `month` or `year`. - `timezone`: an IANA name such as `America/New_York`, used to format timestamps. - `fileName`. - `emails`: extra addresses to notify when the export finishes. The call returns the export record. Save its id from `data.id`. > warn > **An empty selection means "the whole case".** If you send neither `device` nor `conversations`, the export includes **every conversation on the case**. If you meant a narrow export, double-check your selection before calling. Your organization needs an active plan to start an export (see Step 2). Starting an export also needs admin access to the case; the case's owner has it. ## Wait for it `GET /case/{caseId}/export` lists the case's exports. Pass `exportId` to get just yours; it is still a list, so read the row from `data.data`. Then read its `status`: | Status | Meaning | |---|---| | `not-started` | Queued | | `inprogress` | Running. `progress`, `conversationsProcessed` and `messagesProcessed` show how far along it is. | | `completed` | Done. `file` is set. | | `failed` | Failed. `errorMessage` says why. | | `cancelled` | Cancelled. | Poll every 30 to 60 seconds. Large exports can take a long time. ## Download the file When `status` is `completed`, take the file id from the export's `file.id` and call `GET /common/file/{fileId}/signed-url`. It returns a temporary download `url` and the time it stops working, `expiresAt` (up to 24 hours later). Download promptly, and do not store or share signed URLs. They expire, and anyone holding one can download the file while it is valid. ## Retry and clean up - `POST /case/{caseId}/export/{exportId}/rerun` runs a failed or unfinished export again with the same settings. A completed export cannot be rerun; start a new one instead. - `DELETE /case/{caseId}/export/{exportId}` removes an export. ## Example Export one phone's tagged messages as a PDF: ```sh curl -X POST "https://api.usehearsay.com/case/$CASE_ID/export" \ -H "Authorization: Bearer $TOKEN" \ -H "organization: $ORG_ID" \ -H "Content-Type: application/json" \ -d '{ "source": "conversation", "type": "pdf", "sortBy": "old-to-new", "device": "507f1f77bcf86cd799439012", "tags": ["507f1f77bcf86cd799439016"], "timezone": "America/New_York" }' ``` Poll until it is done: ```sh curl "https://api.usehearsay.com/case/$CASE_ID/export?exportId=$EXPORT_ID" \ -H "Authorization: Bearer $TOKEN" \ -H "organization: $ORG_ID" ``` ```json { "data": { "data": [ { "id": "507f1f77bcf86cd799439014", "status": "completed", "progress": 100, "fileName": "doe-v-example-export.pdf", "file": { "id": "507f1f77bcf86cd799439015" }, "errorMessage": null } ], "total": 1, "nextPage": null }, "statusCode": 200, "timestamp": "2026-01-15T10:15:00.000Z" } ``` Get the download link: ```sh curl "https://api.usehearsay.com/common/file/$FILE_ID/signed-url" \ -H "Authorization: Bearer $TOKEN" ``` ```json { "data": { "url": "https://bucket.s3.amazonaws.com/files/report.pdf?X-Amz-Signature=abc123", "expiresAt": "2026-01-15T10:30:00.000Z" }, "statusCode": 200, "timestamp": "2026-01-15T10:15:00.000Z" } ```