# Escrows API

> REST endpoints for escrows — request and response reference with examples.

<!-- Source: https://docs.actuallycare.com/api/reference/escrows -->

Transactions from contract to close — create, list, update, and manage escrows.

Base URL: `https://api.actuallycare.com/v1` · Errors use the [standard envelope](/api/reference#error-responses) — see [Errors](/api/errors).

## List escrows

```http
GET /v1/escrows
```

Returns a paginated list of escrows visible to the authenticated user, with aggregate stats. Supports filtering by status, price range, closing-date range, and free-text search across property address and display ID. Note the effective default page size for this endpoint is 20 (a controller-level override of the platform-wide default of 25).

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `status` | query | enum | No | Filter by escrow status (case-insensitive) · One of: `active`, `pending`, `closed`, `cancelled` |
| `search` | query | string | No | Free-text search across property address and display ID |
| `minPrice` | query | number | No | Minimum purchase price · Min: 0 |
| `maxPrice` | query | number | No | Maximum purchase price · Min: 0 |
| `closingDateStart` | query | string | No | Earliest closing date (ISO 8601) · Format: date |
| `closingDateEnd` | query | string | No | Latest closing date (ISO 8601) · Format: date |
| `archived` | query | boolean | No | Include archived escrows instead of active ones · Default: `false` |
| `sort` | query | string | No | Sort column · Default: `"created_at"` |
| `order` | query | enum | No | Sort direction · One of: `asc`, `desc` · Default: `"desc"` |
| `page` | query | integer | No | Page number for pagination · Default: `1` · Min: 1 |
| `limit` | query | integer | No | Number of items per page (default 25; GET /escrows overrides this to 20 at the controller level) · Default: `25` · Max: 100 · Min: 1 |

### Example request

```bash title="cURL"
curl "https://api.actuallycare.com/v1/escrows" \
  -H "X-API-Key: YOUR_API_KEY"
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows", {
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.actuallycare.com/v1/escrows",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = resp.json()
```

### Example response (200)

```json
{
  "success": true,
  "data": {
    "escrows": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "user_id": "550e8400-e29b-41d4-a716-446655440000",
        "property_address": "123 Main St, Tehachapi, CA 93561",
        "city": "Tehachapi",
        "state": "CA",
        "zip_code": "93561",
        "purchase_price": 500000,
        "escrow_status": "active",
        "acceptance_date": "2025-01-15",
        "closing_date": "2025-03-01",
        "buyers": [
          {
            "name": "John Doe",
            "email": "john@example.com",
            "phone": "(555) 123-4567"
          }
        ],
        "sellers": [
          {
            "name": "John Doe",
            "email": "john@example.com",
            "phone": "(555) 123-4567"
          }
        ],
        "listing_agent": {
          "name": "Alex Rivera",
          "email": "agent@example.com",
          "phone": "+1 661 555 0123",
          "license": "DRE #02209852",
          "brokerage": "Associated Real Estate"
        },
        "selling_agent": {
          "name": "Alex Rivera",
          "email": "agent@example.com",
          "phone": "+1 661 555 0123",
          "license": "DRE #02209852",
          "brokerage": "Associated Real Estate"
        },
        "escrow_company": "First American Title",
        "escrow_officer": "Jane Smith",
        "property_type": "single_family",
        "bedrooms": 3,
        "bathrooms": 2.5,
        "square_feet": 2400,
        "lot_size": 0.25,
        "year_built": 2015,
        "contingencies": [
          {
            "type": "inspection",
            "due_date": "2026-07-15",
            "status": "pending"
          }
        ],
        "earnest_money": 10000,
        "commission_rate": 3,
        "notes": "example notes",
        "version": 1,
        "created_at": "2026-07-15T14:32:10.000Z",
        "updated_at": "2026-07-15T14:32:10.000Z",
        "last_modified_by": "550e8400-e29b-41d4-a716-446655440000"
      }
    ],
    "stats": {},
    "meta": {
      "page": 1,
      "limit": 20,
      "total": 150,
      "totalPages": 8,
      "hasMore": true
    }
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Paginated escrow list with aggregate stats |
| `400` | Invalid request data |
| `401` | Authentication required |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |

## Create an escrow

```http
POST /v1/escrows
```

Opens a new escrow (transaction). Only the property address is required; financial, party, and vendor details can be added later.

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `property_address` | string | Yes | Street address of the property in escrow |
| `purchase_price` | number | No | Purchase price in USD |
| `escrow_status` | enum | No | Initial escrow status (defaults to active) · One of: `active`, `pending`, `closed`, `cancelled` · Default: `"active"` |
| `acceptance_date` | string | No | Offer acceptance date (ISO 8601) · Format: date |
| `closing_date` | string | No | Expected closing date (ISO 8601) · Format: date |
| `city` | string | No | City name |
| `state` | string | No | State abbreviation (e.g. CA) |
| `zip_code` | string | No | ZIP code |
| `earnest_money_deposit` | number | No | Earnest money deposit amount in USD |
| `commission_percentage` | number | No | Total commission rate as a percentage of purchase price |
| `my_commission` | number | No | The authenticated agent's commission amount in USD |
| `representation_type` | string | No | Which side the agent represents (e.g. buyer, seller, dual) |
| `escrow_company` | string | No | Escrow company handling the transaction |
| `title_company` | string | No | Title company name |
| `buyers` | array of objects | No | Buyer parties to attach at creation |
| `buyers[].name` | string | No | Buyer's full name |
| `buyers[].email` | string | No | Buyer's email address |
| `sellers` | array of objects | No | Seller parties to attach at creation |
| `sellers[].name` | string | No | Seller's full name |
| `sellers[].email` | string | No | Seller's email address |

### Example request

```bash title="cURL"
curl -X POST "https://api.actuallycare.com/v1/escrows" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "property_address": "123 Main St, Bakersfield, CA 93301"
  }'
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "property_address": "123 Main St, Bakersfield, CA 93301"
  }),
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.actuallycare.com/v1/escrows",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "property_address": "123 Main St, Bakersfield, CA 93301"
    },
)
data = resp.json()
```

### Example response (201)

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "displayId": "ESC-2026-0001"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Escrow created |
| `400` | Invalid request data |
| `401` | Authentication required |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |

## Get an escrow

```http
GET /v1/escrows/{id}
```

Returns a single escrow. The ID may be a UUID, a display ID (ESC-2026-0001), or the user-scoped numeric sequence.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes | Escrow UUID, display ID, or numeric sequence |

### Example request

```bash title="cURL"
curl "https://api.actuallycare.com/v1/escrows/:id" \
  -H "X-API-Key: YOUR_API_KEY"
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows/:id", {
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.actuallycare.com/v1/escrows/:id",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = resp.json()
```

### Example response (200)

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "property_address": "123 Main St, Tehachapi, CA 93561",
    "city": "Tehachapi",
    "state": "CA",
    "zip_code": "93561",
    "purchase_price": 500000,
    "escrow_status": "active",
    "acceptance_date": "2025-01-15",
    "closing_date": "2025-03-01",
    "buyers": [
      {
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "(555) 123-4567"
      }
    ],
    "sellers": [
      {
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "(555) 123-4567"
      }
    ],
    "listing_agent": {
      "name": "Alex Rivera",
      "email": "agent@example.com",
      "phone": "+1 661 555 0123",
      "license": "DRE #02209852",
      "brokerage": "Associated Real Estate"
    },
    "selling_agent": {
      "name": "Alex Rivera",
      "email": "agent@example.com",
      "phone": "+1 661 555 0123",
      "license": "DRE #02209852",
      "brokerage": "Associated Real Estate"
    },
    "escrow_company": "First American Title",
    "escrow_officer": "Jane Smith",
    "property_type": "single_family",
    "bedrooms": 3,
    "bathrooms": 2.5,
    "square_feet": 2400,
    "lot_size": 0.25,
    "year_built": 2015,
    "contingencies": [
      {
        "type": "inspection",
        "due_date": "2026-07-15",
        "status": "pending"
      }
    ],
    "earnest_money": 10000,
    "commission_rate": 3,
    "notes": "example notes",
    "version": 1,
    "created_at": "2026-07-15T14:32:10.000Z",
    "updated_at": "2026-07-15T14:32:10.000Z",
    "last_modified_by": "550e8400-e29b-41d4-a716-446655440000"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The escrow |
| `401` | Authentication required |
| `404` | Resource not found |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |

## Update an escrow

```http
PUT /v1/escrows/{id}
```

Updates escrow fields. Pass the current `version` to enable optimistic-locking; a stale version returns 409.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes |  |

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `purchase_price` | number | No | Purchase price in USD |
| `closing_date` | string | No | Expected closing date (ISO 8601) · Format: date |
| `escrow_status` | enum | No | Updated escrow status · One of: `active`, `pending`, `closed`, `cancelled` |
| `version` | integer | No | Current record version for optimistic locking |

### Example request

```bash title="cURL"
curl -X PUT "https://api.actuallycare.com/v1/escrows/:id" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "purchase_price": 450000,
    "closing_date": "2026-07-15",
    "escrow_status": "active",
    "version": 3
  }'
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows/:id", {
  method: "PUT",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "purchase_price": 450000,
    "closing_date": "2026-07-15",
    "escrow_status": "active",
    "version": 3
  }),
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.put(
    "https://api.actuallycare.com/v1/escrows/:id",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "purchase_price": 450000,
        "closing_date": "2026-07-15",
        "escrow_status": "active",
        "version": 3
    },
)
data = resp.json()
```

### Example response (200)

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "property_address": "123 Main St, Tehachapi, CA 93561",
    "city": "Tehachapi",
    "state": "CA",
    "zip_code": "93561",
    "purchase_price": 500000,
    "escrow_status": "active",
    "acceptance_date": "2025-01-15",
    "closing_date": "2025-03-01",
    "buyers": [
      {
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "(555) 123-4567"
      }
    ],
    "sellers": [
      {
        "name": "John Doe",
        "email": "john@example.com",
        "phone": "(555) 123-4567"
      }
    ],
    "listing_agent": {
      "name": "Alex Rivera",
      "email": "agent@example.com",
      "phone": "+1 661 555 0123",
      "license": "DRE #02209852",
      "brokerage": "Associated Real Estate"
    },
    "selling_agent": {
      "name": "Alex Rivera",
      "email": "agent@example.com",
      "phone": "+1 661 555 0123",
      "license": "DRE #02209852",
      "brokerage": "Associated Real Estate"
    },
    "escrow_company": "First American Title",
    "escrow_officer": "Jane Smith",
    "property_type": "single_family",
    "bedrooms": 3,
    "bathrooms": 2.5,
    "square_feet": 2400,
    "lot_size": 0.25,
    "year_built": 2015,
    "contingencies": [
      {
        "type": "inspection",
        "due_date": "2026-07-15",
        "status": "pending"
      }
    ],
    "earnest_money": 10000,
    "commission_rate": 3,
    "notes": "example notes",
    "version": 1,
    "created_at": "2026-07-15T14:32:10.000Z",
    "updated_at": "2026-07-15T14:32:10.000Z",
    "last_modified_by": "550e8400-e29b-41d4-a716-446655440000"
  },
  "message": "Escrow updated successfully"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Escrow updated |
| `400` | Invalid request data |
| `401` | Authentication required |
| `404` | Resource not found |
| `409` | Version conflict (record changed since you read it) or business-rule violation |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |

## Delete an escrow

```http
DELETE /v1/escrows/{id}
```

Permanently deletes an escrow. The escrow must be archived first (PATCH /escrows/{id}/archive); deleting a non-archived escrow returns 400.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes |  |

### Example request

```bash title="cURL"
curl -X DELETE "https://api.actuallycare.com/v1/escrows/:id" \
  -H "X-API-Key: YOUR_API_KEY"
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows/:id", {
  method: "DELETE",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.delete(
    "https://api.actuallycare.com/v1/escrows/:id",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = resp.json()
```

### Example response (200)

```json
{
  "success": true,
  "message": "Escrow permanently deleted",
  "data": {
    "displayId": "ESC-2026-0847"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Escrow deleted |
| `400` | Escrow is not archived — archive it before deleting |
| `401` | Authentication required |
| `404` | Resource not found |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |

## Archive an escrow

```http
PATCH /v1/escrows/{id}/archive
```

Moves an escrow to the archive. Archived escrows are hidden from default lists, can be restored at any time, and are the only escrows eligible for permanent deletion.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes |  |

### Example request

```bash title="cURL"
curl -X PATCH "https://api.actuallycare.com/v1/escrows/:id/archive" \
  -H "X-API-Key: YOUR_API_KEY"
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows/:id/archive", {
  method: "PATCH",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.patch(
    "https://api.actuallycare.com/v1/escrows/:id/archive",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = resp.json()
```

### Example response (200)

```json
{
  "success": true,
  "message": "Escrow archived successfully",
  "data": {
    "displayId": "ESC-2026-0847"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Escrow archived |
| `401` | Authentication required |
| `404` | Resource not found |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |

## Restore an archived escrow

```http
PATCH /v1/escrows/{id}/restore
```

Returns an archived escrow to the active list.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes |  |

### Example request

```bash title="cURL"
curl -X PATCH "https://api.actuallycare.com/v1/escrows/:id/restore" \
  -H "X-API-Key: YOUR_API_KEY"
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows/:id/restore", {
  method: "PATCH",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.patch(
    "https://api.actuallycare.com/v1/escrows/:id/restore",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = resp.json()
```

### Example response (200)

```json
{
  "success": true,
  "message": "Escrow restored successfully",
  "data": {
    "displayId": "ESC-2026-0847"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Escrow restored |
| `401` | Authentication required |
| `404` | Resource not found |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |

## Get an escrow's timeline

```http
GET /v1/escrows/{id}/timeline
```

Returns the escrow's milestone timeline (deposits, contingencies, closing) with target dates, completion state, and a computed status for each milestone.

### Parameters

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | Yes |  |

### Example request

```bash title="cURL"
curl "https://api.actuallycare.com/v1/escrows/:id/timeline" \
  -H "X-API-Key: YOUR_API_KEY"
```

```javascript title="JavaScript"
const res = await fetch("https://api.actuallycare.com/v1/escrows/:id/timeline", {
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.actuallycare.com/v1/escrows/:id/timeline",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = resp.json()
```

### Example response (200)

```json
{
  "success": true,
  "data": [
    {
      "key": "example key",
      "label": "example label",
      "date": "2026-07-15T14:32:10.000Z",
      "completed": true,
      "completedDate": "2026-07-15T14:32:10.000Z",
      "status": "active",
      "sortOrder": 1
    }
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Timeline milestones in display order |
| `401` | Authentication required |
| `404` | Resource not found |
| `429` | Rate limit exceeded — too many requests in the current window. Wait for the window to reset (see Retry-After) before retrying. |
| `500` | Internal server error |
