# Async Endpoints V1 — Developer Guide

These endpoints retrieve records **asynchronously**. When called, they return the first 10 matching results immediately in the HTTP response body, while simultaneously streaming all matching records to the Streaming API using a routing key.

Async requests are limited to a `pageSize` of 10 for the immediate response. All async endpoints require an `Organization-ID` header.

The following async endpoints are available:

- [GET /v1/patients/async](#get--v1patients-async)
- [GET /v1/events/async](#get--v1events-async)
- [GET /v1/appointments/async](#get--v1appointments-async)
- [GET /v1/imageattachments/async](#get--v1imageattachments-async)
- [GET /v1/locationproductionnetschedule/async](#get--v1locationproductionnetschedule-async)


## GET — /v1/patients/async

> **Reference:** [Patients (V1) Endpoint Documentation](https://papidocs.hs1api.com/publicapi/api-patient-management/patients-(v1))


Retrieves patients asynchronously. Returns the first 10 results immediately and streams all matching records to the Streaming API.

### Parameters

| Parameter | In | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `Organization-ID` | header | Yes | string | Your organization identifier |
| `filter` | query | No | string | Filter expression. See [Filter Keys](#patients-filter-keys) below |
| `responseFields` | query | No | string | URL-encoded comma-delimited list of fields to return. Use `ALL` for all fields |
| `lastId` | query | No | string | The largest `patientId` from the previous page — used for cursor-based pagination |
| `page` | query | No | string | Page number for offset-based pagination |
| `pageSize` | query | No | string | Page size — limited to `10` for async requests |


#### Patients Filter Keys

| Filter Key | Supported Operators |
|  --- | --- |
| `firstName` | `==`, `!=`, `~=`, `<>=` |
| `lastName` | `==`, `!=`, `~=`, `<>=` |
| `gender` | `==`, `!=` |
| `preferredName` | `==`, `!=`, `~=`, `<>=` |
| `dateOfBirth` | `==`, `!=` |
| `patientStatus` | `==`, `!=` |
| `phones.number` | `==`, `!=`, `->` |
| `emailAddress` | `==` |
| `chartNumber` | `==`, `.absent`, `.present` |
| `preferredLocation.id` | `==`, `!=`, `->` |
| `primaryGuarantor.id` | `==` |
| `duplicateOfPatient.id` | `==` |
| `primaryContact.id` | `==` |
| `firstVisitDate` | `==`, `>`, `>=`, `<`, `<=` |
| `lastModified` | `>`, `>=`, `<`, `<=` |
| `referredByPatient.id` | `==`, `!=`, `->` |
| `referredByReferral.id` | `==`, `!=`, `->` |


> **Note:** `patientStatus` valid values: `NEW`, `ACTIVE`, `NON-PATIENT`, `INACTIVE`, `DUPLICATE`, `DISMISSED`, `DECEASED`. `gender` valid values: `M`, `F`, `O`.


> **Ordering:** Results on this async endpoint are returned in **descending** `id` order (newest first). The synchronous **`GET /v1/patients`** bulk endpoint pages by ascending `id`. See [Patients V1 — Developer Guide](/publicapi/endpoints/patients-v1) for the full bulk GET filter list (including `id->[…]`, which is documented on sync bulk GET but not listed here).


> **Upcoming Breaking Change:** `preferredLocation.id` (as a list of IDs or `["ALL"]`) will become a **required** filter. Omitting it currently defaults to all locations.


> **Date-limiting filters:** If you do not supply a date-limiting filter, one may be applied automatically using `lastModified`. Supply your own date bound for predictable results. The following filter keys count as date-limiting: **`lastModified`**, **`createdDate`**, and **`updatedDate`**.


### Example Requests

Fetch all patients modified after a date:

```
GET /api/v1/patients/async?filter=lastModified>=2025-01-01T00:00:00Z,preferredLocation.id->[64000000000004]
```

Paginate using `lastId`:

```
GET /api/v1/patients/async?lastId=22000012345678&filter=lastModified>=2025-01-01T00:00:00Z,preferredLocation.id->[64000000000004]
```

## GET — /v1/events/async

> **Reference:** [Events (V1) Endpoint Documentation](https://papidocs.hs1api.com/publicapi/api-appointment-management/events-(v1))


Retrieves events asynchronously. Returns the first 10 results immediately and streams all matching records to the Streaming API.

For full Events V1 documentation — including all filter keys, create/update/delete semantics, recurrence, and field reference — see the [Events V1 — Developer Guide](/publicapi/endpoints/events-v1).

### Parameters

| Parameter | In | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `Organization-ID` | header | Yes | string | Your organization identifier |
| `filter` | query | No | string | Filter expression. Same keys as [GET /v1/events](/publicapi/endpoints/events-v1#filter-keys) |
| `responseFields` | query | No | string | URL-encoded comma-delimited list of fields to return. Use `ALL` for all fields |
| `lastId` | query | No | string | The largest `eventId` from the previous page — used for cursor-based pagination |
| `page` | query | No | string | Page number for offset-based pagination |
| `pageSize` | query | No | string | Page size — limited to `10` for async requests |


### Example Requests

Fetch events modified after a date at a specific location:

```
GET /api/v1/events/async?filter=lastModified>=2025-01-01T00:00:00Z,location.id->[64000000000004]
```

Paginate using `lastId`:

```
GET /api/v1/events/async?lastId=500&filter=lastModified>=2025-01-01T00:00:00Z,location.id->[64000000000004]
```

## GET — /v1/appointments/async

> **Reference:** [Appointments (V1) Endpoint Documentation](https://papidocs.hs1api.com/publicapi/api-appointment-management/appointments-(v1))


Retrieves appointments asynchronously. Returns the first 10 results immediately and streams all matching records to the Streaming API.

### Parameters

| Parameter | In | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `Organization-ID` | header | Yes | string | Your organization identifier |
| `filter` | query | No | string | Filter expression. See [Filter Keys](#appointments-filter-keys) below |
| `responseFields` | query | No | string | URL-encoded comma-delimited list of fields to return. Use `ALL` for all fields |
| `lastId` | query | No | string | The largest `appointmentId` from the previous page — used for cursor-based pagination |
| `page` | query | No | string | Page number for offset-based pagination |
| `pageSize` | query | No | string | Page size — limited to `10` for async requests |


#### Appointments Filter Keys

| Filter Key | Supported Operators |
|  --- | --- |
| `id` | `->` |
| `needsFollowUp` | `==`, `!=` |
| `status` | `==`, `!=` |
| `patient.id` | `==`, `!=` |
| `operatory.id` | `==`, `!=`, `->` |
| `location.id` | `==`, `!=`, `->` |
| `provider.id` | `==`, `!=`, `->` |
| `asap` | `==` |
| `start` | `>`, `>=`, `<`, `<=` |
| `lastModified` | `>`, `>=`, `<`, `<=` |


> **Upcoming Breaking Change:** `location.id` (as a list of IDs or `["ALL"]`) will become a **required** filter. Omitting it currently defaults to all locations.


> **Note:** `status` valid values: `LATE`, `HERE`, `READY`, `CHAIR`, `COMPLETED`, `CONFIRMED`, `UNCONFIRMED`, `NO_SHOW`, `BROKEN`, `LEFT_MESSAGE`, `CHECKOUT`, `WILL_CALL`, `UNREACHABLE`, `CANCELLEDBYOFFICE`.


### Example Requests

Fetch appointments modified after a date at a specific location:

```
GET /api/v1/appointments/async?filter=lastModified>=2025-01-01T00:00:00Z,location.id->[64000000000004]
```

Paginate using `lastId`:

```
GET /api/v1/appointments/async?lastId=8000052360370&filter=lastModified>=2025-01-01T00:00:00Z,location.id->[64000000000004]
```

## GET — /v1/imageattachments/async

> **Reference:** [ImageAttachments (V1) Endpoint Documentation](https://papidocs.hs1api.com/publicapi/api-document-management/imageattachments-(v1))


Returns a list of image attachments with async support via the Streaming API.

> **Note:** Async retrieval for image attachments is **only** available via this `/async` endpoint. The regular `/v1/imageattachments` endpoint does not support async or streaming.


### Parameters

| Parameter | In | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `Organization-ID` | header | Yes | string | Your organization identifier |
| `filter` | query | No | string | Filter expression. See [Filter Keys](#imageattachments-filter-keys) below |
| `responseFields` | query | No | string | URL-encoded comma-delimited list of fields to return. Use `ALL` for all fields |
| `lastId` | query | No | string | The largest image attachment ID from the previous page — used for cursor-based pagination |
| `page` | query | No | string | Page number for offset-based pagination |
| `pageSize` | query | No | string | Page size — limited to `10` for async requests |


#### ImageAttachments Filter Keys

| Filter Key | Supported Operators |
|  --- | --- |
| `id` | `==`, `->` |
| `insuranceClaim.id` | `==`, `->` |


### Example Requests

Fetch image attachments by insurance claim:

```
GET /api/v1/imageattachments/async?filter=insuranceClaim.id==456
```

Fetch a specific set of attachments by ID:

```
GET /api/v1/imageattachments/async?filter=id->[123,124,125]
```

## GET — /v1/locationproductionnetschedule/async

> **Reference:** [Production Net Schedule Report (V1) Endpoint Documentation](https://papidocs.hs1api.com/publicapi/api-reports-and-analytics/locationproductionnetschedule-(v1))


Returns production total net schedule reports asynchronously based on filter criteria.

### Parameters

| Parameter | In | Required | Type | Description |
|  --- | --- | --- | --- | --- |
| `Organization-ID` | header | Yes | string | Your organization identifier |
| `filter` | query | **Yes** | string | Filter expression. `fromDate` is **required**. See [Filter Keys](#locationproductionnetschedule-filter-keys) below |
| `responseFields` | query | No | string | URL-encoded comma-delimited list of fields to return. Use `ALL` for all fields |


#### LocationProductionNetSchedule Filter Keys

| Filter Key | Supported Operators | Required | Notes |
|  --- | --- | --- | --- |
| `fromDate` | `==` | **Yes** | Start date for the report (e.g. `2025-01-14`) |
| `location.id` | `==`, `->` | No | Filter by location. Defaults to all locations. Will become required in a future release |
| `provider.id` | `==`, `->` | No | Mutually exclusive with `patient.id` and `appointment.id` |
| `patient.id` | `==`, `->` | No | Mutually exclusive with `provider.id` and `appointment.id` |
| `appointment.id` | `==`, `->` | No | Mutually exclusive with `provider.id` and `patient.id` |
| `range` | `==` | No | Number of days for the report window. Maximum `31` |
| `timezone` | `==` | No | Timezone for the report (e.g. `America/New_York`). Defaults to organization timezone |
| `isPrimaryWriteOff` | `==` | No | **Deprecated** — do not use in new implementations |


> **Note:** `provider.id`, `patient.id`, and `appointment.id` are mutually exclusive — only one may be used per request.


> **Upcoming Breaking Change:** `location.id` (as a list of IDs or `["ALL"]`) will become a **required** filter. Omitting it currently defaults to all locations.


### Example Requests

Fetch production net schedule report for a date range at a location:

```
GET /api/v1/locationproductionnetschedule/async?filter=fromDate==2025-01-14,range==7,location.id->[64000000000004]
```

Fetch report for a specific provider:

```
GET /api/v1/locationproductionnetschedule/async?filter=fromDate==2025-01-14,provider.id==789
```

## Response Structure

All async endpoints return a `200` response with the following top-level structure:

| Field | Type | Description |
|  --- | --- | --- |
| `data` | array | The first 10 matching records. All remaining records are streamed via the Streaming API |
| `warnings` | array | Non-fatal warnings (operation still succeeded) |
| `errors` | array | Field-level or structural errors |


## Paginating with `lastId`

`lastId` is the recommended approach for iterating through large result sets on async endpoints. It uses the record's `id` as a cursor rather than an offset.

### Step 1 — Initial Request

Send your first request without `lastId`:

```
GET /api/v1/patients/async?filter=lastModified>=2025-01-01T00:00:00Z,preferredLocation.id->[64000000000004]
```

### Step 2 — Subsequent Requests

Take the `id` of the **last record** in the returned `data` array and pass it as `lastId` in the next request:

```
GET /api/v1/patients/async?lastId=22000012345678&filter=lastModified>=2025-01-01T00:00:00Z,preferredLocation.id->[64000000000004]
```

### Step 3 — Repeat

Continue until the response returns an empty `data` array or no-more-data indicator.

## Streaming API

Async endpoints deliver the complete result set to the **Streaming API** in parallel with the immediate HTTP response. To consume the streamed data, your application must be subscribed to the Streaming API.

See the [Streaming API Webhooks Setup Guide](/publicapi/streamapi-webhooks-setup) for full setup instructions.

## Errors & Warnings Reference

details
summary
strong
HTTP Status Code Errors
— click to expand
These apply to all Async V1 endpoints.

#### `400` — Bad Request

The request query parameters are invalid or cannot be processed. Check that all required filters are provided and values are the correct type.

#### `401` — Unauthorized

|  |  |
|  --- | --- |
| **Message** | Authentication is required and has failed or has not been provided. |
| **Why** | No valid auth token was sent, the token is expired, or the token is malformed. |
| **Fix** | Provide a valid Bearer token in the `Authorization` header. |


#### `403` — Forbidden

|  |  |
|  --- | --- |
| **Message** | The request is understood, but it has been refused or access is not allowed. |
| **Why** | The authenticated token does not have the required scope. Read operations require `model:read`. |
| **Fix** | Request a token that includes the `model:read` scope. |


#### `404` — Not Found

|  |  |
|  --- | --- |
| **Message** | The requested resource is either missing or does not exist. |
| **Why** | No records matching the provided filters exist within your organization. |
| **Fix** | Confirm your filter values are correct and belong to your organization. |


#### `408` — Request Timeout

|  |  |
|  --- | --- |
| **Message** | The server timed out while processing the request. |
| **Why** | The server took too long to respond, often due to high server load. |
| **Fix** | Retry the request. If the issue persists, contact support with the request details and timestamp. |


#### `429` — Too Many Requests

|  |  |
|  --- | --- |
| **Message** | Rate limit exceeded. |
| **Why** | Your client has made too many requests in a short period of time. |
| **Fix** | Implement exponential backoff and retry logic. Reduce request frequency. See the [rate limiting guide](https://papidocs.hs1api.com/publicapi/api-consumer-guide#rate-limiting). |


#### `500` — Internal Server Error

|  |  |
|  --- | --- |
| **Message** | An unexpected error occurred. |
| **Why** | An unhandled server-side error occurred. |
| **Fix** | Retry the request. If the issue persists, contact support with the request details and timestamp. |