API Reference

Get Proposal Documents

🚀

Try our GraphQL Playground

We've included some static documentation below, however GraphQL APIs are traditionally represented through interactive playgrounds. HOVER GraphQL Playground

Introduction

A contractor generates a proposal for the customer based on a selected salesOpportunity or estimateGroup. When a proposal is created, a corresponding PDF is generated. This PDF can be shared with the customer via an embedded on screen signature or shared via email. When a proposal document PDF is created or updated, HOVER sends a webhook with the event, order document id, state, and timestamp.

Webhooks

project-management-proposal-document-state-changed Event

When a project management proposal document has been created, you will receive a webhook with the following post body.

Why would I use this?

Receiving an event notifying you that a proposal document is completed allows you to look at the ID of the document to hit our API to download it to , maybe, your CRM, or to your sales persons personal computer to show a customer.

{ 
  "event": "project-management-proposal-document-state-changed",
  "project_management_proposal_document_id": "d69021ae-2ebb-457d-b645-b70e6e26a903",
  "state": "complete"
}

project-management-signature-request-state-changed Event

When a project management signature request has been created, you will receive a webhook with the following post body. The signed_at field value is seconds since the epoch. Please note that a project-management-signature-request-state-changed event signed_at will only be sent when the state is signed or complete.

{
  "event": "project-management-signature-request-state-changed",
  "project_management_signature_request_id": "b37dfabb-c0f4-4d75-a753-450f819e27af",
  "project_management_proposal_document_id": "ea253901-01a3-4b43-94f1-98802ae8496b",
  "state": "signed",
  "signed_at": 1598555054
}

Signed Proposals

Once a proposal is signed, the proposal document PDF gets updated with the customer signature. When a proposal document PDF is created or updated, HOVER sends a webhook with the event, proposal document ID, state, and timestamp.

This webhook will also be used to indicate when a SignatureRequest was made, based on the signedAt timestamp and state fields.

Queries

projectManagementProposalDocuments

This query will return all the proposal documents associated with an estimate.

{
  projectManagementProposalDocuments(estimateGroupId: {estimate_group_id}) {
    nodes{
      id
      createdAt
      updatedAt
      signatureRequest {
        createdAt
        signedAt
      }
      pdf{
        redirectUrl
      }
    }
  }
}
{
  "data": {
    "projectManagementProposalDocuments": {
      "nodes": [
        {
          "id": "e0bf7161-3812-4c8d-8d7f-bb11237bb1b7",
          "createdAt": "2020-06-25T08:54:08Z",
          "updatedAt": "2020-06-25T08:55:16Z",
          "signatureRequest": {
            "createdAt": "2020-06-25T08:54:25Z",
            "signedAt": null
          },
          "pdf": {
            "redirectUrl": "redirectUrl"
          }
        },
        // ... other documents ...  //
      ]
    }
  }
}
curl -X POST "https://graph.hover.to/graphql" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{"query": "{ projectManagementProposalDocuments(estimateGroupId: \"estimate_group_id\") { nodes { id createdAt updatedAt signatureRequest { createdAt signedAt } pdf { redirectUrl } } } }"}'
Request:
  Method: POST
  URL: https://graph.hover.to/graphql
  Headers:
    Content-Type: application/json
    Authorization: Bearer YOUR_ACCESS_TOKEN
  Body:
    Type: Raw (JSON)
    Content:
      {
        "query": "{ projectManagementProposalDocuments(estimateGroupId: \"estimate_group_id\") { nodes { id createdAt updatedAt signatureRequest { createdAt signedAt } pdf { redirectUrl } } } }"
      }

Filtering Arguments

You can specify arguments when querying proposal documents. These arguments are entered in the query as shown below:

projectManagementProposalDocuments(last: 30, state: COMPLETE)

ArgumentDescription
afterReturns the elements in the list that come after the specified cursor
beforeReturns the elements in the list that come before the specified cursor
firstReturns the first n elements from the list
lastReturns the last n elements from the list
salesOpportunityIdOnly return records for this sales opportunity
estimateGroupIdOnly return records for this estimate group
stateReturn documents at given state

Get a Proposal Document Details

This example query using projectManagementProposalDocuments will return all available details of a specific proposal document.

{
  projectManagementProposalDocument(id: proposal_document_id) {
    id
    createdAt
    userId
    customerName
    customerEmail
    state
    totalPrice
    pdf {
      redirectUrl
    }
    signatureRequest {
      createdAt
      requestType
      signedAt
      state
    }
    estimateGroup {
      salesOpportunity {
        id
        createdAt
        updatedAt
        soldEstimateGroupId
        productionList {
          id
        }
      }
      jobId
      orgId
      estimates {
        name
        tradeType
        active
        userId
        discount
        discounts {
          name
          value
          discountType
        }
      }
    }
  }
}
{
  "data": {
    "projectManagementProposalDocument": {
      "id": "e0bf7161-3812-4c8d-8d7f-bb11237bb1b7",
      "createdAt": "2020-06-25T08:54:08Z",
      "userId": 549941,
      "customerName": "John Smith",
      "customerEmail": "[email protected]",
      "state": "COMPLETE",
      "totalPrice": 31851.32333,
      "pdf": {
        "redirectUrl": "redirectUrl"
      },
      "signatureRequest": {
        "createdAt": "2020-06-25T08:54:25Z",
        "requestType": "EMBED",
        "signedAt": null,
        "state": "COMPLETE"
      },
      "estimateGroup": {
        "salesOpportunity": {
          "id": 17659,
          "createdAt": "2020-06-25T08:52:02Z",
          "updatedAt": "2020-06-25T09:09:00Z",
          "soldEstimateGroupId": "228457",
          "productionList": {
            "id": 6943
          }
        },
        "jobId": "2210684",
        "orgId": "301438",
        "estimates": [
          {
            "name": "GAF Timberline American Harvest (Roof)",
            "tradeType": "ROOF",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "GAF - Grand Sequoia (Roof)",
            "tradeType": "ROOF",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Standard (Skylights)",
            "tradeType": "SKYLIGHTS",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Custom (Skylights)",
            "tradeType": "SKYLIGHTS",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Vinyl (Windows)",
            "tradeType": "WINDOWS",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Custom (Windows)",
            "tradeType": "WINDOWS",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Wood & Plastic (Door)",
            "tradeType": "DOOR",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Specialty (Door)",
            "tradeType": "DOOR",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Gutters (With Roof Discount)",
            "tradeType": "GUTTERS",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Gutters + Toppers (with discount)",
            "tradeType": "GUTTERS",
            "active": false,
            "userId": 549941,
            "discount": 0,
            "discounts": []
          },
          {
            "name": "Standard (Fascia)",
            "tradeType": "FASCIA",
            "active": true,
            "userId": 549941,
            "discount": 6.15,
            "discounts": [
              {
                "name": "promo",
                "value": 10,
                "discountType": "PERCENTAGE"
              }
            ]
          },
          {
            "name": "GAF Timberline HD (Roof)",
            "tradeType": "ROOF",
            "active": true,
            "userId": 549941,
            "discount": 2731.52,
            "discounts": [
              {
                "name": "promo",
                "value": 10,
                "discountType": "PERCENTAGE"
              }
            ]
          },
          {
            "name": "Gutters",
            "tradeType": "GUTTERS",
            "active": true,
            "userId": 549941,
            "discount": 1566.11,
            "discounts": [
              {
                "name": "Gutters Special",
                "value": 25,
                "discountType": "PERCENTAGE"
              },
              {
                "name": "promo",
                "value": 10,
                "discountType": "PERCENTAGE"
              }
            ]
          }
        ]
      }
    }
  }
}
curl -X POST "https://graph.hover.to/graphql" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{"query": "{ projectManagementProposalDocument(id: \"proposal_document_id\") { id createdAt userId customerName customerEmail state totalPrice pdf { redirectUrl } signatureRequest { createdAt requestType signedAt state } estimateGroup { salesOpportunity { id createdAt updatedAt soldEstimateGroupId productionList { id } } jobId orgId estimates { name tradeType active userId discount discounts { name value discountType } } } } }"}'

Request:
  Method: POST
  URL: https://graph.hover.to/graphql
  Headers:
    Content-Type: application/json
    Authorization: Bearer YOUR_ACCESS_TOKEN
  Body:
    Type: Raw (JSON)
    Content:
      {
        "query": "{ projectManagementProposalDocument(id: \"proposal_document_id\") { id createdAt userId customerName customerEmail state totalPrice pdf { redirectUrl } signatureRequest { createdAt requestType signedAt state } estimateGroup { salesOpportunity { id createdAt updatedAt soldEstimateGroupId productionList { id } } jobId orgId estimates { name tradeType active userId discount discounts { name value discountType } } } } }"
      }

Proposal Field Index

FieldDescription
idProposal document ID
createdAtTimestamp of when the document was first generated
customerNameName of the customer
customerEmailEmail of the customer
stateCurrent state of the proposal, can be one of:
CREATED, QUEUED, REQUESTED, SIGNED, COMPLETE, FAILED, CANCELLED, DECLINED
tradeTypeThe estimated trade types of the proposal (roof, gutters, siding, etc.)
requestTypeThe format of the proposal, can be one of:
embedded: the customer signed the proposal onscreen.
shared: the proposal was sent via email
signedAtTimestamp when the proposalDocument was signed
totalPriceThe total price, including discounts, on the proposal.
discountTotal discount value applied to a particular trade.
redirectUrlNon-expiring URL to the proposal PDF. Requires authentication to view.