Quotes

Create and manage service quotes for customers

Overview

Quotes allow you to propose work to customers before performing services. They include detailed line items, photos, and can be converted to invoices once accepted. Quotes can be sent via email and tracked through their lifecycle.

List Quotes

Retrieve a paginated list of quotes with filtering.

query InfiniteQuotes($first: Int!, $after: String, $filter: QuoteFilter) {
  infiniteQuotes(first: $first, after: $after, filter: $filter) {
    edges {
      node {
        id
        number
        title
        status
        total
        validUntil
        customer {
          id
          firstName
          lastName
        }
      }
      cursor
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

# Variables
{
  "first": 20,
  "filter": {
    "status": "SENT",
    "customerId": "cust_456"
  }
}

Response:

{
  "data": {
    "infiniteQuotes": {
      "edges": [
        {
          "node": {
            "id": "quote_001",
            "number": "QUO-2024-0001",
            "title": "Pool Renovation Project",
            "status": "SENT",
            "total": 5500.00,
            "validUntil": "2024-02-15T00:00:00Z",
            "customer": {
              "id": "cust_456",
              "firstName": "John",
              "lastName": "Smith"
            }
          },
          "cursor": "eyJpZCI6InF1b3RlXzAwMSJ9"
        }
      ],
      "pageInfo": {
        "hasNextPage": false,
        "endCursor": "eyJpZCI6InF1b3RlXzAwMSJ9"
      }
    }
  }
}

Get Single Quote

Retrieve a single quote with all details.

query Quote($selector: QuoteSelector!) {
  quote(selector: $selector) {
    id
    number
    title
    status
    subtotal
    tax
    total
    validUntil
    acceptedAt
    customer {
      id
      firstName
      lastName
      email
    }
    lineItems {
      id
      description
      quantity
      unitPrice
      amount
    }
    notes
    terms
    photos {
      id
      url
      caption
    }
    pdfUrl
    createdAt
    updatedAt
  }
}

# Variables
{
  "selector": {
    "id": "quote_001"
  }
}

Response:

{
  "data": {
    "quote": {
      "id": "quote_001",
      "number": "QUO-2024-0001",
      "title": "Pool Renovation Project",
      "status": "SENT",
      "subtotal": 5000.00,
      "tax": 500.00,
      "total": 5500.00,
      "validUntil": "2024-02-15T00:00:00Z",
      "acceptedAt": null,
      "customer": {
        "id": "cust_456",
        "firstName": "John",
        "lastName": "Smith",
        "email": "john@example.com"
      },
      "lineItems": [
        {
          "id": "qli_001",
          "description": "Pool resurfacing",
          "quantity": 1,
          "unitPrice": 3500.00,
          "amount": 3500.00
        },
        {
          "id": "qli_002",
          "description": "New pool pump installation",
          "quantity": 1,
          "unitPrice": 1500.00,
          "amount": 1500.00
        }
      ],
      "notes": "Work to be completed within 2 weeks of acceptance",
      "terms": "50% deposit required. Balance due upon completion.",
      "photos": [
        {
          "id": "photo_001",
          "url": "https://storage.example.com/quotes/photo_001.jpg",
          "caption": "Current pool condition"
        }
      ],
      "pdfUrl": "https://storage.example.com/quotes/quote_001.pdf",
      "createdAt": "2024-01-15T10:00:00Z",
      "updatedAt": "2024-01-16T09:00:00Z"
    }
  }
}

Create Quote

Create a new quote for a customer.

mutation CreateQuote($input: CreateQuoteInput!) {
  createQuote(input: $input) {
    id
    number
    title
    status
    total
    customer {
      id
      firstName
      lastName
    }
    createdAt
  }
}

# Variables
{
  "input": {
    "customerId": "cust_456",
    "title": "Equipment Upgrade",
    "validUntil": "2024-03-01T00:00:00Z",
    "lineItems": [
      {
        "description": "Variable speed pump",
        "quantity": 1,
        "unitPrice": 800.00
      },
      {
        "description": "Installation labor",
        "quantity": 4,
        "unitPrice": 75.00
      }
    ],
    "taxId": "tax_001",
    "notes": "Energy-efficient upgrade recommended"
  }
}

Response:

{
  "data": {
    "createQuote": {
      "id": "quote_002",
      "number": "QUO-2024-0002",
      "title": "Equipment Upgrade",
      "status": "DRAFT",
      "total": 1210.00,
      "customer": {
        "id": "cust_456",
        "firstName": "John",
        "lastName": "Smith"
      },
      "createdAt": "2024-01-20T14:00:00Z"
    }
  }
}

Update Quote Status

Update quote status (e.g., mark as accepted).

mutation UpdateQuote($id: ID!, $input: UpdateQuoteInput!) {
  updateQuote(id: $id, input: $input) {
    id
    status
    acceptedAt
    updatedAt
  }
}

# Variables
{
  "id": "quote_001",
  "input": {
    "status": "ACCEPTED"
  }
}

Response:

{
  "data": {
    "updateQuote": {
      "id": "quote_001",
      "status": "ACCEPTED",
      "acceptedAt": "2024-01-25T11:00:00Z",
      "updatedAt": "2024-01-25T11:00:00Z"
    }
  }
}

REST Endpoints

Upload photos and PDFs, export quotes.

POST/quotes/:id/photos

Upload a photo for a quote

curl -X POST "https://api.poolservicemanager.com/quotes/quote_001/photos" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -F "file=@photo.jpg" \
  -F "caption=Current condition"
POST/quotes/:id/pdf

Upload a custom PDF for the quote

curl -X POST "https://api.poolservicemanager.com/quotes/quote_001/pdf" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -F "file=@quote.pdf"
GET/quotes/export/csv

Export quotes to CSV format

curl -X GET "https://api.poolservicemanager.com/quotes/export/csv?startDate=2024-01-01" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -o quotes.csv

Field Reference

FieldTypeDescription
idID!Unique identifier
numberString!Quote number
titleString!Quote title
customerCustomer!Customer receiving the quote
statusQuoteStatus!Status (DRAFT, SENT, ACCEPTED, DECLINED, EXPIRED)
subtotalFloat!Subtotal before tax
taxFloat!Tax amount
totalFloat!Total amount
validUntilDateTime(nullable)Quote expiration date
acceptedAtDateTime(nullable)When quote was accepted
lineItems[QuoteLineItem!]!Quote line items
notesString(nullable)Quote notes
termsString(nullable)Terms and conditions
photos[QuotePhoto!]!Attached photos
pdfUrlString(nullable)Generated PDF URL
createdAtDateTime!Creation timestamp
updatedAtDateTime!Last update timestamp