# Step 3: Collect phone data with an extraction code An extraction code is a one-time code you give to a **custodian**: the person whose phone holds the data. The custodian enters the code in the **Hearsay desktop app**, connects their phone, and the app uploads the selected data into your case. Your integration creates the code, delivers it, and then waits for the upload. ## Create a code `POST /case/{caseId}/extraction` - No field is strictly required, but set `dueDate` and the custodian details. - Custodian: `custodianName`, `custodianEmail`, `custodianPhone`. - `requestedSources`: what you want collected. For phones, use `ios`, `android` or both. - `label`: a name you choose, to tell codes apart. - `config`: collection settings, for example a date range, which apps may be shared, and attachments. See `ExtractionCodeConfigDto` in the reference. If you send `config`, its `type` is required. - Delivery: set `sendEmail: true` **and** give a `custodianEmail`, and Hearsay emails the code to the custodian. If you leave either out, no email is sent; you must pass the code to the custodian some other way. - `sendReminders`: optional automatic reminder emails, before the due date and after the code was issued. - Save the code value from `data.code`. Later routes call it `extractionCode`. Leave these fields alone unless Hearsay tells you otherwise: the payment fields (`paymentRequired`, `paymentAmount`, `prepaidItems` and so on), `ocRequired`, and the deprecated `allowShareAll` (use `config` instead). ## Update a code `PATCH /case/{caseId}/extraction/{extractionCode}` - You can change the label, due date, configuration and custodian details. - Once a code is **locked** (`lockCode`), its configuration cannot change; the call returns an error. Set the configuration right at creation where you can. - To change only the custodian's contact details, use `PATCH /case/{caseId}/extraction/{extractionCode}/custodian`. By default it sends the code email again when the email address changes. - To send or resend the email, use `POST /case/{caseId}/extraction/{extractionCode}/send-email`. ## List codes `GET /case/{caseId}/extraction` returns the case's codes with their upload status. You can filter with `searchText` or `extractionCode`, and page through the results. ## Know when the phone data has arrived There is no callback. **Poll** `GET /case/{caseId}/data-status-v2`: - The entries are in `data.data`, one per extraction code, each with its `code`, `custodian` and `dataSources`. - For a phone, a data source has `type` `ios` or `android`. It also has a `status`, an `itemsCount`, a `name` (the device name), and a `sourceId`, which is the **device id** you need for Steps 4 and 5. - Start the export only after the phone source shows a completed status and a non-zero `itemsCount`. - Poll every few minutes, not every few seconds. A phone upload can take hours, and a custodian may take days to act. ## Read device details `GET /device/{deviceId}` (with the `sourceId` from data-status-v2) returns the phone's details and which kinds of data it holds. `PATCH /device/{deviceId}` changes its display name, manufacturer, brand or model. ## Example Create a code and email it to the custodian: ```sh curl -X POST "https://api.usehearsay.com/case/$CASE_ID/extraction" \ -H "Authorization: Bearer $TOKEN" \ -H "organization: $ORG_ID" \ -H "Content-Type: application/json" \ -d '{ "dueDate": "2026-11-15T00:00:00.000Z", "label": "Primary phone", "custodianName": "Jane Doe", "custodianEmail": "jane.doe@example.com", "requestedSources": ["ios"], "sendEmail": true, "sendReminders": { "dueIn3Days": true } }' ``` The code is `data.code`: ```json { "data": { "id": "507f1f77bcf86cd799439013", "code": "K7Q2-9XPL", "label": "Primary phone", "name": "Jane Doe", "email": "jane.doe@example.com", "status": "pending" }, "statusCode": 201, "timestamp": "2026-01-15T10:15:00.000Z" } ``` Poll for the upload: ```sh curl "https://api.usehearsay.com/case/$CASE_ID/data-status-v2" \ -H "Authorization: Bearer $TOKEN" \ -H "organization: $ORG_ID" ``` The phone is ready when its source is completed and has items. `sourceId` is the device id: ```json { "data": { "data": [ { "code": "K7Q2-9XPL", "custodian": { "name": "Jane Doe", "email": "jane.doe@example.com" }, "dataSources": [ { "type": "ios", "name": "iPhone 15", "status": "completed", "itemsCount": 1250, "sourceId": "507f1f77bcf86cd799439012" } ] } ] }, "statusCode": 200, "timestamp": "2026-01-15T10:15:00.000Z" } ```