Services
Track and manage pool service visits and records
Overview
Services represent individual service visits performed for customers. Each service tracks the customer, technician assignments, appointment details, chemical readings, water observations, photos, and billing status. Services are categorized by a type reference whose display fields are display (name) and desc (description).
List Services (Cursor-Based)
Retrieve a cursor-based paginated list of services using infiniteServices. All filtering and search options are passed via the selector argument which wraps filters, search, include, and exclude.
query InfiniteServices(
$selector: ServicesSelector
$sort: ServiceSort
$first: Int!
$after: String
) {
infiniteServices(
selector: $selector
sort: $sort
first: $first
after: $after
) {
edges {
node {
id
reference
startTime
endTime
billingStatus
customer {
id
firstName
lastName
}
type {
id
display
desc
}
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}
# Variables
{
"first": 20,
"selector": {
"filters": {
"customerId": { "equals": "cust_456" },
"startTime": { "gte": "2024-01-01T00:00:00Z" }
},
"search": "pool cleaning"
}
}Response:
{
"data": {
"infiniteServices": {
"edges": [
{
"node": {
"id": "svc_001",
"reference": "SVC-20240115-001",
"startTime": "2024-01-15T09:00:00Z",
"endTime": "2024-01-15T10:30:00Z",
"billingStatus": "INVOICED",
"customer": {
"id": "cust_456",
"firstName": "John",
"lastName": "Smith"
},
"type": {
"id": "type_001",
"display": "Pool Cleaning",
"desc": "Standard weekly pool cleaning service"
}
},
"cursor": "eyJpZCI6InN2Y18wMDEifQ=="
}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "eyJpZCI6InN2Y18wMDEifQ=="
}
}
}
}List Services (Offset-Based)
Retrieve an offset-based paginated list of services using paginatedServices. Uses the same ServicesSelector for filtering and search, with limit and offset for pagination.
query PaginatedServices(
$selector: ServicesSelector
$sort: ServiceSort
$limit: Int!
$offset: Int!
) {
paginatedServices(
selector: $selector
sort: $sort
limit: $limit
offset: $offset
) {
items {
id
reference
startTime
endTime
billingStatus
customer {
id
firstName
lastName
}
type {
id
display
}
}
totalCount
}
}
# Variables
{
"limit": 20,
"offset": 0,
"selector": {
"filters": {
"billingStatus": { "equals": "UNINVOICED" },
"newTechnicianId": { "equals": "tech_123" }
}
}
}Response:
{
"data": {
"paginatedServices": {
"items": [
{
"id": "svc_003",
"reference": "SVC-20240120-003",
"startTime": "2024-01-20T08:00:00Z",
"endTime": "2024-01-20T09:15:00Z",
"billingStatus": "UNINVOICED",
"customer": {
"id": "cust_789",
"firstName": "Jane",
"lastName": "Doe"
},
"type": {
"id": "type_001",
"display": "Pool Cleaning"
}
}
],
"totalCount": 15
}
}
}REST Endpoints
Upload service photos.
/services/:id/photosUpload a photo for a service
curl -X POST "https://api.poolservicemanager.com/services/svc_001/photos" \
-H "Authorization: Bearer pom_live_<your_api_key>" \
-F "file=@photo.jpg" \
-F "caption=Pool after cleaning"Bulk & Export Operations
Exporting or bulk-editing many services at once is handled asynchronously through the Bulk Operations API. These jobs run in the background and report progress you can poll. See the Bulk Operations guide for the full workflow.
Field Reference
| Field | Type | Description |
|---|---|---|
id | ID! | Unique identifier |
reference | String(nullable) | Service reference number |
customerId | String(nullable) | Associated customer ID |
customer | Customer(nullable) | Customer this service was performed for |
type | TypeEntity(nullable) | Service type (use `display` for name, `desc` for description) |
typeId | String(nullable) | Service type ID |
newTechnicianId | String(nullable) | Primary technician ID |
newSecondaryTechnicianId | String(nullable) | Secondary technician ID |
appointmentId | String(nullable) | Associated appointment ID |
appointmentIdentifierCuid | String(nullable) | Appointment identifier CUID |
appointmentRecurringRuleId | String(nullable) | Recurring rule ID for the appointment |
startTime | DateTime(nullable) | Service start time |
endTime | DateTime(nullable) | Service end time |
returnAppointmentDate | DateTime(nullable) | Scheduled return appointment date |
billingStatus | String(nullable) | Billing status of the service |
flag | String(nullable) | Service flag |
vacuum | String(nullable) | Vacuum status |
waterLevel | String(nullable) | Water level reading |
waterCondition | String(nullable) | Water condition assessment |
waterColor | String(nullable) | Water color observation |
photos | [ServicePhoto!]! | Service photos |
notes | String(nullable) | Service notes |
chemicalReadings | ChemicalReading(nullable) | Pool chemical readings |
dateEmailed | DateTime(nullable) | When the service report was emailed |
dateTexted | DateTime(nullable) | When the service report was texted |
createdAt | DateTime! | Creation timestamp |
updatedAt | DateTime! | Last update timestamp |
ServicesSelector
The selector wraps all query parameters for service list queries. Both infiniteServices and paginatedServices accept this selector.
| Field | Type | Description |
|---|---|---|
filters | ServiceFilter(nullable) | Filter criteria for services |
search | String(nullable) | Search string (max 600 characters) |
include | [String](nullable) | Service IDs to explicitly include in results |
exclude | [String](nullable) | Service IDs to explicitly exclude from results |
ServiceFilter
Available filter fields within ServicesSelector.filters. String filters support equals and contains operators. DateTime filters support gte, lte, and equals operators.
| Field | Type | Description |
|---|---|---|
id | IdFilter(nullable) | Filter by service ID |
reference | StringFilter(nullable) | Filter by reference number |
customerId | StringFilter(nullable) | Filter by customer ID (supports contains/equals) |
newTechnicianId | StringFilter(nullable) | Filter by primary technician ID |
newSecondaryTechnicianId | StringFilter(nullable) | Filter by secondary technician ID |
appointmentId | StringFilter(nullable) | Filter by appointment ID |
appointmentIdentifierCuid | StringFilter(nullable) | Filter by appointment identifier CUID |
appointmentRecurringRuleId | StringFilter(nullable) | Filter by recurring rule ID |
startTime | DateTimeFilter(nullable) | Filter by service start time |
endTime | DateTimeFilter(nullable) | Filter by service end time |
returnAppointmentDate | DateTimeFilter(nullable) | Filter by return appointment date |
billingStatus | StringFilter(nullable) | Filter by billing status |
flag | StringFilter(nullable) | Filter by flag |
typeId | StringFilter(nullable) | Filter by service type ID |
dateEmailed | DateTimeFilter(nullable) | Filter by date emailed |
dateTexted | DateTimeFilter(nullable) | Filter by date texted |
vacuum | StringFilter(nullable) | Filter by vacuum status |
waterLevel | StringFilter(nullable) | Filter by water level |
waterCondition | StringFilter(nullable) | Filter by water condition |
waterColor | StringFilter(nullable) | Filter by water color |
customerTags | IDFilter(nullable) | Filter by customer tags |
customerReadyForInvoice | BooleanFilter(nullable) | Filter by customer ready-for-invoice status |
notification | [NotificationStatusEnum](nullable) | Filter by notification status |
technicians | [String](nullable) | Filter by technician IDs |