# Acquisitions API

The Acquisitions API allows you to create, retrieve, update, and delete acquisition records. Acquisitions represent forensic data collections tied to cases, evidence items, and other related entities.

***

### Endpoints

| Method   | Path                  | Description                    |
| -------- | --------------------- | ------------------------------ |
| `GET`    | `/acquisitions`       | List all acquisitions          |
| `GET`    | `/acquisitions/:uuid` | Get a single acquisition       |
| `POST`   | `/acquisitions`       | Create a new acquisition       |
| `PATCH`  | `/acquisitions/:uuid` | Update an existing acquisition |
| `DELETE` | `/acquisitions/:uuid` | Delete an acquisition          |

***

### Data Model

Each acquisition object contains the following fields:

| Field            | Type   | Description                                         |
| ---------------- | ------ | --------------------------------------------------- |
| `acq_id`         | number | Internal acquisition ID                             |
| `uuid`           | string | Unique identifier                                   |
| `name`           | string | Acquisition name                                    |
| `format`         | string | Acquisition format (e.g., E01, DD, AD1)             |
| `type`           | string | Acquisition type                                    |
| `status`         | string | `"Active"` or `"Deleted"`                           |
| `size`           | number | Numeric size value                                  |
| `size_unit`      | string | Unit of size: `"B"`, `"KB"`, `"MB"`, `"GB"`, `"TB"` |
| `size_bytes`     | number | Calculated size in bytes                            |
| `size_gb`        | number | Calculated size in gigabytes                        |
| `description`    | string | Notes or description                                |
| `created_on`     | string | Timestamp when the record was created               |
| `updated_on`     | string | Timestamp when the record was last updated          |
| `acquire_date`   | string | Date the acquisition was performed (ISO 8601)       |
| `duration`       | number | Acquisition duration in seconds                     |
| `hashes`         | array  | Array of `{ type, hash }` objects                   |
| `storage`        | object | Linked storage location                             |
| `evidence`       | object | Linked evidence item                                |
| `case`           | object | Linked case                                         |
| `linked_contact` | object | Linked contact / custodian                          |
| `acquired_by`    | object | User who performed the acquisition                  |
| `location`       | object | Physical storage location                           |
| `custom_fields`  | array  | Custom field values                                 |

***

### GET /acquisitions

Retrieve a paginated list of acquisitions. Supports filtering by case, evidence, status, and date ranges.

#### Query Parameters

| Parameter         | Type   | Required | Description                                   |
| ----------------- | ------ | -------- | --------------------------------------------- |
| `uuid`            | string | No       | Filter by acquisition UUID                    |
| `acq_id`          | number | No       | Filter by acquisition ID                      |
| `evidence_uuid`   | string | No       | Filter by evidence UUID                       |
| `evidence_id`     | number | No       | Filter by evidence ID                         |
| `case_id`         | number | No       | Filter by case ID                             |
| `case_uuid`       | string | No       | Filter by case UUID                           |
| `status`          | string | No       | `"Active"` or `"Deleted"`                     |
| `created_after`   | string | No       | Records created on or after this date         |
| `created_before`  | string | No       | Records created on or before this date        |
| `acquired_after`  | string | No       | Acquisitions performed on or after this date  |
| `acquired_before` | string | No       | Acquisitions performed on or before this date |
| `updated_after`   | string | No       | Records updated on or after this date         |
| `updated_before`  | string | No       | Records updated on or before this date        |
| `page`            | number | No       | Page number (minimum: 1, default: 1)          |
| `page_size`       | number | No       | Results per page (1–1000, default: 1000)      |

#### Response

```json
{
  "data": [ ... ],
  "total": 42,
  "page_size": 25,
  "page": 1,
  "next_page": 2
}
```

The `next_page` field is `null` when there are no more pages.

#### Example: List All Acquisitions

```python
response = requests.get(
    f"{BASE_URL}/acquisitions",
    headers=HEADERS,
)

result = response.json()

for acq in result["data"]:
    print(f"{acq['uuid']} - {acq['name']} ({acq['size']} {acq['size_unit']})")

print(f"Total: {result['total']}")
```

#### Example: Filter by Case UUID with Pagination

```python
response = requests.get(
    f"{BASE_URL}/acquisitions",
    headers=HEADERS,
    params={
        "case_uuid": "abc-123-def-456",
        "status": "Active",
        "page_size": 25,
        "page": 1,
    },
)

result = response.json()
print(f"Page {result['page']} — showing {len(result['data'])} of {result['total']}")
```

#### Example: Filter by Date Range

```python
response = requests.get(
    f"{BASE_URL}/acquisitions",
    headers=HEADERS,
    params={
        "acquired_after": "2025-01-01",
        "acquired_before": "2025-12-31",
    },
)

for acq in response.json()["data"]:
    print(f"{acq['name']} — acquired {acq['acquire_date']}")
```

***

### GET /acquisitions/:uuid

Retrieve a single acquisition by UUID.

#### Example

```python
acquisition_uuid = "abc-123-def-456"

response = requests.get(
    f"{BASE_URL}/acquisitions/{acquisition_uuid}",
    headers=HEADERS,
)

acq = response.json()["data"][0]
print(f"Name: {acq['name']}")
print(f"Format: {acq['format']}")
print(f"Size: {acq['size']} {acq['size_unit']} ({acq['size_gb']} GB)")
print(f"Case: {acq['case']['case_number']}")

for h in acq["hashes"]:
    print(f"  {h['type']}: {h['hash']}")
```

***

### POST /acquisitions

Create a new acquisition.

#### Request Body

| Field                 | Type   | Required | Description                                     |
| --------------------- | ------ | -------- | ----------------------------------------------- |
| `name`                | string | **Yes**  | Acquisition name                                |
| `case_uuid`           | string | **Yes**  | UUID of the parent case                         |
| `uuid`                | string | No       | Custom UUID (auto-generated if omitted)         |
| `format`              | string | No       | Acquisition format (e.g., E01, DD)              |
| `type`                | string | No       | Acquisition type                                |
| `status`              | string | No       | `"Active"` or `"Deleted"`                       |
| `size`                | number | No       | Numeric size value                              |
| `size_unit`           | string | No       | `"B"`, `"KB"`, `"MB"`, `"GB"`, or `"TB"`        |
| `tool`                | string | No       | Tool used for acquisition                       |
| `tool_version`        | string | No       | Version of the acquisition tool                 |
| `description`         | string | No       | Notes or description                            |
| `acquire_date`        | string | No       | Date of acquisition (ISO 8601)                  |
| `duration`            | number | No       | Duration in seconds                             |
| `hash_1`              | string | No       | Primary hash value                              |
| `hash_1_type`         | string | No       | Primary hash algorithm (e.g., MD5, SHA1)        |
| `hash_2`              | string | No       | Secondary hash value                            |
| `hash_2_type`         | string | No       | Secondary hash algorithm                        |
| `storage_uuid`        | string | No       | UUID of the storage location                    |
| `evidence_uuid`       | string | No       | UUID of the parent evidence item                |
| `linked_contact_uuid` | string | No       | UUID of the linked contact / custodian          |
| `acquired_by_id`      | number | No       | User ID of the person who performed acquisition |
| `location_uuid`       | string | No       | UUID of the physical location                   |
| `custom_fields`       | array  | No       | Array of `{ field_id, value }` objects          |

#### Response

```json
{
  "data": { ... },
  "message": "Acquisition created successfully"
}
```

#### Example: Create a Basic Acquisition

```python
response = requests.post(
    f"{BASE_URL}/acquisitions",
    headers=HEADERS,
    json={
        "name": "Laptop-HDD-001",
        "case_uuid": "case-abc-123",
    },
)

result = response.json()
print(f"Created: {result['data']['uuid']}")
print(result["message"])
```

#### Example: Create with Full Details

```python
response = requests.post(
    f"{BASE_URL}/acquisitions",
    headers=HEADERS,
    json={
        "name": "Laptop-HDD-001-Full",
        "case_uuid": "case-abc-123",
        "evidence_uuid": "evidence-xyz-789",
        "format": "E01",
        "type": "Physical",
        "size": 256,
        "size_unit": "GB",
        "tool": "FTK Imager",
        "tool_version": "4.7.1",
        "description": "Full disk image of suspect laptop",
        "acquire_date": "2025-06-15T10:30:00Z",
        "duration": 7200,
        "hash_1": "d41d8cd98f00b204e9800998ecf8427e",
        "hash_1_type": "MD5",
        "hash_2": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
        "hash_2_type": "SHA1",
        "storage_uuid": "storage-def-456",
        "linked_contact_uuid": "contact-ghi-789",
        "acquired_by_id": 12,
        "custom_fields": [
            {"field_id": 1, "value": "Priority: High"},
            {"field_id": 2, "value": "Encrypted: No"},
        ],
    },
)

acq = response.json()["data"]
print(f"UUID: {acq['uuid']}")
print(f"Size: {acq['size_gb']} GB")
```

***

### PATCH /acquisitions/:uuid

Update an existing acquisition. Only include the fields you want to change.

#### Request Body

All fields from the create endpoint are accepted (except `case_uuid` is optional). Only provided fields will be updated.

#### Response

```json
{
  "data": { ... },
  "message": "Acquisition updated successfully"
}
```

#### Example: Update Name and Description

```python
acquisition_uuid = "abc-123-def-456"

response = requests.patch(
    f"{BASE_URL}/acquisitions/{acquisition_uuid}",
    headers=HEADERS,
    json={
        "name": "Laptop-HDD-001-Updated",
        "description": "Re-imaged with corrected write blocker settings",
    },
)

result = response.json()
print(result["message"])
print(f"Updated name: {result['data']['name']}")
```

#### Example: Update Hash Values

```python
acquisition_uuid = "abc-123-def-456"

response = requests.patch(
    f"{BASE_URL}/acquisitions/{acquisition_uuid}",
    headers=HEADERS,
    json={
        "hash_1": "e99a18c428cb38d5f260853678922e03",
        "hash_1_type": "MD5",
        "hash_2": "6dcd4ce23d88e2ee9568ba546c007c63d9131c1b",
        "hash_2_type": "SHA1",
    },
)

print(response.json()["message"])
```

#### Example: Update Custom Fields

```python
acquisition_uuid = "abc-123-def-456"

response = requests.patch(
    f"{BASE_URL}/acquisitions/{acquisition_uuid}",
    headers=HEADERS,
    json={
        "custom_fields": [
            {"field_id": 1, "value": "Priority: Low"},
        ],
    },
)

print(response.json()["message"])
```

***

### DELETE /acquisitions/:uuid

Permanently delete an acquisition by UUID.

#### Response

```json
{
  "data": { ... },
  "message": "Acquisition deleted successfully"
}
```

#### Example

```python
acquisition_uuid = "abc-123-def-456"

response = requests.delete(
    f"{BASE_URL}/acquisitions/{acquisition_uuid}",
    headers=HEADERS,
)

result = response.json()
print(result["message"])
print(f"Deleted: {result['data']['name']}")
```

***

### Error Handling

The API returns standard HTTP status codes:

| Code | Meaning                                    |
| ---- | ------------------------------------------ |
| 200  | Success                                    |
| 400  | Validation error (invalid parameters/body) |
| 401  | Unauthorized (missing or invalid API key)  |
| 500  | Internal server error                      |

Error responses include a `message` field. Validation errors also include an `errors` array with details.

```json
{
  "message": "Invalid request body",
  "errors": [
    {
      "code": "invalid_type",
      "expected": "string",
      "received": "undefined",
      "path": ["name"],
      "message": "Required"
    }
  ]
}
```

#### Example: Error Handling in Python

```python
response = requests.post(
    f"{BASE_URL}/acquisitions",
    headers=HEADERS,
    json={
        "description": "Missing required name and case_uuid",
    },
)

if response.status_code != 200:
    error = response.json()
    print(f"Error {response.status_code}: {error['message']}")
    if "errors" in error:
        for err in error["errors"]:
            print(f"  - {'.'.join(str(p) for p in err['path'])}: {err['message']}")
```

***

### Pagination

List responses are paginated. Use `page` and `page_size` to control pagination.

#### Example: Iterate Through All Pages

```python
def get_all_acquisitions(case_uuid):
    all_acquisitions = []
    page = 1

    while True:
        response = requests.get(
            f"{BASE_URL}/acquisitions",
            headers=HEADERS,
            params={
                "case_uuid": case_uuid,
                "page": page,
                "page_size": 100,
            },
        )

        result = response.json()
        all_acquisitions.extend(result["data"])

        if result["next_page"] is None:
            break

        page = result["next_page"]

    return all_acquisitions


acquisitions = get_all_acquisitions("case-abc-123")
print(f"Total acquisitions: {len(acquisitions)}")
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.monolithforensics.com/monolith/monolith-api/acquisitions-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
