API Documentation - Appointments

Table of Contents

Appointment Configuration

GET /api/v2/group/<group_id>/verify-widget/?widget=lead_capture_appointment

This endpoint allows you to get your group’s specific appointment widget configuration.

Required URI Parameters

Required Query Parameters

Appointment Configuration: GET response 200 success payload example

{
    "data": {
        "layout_options": [
            "loft",
            "studio",
            "1br",
            "2br",
            "3br",
            "4+br"
        ],
        "referral_sources": [
            [10, "Manual"],
            [20, "Website"],
            [30, "StreetEasy"],
            [40, "Zillow"],
            [50, "Apartments.com"],
            [60, "Zumper"],
            [70, "Walk In"],
            [80, "RentHop"],
            [90, "Realtor.com"],
            [110, "Agorafy"],
            [120, "Apartable"],
            [130, "Apartmentguide.com"],
            [140, "Apartmentlist"],
            [150, "Brownstoner"],
            [160, "Building/Property Website"],
            [170, "City Realty"],
            [180, "Company/Portfolio Website"],
            [190, "Craigslist"],
            [200, "Facebook"],
            [210, "ForRent.com"],
            [220, "Google"],
            [230, "Hotpads"],
            [240, "Instagram"],
            [250, "LeaseBreak"],
            [260, "Naked Apartments"],
            [270, "NY Bits"],
            [280, "NYTimes"],
            [290, "Observer"],
            [300, "Other"],
            [310, "Placebee"],
            [320, "Flyer, postcard or brochure"],
            [330, "Rentpath"],
            [340, "Sister property"],
            [350, "Building sign"],
            [360, "Current Resident"],
            [370, "The Real Deal"],
            [380, "Trulia"],
            [390, "Word of Mouth"],
            [400, "Yelp"],
            [410, "Rent.com"],
            [420, "Broker"],
            [425, "NYC Ferry"],
            [430, "MTA Subway"],
            [445, "Marketproof"],
            [450, "Friend or Family"]
        ],
        "discovery_source_choices": [
            {"value":  10, "label": "Manual"},
            {"value":  20, "label": "Website"},
            {"value":  30, "label": "StreetEasy"}
        ],
        "field_config": {
            "client.price_ceiling": 20,
            "client.other_occupants": 20,
            "client.reason_for_move": 30,
            "client.pets": 30,
            "client.notes": 20,
            "client.move_in_date": 20,
            "client.current_postal_code": 20,
            "client.sms_opted_in": 20,
            "client.lease_term": 10,
            "client.price_floor": 20,
            "client.discovery_source": 30,
            "client.agents": 30,
            "client.broker_toggle": 20,
            "client.client_location": 30,
            "client.amenities": 30,
            "client.broker_company": 20,
            "client.neighborhoods": 30,
            "client.layout": 20
        }
    }
}

Appointment Configuration: GET response 400 error payload example

If your request is unsuccessful for whatever reason, a 400 error response will be returned with a single key ‘widget’. These errors will be in an array of strings (however, only one item will be in the array)

{
   "errors":{
      "widget": ["Widget is inactive"]
   }
}

Appointment Configuration: GET response payload glossary

Appointment Times

GET /api/v2/appointments/group/<group_id>/times

This endpoint returns two different payloads depending on the presence of the time query parameter.

Without time, this endpoint returns all possible appointment times today regardless of actual agent availability (see example payload below). In other words, this array of times represents the group’s office hours. Please note that the array is an array of times not datetimes (since these times represent the present day)

If time is passed in (an ISO format datetime such as 2019-06-13T08:00), this endpoint returns only timeslots where at least one agent is available to give a tour. Please note that the array is an array of datetimes in ISO format (since the request could be for a day other than the present day)

Required URI Parameters

Optional Query Parameters

Note that in addition to the 200 status code, the success responses also have a valid: true item in the payload.

Appointment Times: GET response 200 success example payload without time query parameter (returns group office hours)

{
   "available_times": [
      "08:00:00", "08:15:00", "08:30:00", "08:45:00", "09:00:00", "09:15:00", "09:30:00", "09:45:00",
      "10:00:00", "10:15:00", "10:30:00", "10:45:00", "11:00:00", "11:15:00", "11:30:00", "11:45:00",
      "12:00:00", "12:15:00", "12:30:00", "12:45:00", "13:00:00", "13:15:00", "13:30:00", "13:45:00",
      "14:00:00", "14:15:00", "14:30:00", "14:45:00", "15:00:00", "15:15:00", "15:30:00", "15:45:00",
      "16:00:00", "16:15:00", "16:30:00", "16:45:00", "17:00:00", "17:15:00", "17:30:00", "17:45:00",
      "18:00:00", "18:15:00", "18:30:00", "18:45:00", "19:00:00", "19:15:00", "19:30:00"
   ],
   "valid": true,
   "errors": {},
   "appointment_sms_opt_in": true
}

Appointment Times: GET response 200 success example payload with time query parameter (returns appointment availability)

{
   "available_times": [
       "2019-06-13T10:00:00", "2019-06-13T10:15:00", "2019-06-13T10:30:00", "2019-06-13T10:45:00",
       "2019-06-13T15:00:00", "2019-06-13T15:15:00", "2019-06-13T15:30:00", "2019-06-13T15:45:00",
       "2019-06-13T17:00:00", "2019-06-13T17:15:00", "2019-06-13T17:30:00", "2019-06-13T17:45:00",
       "2019-06-13T18:00:00", "2019-06-13T18:15:00"
   ],
   "valid": true,
   "errors": {},
   "appointment_sms_opt_in": true
}

Appointment Times: GET response 400 error payload example

If you include a time query parameter and that time is not available, a 400 error will be returned with some available_times that are available for that day. Note that in addition to the 400 status code, the error response also has a valid: false item in the payload.

{
   "available_times":[
      "2019-06-19T08:00:00", "2019-06-19T08:15:00", "2019-06-19T08:30:00", "2019-06-19T08:45:00",
      "2019-06-19T17:45:00", "2019-06-19T18:00:00", "2019-06-19T18:15:00", "2019-06-19T18:30:00",
      "2019-06-19T18:45:00", "2019-06-19T19:00:00", "2019-06-19T19:15:00", "2019-06-19T19:30:00"
   ],
   "valid":false,
   "errors":{
      "start":["No Employees free at Scheduled Appointment time"]
   },
   "appointment_sms_opt_in":true
}

Appointment Times: GET response payload glossary

Appointment Booking

POST /api/v2/appointments/group/<group_id>/book

This endpoint is where you will POST the actual appointment information to the server to create an appointment and either create a new prospect or modify an existing one.

Required URI Parameters

Appointment Booking: POST request example payload

{
   "appointment":{
      "start":"2019-06-21T08:15:00",
      "location":"",
      "broker_booked":false
   },
   "client":{
      "broker_first_name":"Jeff",
      "broker_last_name":"Brokerman",
      "broker_company":"Jeff Brokerman Brokerage",
      "broker_phone":"18222120422",
      "broker_email":"jeff@brokermanbrokerage.com",
      "people":[
         {
            "first_name":"John",
            "last_name":"Doe",
            "email":"johndoe@name.com",
            "phone_1":"18582007006"
         }
      ],
      "community": 105,
      "sms_opted_in":10,
      "move_in_date":"2019-07-01T00:00:00",
      "layout":null,
      "price_floor":"3000",
      "price_ceiling":"4500",
      "pets":[
         "20",
         "10"
      ],
      "discovery_source":270,
      "notes": "Looking for an apartment for a great client of mine",
      "neighborhoods":[
         133,
         116,
         1732,
         108,
         375,
         126
      ],
      "elevator":true,
      "laundry":[
         20,
         10
      ],
      "outdoor_space":[
         10
      ]
   }
}

Appointment Booking: POST request payload glossary

The payload is separated in two parts: appointment data and prospect data (client).

Please note that while many of these fields are optional, prospect data is much more useful the more you collect. Consider performing client side validation and requiring at minimum the people fields (first name, last name, email, phone).

Appointment Booking: POST response success example payload

After the data is successfully submitted, you will receive a 200 success response with data similar to the following.

{
   "data":{
      "appointment":{
         "id": 952,
         "confirmation_enabled":true,
         "start":"2019-06-21T09:00:00+00:00",
         "location":"",
         "expiration_date":"2019-06-17T12:53:05.799365"
      }
   }
}

Appointment Booking: POST response error payload examples

If an appointment time is no longer available, a 400 error response will be returned. These errors will be in an array of strings.

{
   "errors":{
      "appointment":{
         "start": ["No Employees free at Scheduled Appointment time"]
      }
   }
}

If any of the prospect fields fail validation, a 400 error response will be returned. These errors will be in an array of strings.

{
   "errors":{
      "client":{
         "pets": ["'dogs' is not a number"],
         "laundry": ["'in unit' is not a number"]
      }
   }
}

Appointment Booking: POST response payload glossary

Example Appointment Booking Flow

Screen 1: Date Select and Office Hours

Using the Nestio-powered appointment scheduler as an example, here’s how we use the API internally.

In the initial view, Nestio makes GET requests to:

Screen 2: Date Selected, Choose Appointment Slot

After user chooses a date and time, GET request is made to the appointment times endpoint and agent availability is returned back

Screen 3: Appointment Form

After user chooses a specific timeslot, the form is assembled using the configuration

Screen 4 Success: Optional Confirmation Screen

User fills out the form and submits.

After booking is confirmed, a 200 response is returned. Since this group in particular has appointment confirmations turned on, show the confirmation screen

Screen 4 Error: Timeslot Not Available

User fills out the form, submits, but time is no longer available and a 400 error response is returned

Client Appointments

GET /api/v2/clients/<client_id>/appointments

This endpoint returns all of a client’s appointments, ordered by appointment start time, which are either status=CONFIRMED or status=null (e.g. appointments that are created directly within the Nestio web application)

Required URI Parameters

Client Appointments: GET response 200 success example

{
  "data": {
    "appointments": [
      {
        "status": 30, 
        "id": 509,
        "start": "2019-06-24T08:00:00+00:00", 
        "end": "2019-06-24T08:30:00+00:00", 
        "notes": "", 
        "location": "", 
        "employee": {
          "id": 596, 
          "photo": null, 
          "name": "Travis Smiley"
        }, 
        "client": {
          "id": 890,
          "name": "John Doe, Jane Fonda", 
          "group": null, 
          "person": {
            "id": 740, 
            "first_name": "John", 
            "last_name": "Doe", 
            "is_primary": true, 
            "email": "johndoe@name.com", 
            "phone_1": "555-555-5555",
            "phone_2": ""
          }, 
          "agents": [], 
          "broker_first_name": "", 
          "broker_last_name": "", 
          "lead_source": "StreetEasy"
        }, 
        "appointment_showings": []
      }
    ]
  }
}

Client Appointments: GET response payload glossary

An array of appointment objects are keyed in the payload under data and appointments. The glossary below describes data in each appointment object. Please note that in the appointment payload is an appointment_showings array. This data is used internally and you can safely disregard for purposes of this.

Client Appointments: GET error response

Below is an example error response. In this example, attempting to get appointments for a client who does not exist.

{
  "errors": {
    "client": {"id": "client id=890 does not exist"}
  }
}

Appointment Deletion

DELETE /api/v2/appointments/<appointment_id>

This endpoint allows you to delete an appointment. While this is a delete endpoint, the appointment will actually be set to status=CANCELLED. If the appointment was previously confirmed, this will send an email to the employee assigned to the appointment notifying them of the appointment cancellation.

Required URI Parameters

Appointment Deletion: DELETE response 200 success example

{
  "data": {
    "message": "success",
    "notification_sent": true
  }
}

Appointment Deletion: DELETE response payload glossary

Appointment Deletion: DELETE error response

Below is an example error response. In this example, attempting to delete an appointment which does not exist.

{
  "errors": {
    "appointment": {"id": "Appointment id=890 does not exist"}
  }
}

Appointment Reschedule

PUT /api/v2/appointments/<appointment_id>/group/<group_id>/book/

This endpoint allows you to reschedule an appointment to a new time. If the time is valid, we will attempt to reschedule the appointment with the same employee. If that employee is not available, another employee belonging to the specified employee group will be selected randomly.

Required URI Parameters

Appointment Reschedule: PUT request example

{
  "data": {
    "appointment": {"start": "2019-07-20T14:00:00"}
  }
}

Appointment Reschedule: PUT response 200 success example

{
  "data": {
    "appointment": {
      "id": 952,
      "status": 30, 
      "start": "2019-07-20T05:00:00+00:00", 
      "end": "2019-07-20T05:30:00+00:00", 
      "notes": "Please mind the gap", 
      "location": "Near the fountain of the building's main entrance"
    }
  }
}

Appointment Reschedule: PUT response payload glossary

Appointment Reschedule: PUT error response

Below is an example error response. In this example, attempting to reschedule an appointment in the past.

{
  "errors": {
    "appointment": {"start": ["The date and time you selected is in the past"]}
  }
}