Introduction

## Values and Refs Most of the data structures that the Skedge.me API provides can be uniquely identified with an integer, or ref, and type. For example, the type "service" and the ref "2" represents a unique service value. # Glossary **Attendee**: An attendee is a relation between a "thing" and an "event". **Event**: An event is an instantiation of a service. Specifically, it is a service with roles and time assigned. Note that events can be recurring and have multiple times. **Fields**: A field is a way to associate information with a Skedge.me value. For example, a thing (see below) may have a "name" field, allowing the application to associate that name with the thing. **Interval**: An interval is a pair of change points, each of which indicates a time and whether or not the interval begins "just after" the time. For example, a value of "true" for the second point would indicate that the interval strictly includes that time. A value of “false” would indicate that it does not. **Occurrence**: An occurrence is a recurrence of an event. It is an event taking place at a discrete time. **Ref**: A ref is a unique numeric identifier for values in the Skedge.me API and can be used to retrieve any value. **Role**: A role defines a relation between a thing (see below) and a service (see below). A given thing takes on a certain role when booked for a service. The most common roles are the customer role and the staff role. **Service**: A service can be either for individuals (An appointment) or a group (an event). A service can represent a discrete event or a series of events with similar features (i.e. the same name). **Thing**: A thing is, essentially, any item that can have a schedule. A staff is a thing. A customer is a thing. A building is a thing. **Thing type**: A thing type is a category to which a thing belongs. For example, staff member Bayta Darell is a thing that may belong to the thing type "staff". **Thing type constraint**: A value for specifying the kind of thing type being searched for. Note, this is only used to retrieve the correct thing refs from the getAvailableAssignments API. If a thing belonging to "staff" is sought, use the staffThingTypeConstraint attribute on the config. # Core API ## Retrieving Types by Constraint The findAndRead family of APIs allows for the retrieval of a type's values with a given constraint. This can be used to retrieve all values of a given type. Request: url: $type/findAndRead method: GET data: a type's constraint. Can be Any, And, Or, In, Ref, or Value. ``` sample: { "token": "xkqY3YvGtTr7Q7klsJYlOA==", "request": ["any", []] } ``` ## Create Customer Token For new visitors, the application must first exchange the supplied dummy token for a token uniquely representing the new customer. Request: ``` url: token/createCustomerToken method: POST data: an empty array ``` ``` sample: {"request":[]} ``` Response: A string representing the customer-specific token. ``` sample: { "envelopeContents": "xkqY3YvGtTr7Q7klsJYlOA==", "modifiedRefs": { } } ``` ## Authenticate Some API endpoints cannot be used with customer tokens, for example /reports. In order to use such API, we need to authenticate and receive a user token, which will give access to different parts of API depending on the type of authenticated user. Request: url: auth/email/authenticate method: POST data: email: user's login password: user's password ``` sample: { "request": { "email": "login", "password": "somePassword" }, "token": "p3v0UCDUa1ECz_FKVbYJkQ==" } Response: User id and user token to use in subsequent API calls ``` sample: { "envelopeContents": { "token": "HWjuRHpMrHAjerFnUhrxerR4", "principal": "1490970632945023613" }, "modifiedRefs": { } } ## Get Configuration Parameters When interacting with the Skedge.me API, it sometimes becomes necessary to have a semantic representation of various refs. Since the value of these refs are subject to change, Skedge.me provides an API that returns a mapping of strings to refs that the developer can then use to refer to the needed ref. Examples for using this mapping are shown in the various workflows below. Request: url: frontend/frontend method: GET data: an empty array ``` sample: { "request":[] } ``` Response: A mapping of strings to refs. ``` sample: { "envelopeContents": { "assetGroups": [ "194624191650768261" ], "individualService": "194624484494288404", "staffThingTypeConstraint": "194624191650768261", "customerPreferredTimeZone": null, "customerThingType": "194623611039875186", "checkInConfig": { "completedField": "194624106678439525", "startTimeField": "194624167015399671", "noShowField": "194624302969284202", "checkInField": "194624089838572557" }, "locationPhoneField": "194623882308220739", "colorThingField": "194623933291732712", "locationEmailField": "194624003653900506", "staffRoleRef": "194623494585641297", "defaultNameField": "194623775522528846", "customConfig": null, "thingEmailMessageField": "194623461348957605", "notesField": "194623506165193229", "addressField": "194624515706143325", "searchFields": { "attendeeFields": [], "locationFields": [ "194623460611596255", "194624003653900506" ], "thingFields": [ "194623739542136971", "194623775522528846", "194623792185743692", "194624033048807117" ] }, "locationName": "123", "locationViewConfig": { "fields": [ "194623460611596255" ] }, "agreeToSms": null, "groupService": "194623625204657625", "colorServiceField": "194624074378636980", "nameConfig": [ [ "194624033048807117", "194623739542136971" ], [ "194623775522528846" ] ], "customerThingTypeConstraint": "194624037165549959", "locationCountry": null, "servicePublished": "194624498569908448", "languageConfig": null, "customCss": null, "serviceEmailMessageField": "194623768873017725", "locationId": null, "locationDescription": "194624156238294106", "resourceThingTypeConstraint": "194624191650768261", "serviceDescription": "194623536588932748", "cancelReasonRequired": false, "phoneField": "194623678988539542", "serviceExpiration": "194623639122503992", "widgetConfig": { "link": { "suffix": "", "base": "\/skedgewidget", "params": { "service": null, "location": null, "resource": null } }, "name": "Skedge", "workflow": [] }, "locationMapMarkerColor": "1639257395300331668", "internalNotesField": "194623544398612651", "emailField": "194623792185743692", "customerRoleRef": "194624391368126035", "preferredLangLocale": [ "en-US" ], "locationAddressField": "194624321264188867" }, "modifiedRefs": {} } ``` # Main Workflows ## Create Appointment ### Step 1: Create Customer Token See Core API ### Step 2: Get Configuration Parameters See Core API ### Step 3: Get Service Durations Skedge.me allows for services to have versions of different length. In order for the user to determine which version to use, retrieve an array of pairs of service refs and lengths. Request: url: service/getServiceDurations method: GET data: services: service constraint. location: location constraint. ``` sample: { "token": "xkqY3YvGtTr7Q7klsJYlOA==", "request": { "services": [ "in", [ [ "1166075204099624855", "1566376991425378992", "1896920517227619823" ] ] ], "location": ["any", []] } } ``` Response: An array of pairs of service refs and lengths. ``` sample: { "envelopeContents": [ ["1166075204099624855", 3600000 ], ["1566376991425378992", 3600000 ], ["1896920517227619823", 3600000 ] ], "modifiedRefs": {} } ``` ### Step 4: Get Resource Refs This call will provide the application with a set of all the resources associated with the service that are available to book an appointment during the period queried. The application may also restrict the query to specific resources, using the "chosenStaffing" field: a mapping from role refs to thing refs. Request: url: service/getAvailableAssignmentPossibilities method: GET data: service: The service ref for which the application needs available resources. length: The length, in milliseconds, of the service. Retrieved from the getServiceDurations API. range: An interval representing the period of time during which to find assignments. eventFields : A mapping from event field ref to event field value, limiting the result to events with that field value. locations: A location constraint, limiting results to events from chosen locations. overridePadding: A boolean indicating that the scheduler can override the padding time requirement for resources. overrideAvailability: A boolean indicated that the scheduler can override the booking hours for a resource. chosenStaffing: A mapping from role ref to thing ref, identifying which, if any, resources to use for generating assignments. Not typically used for this API call. ``` sample: { "token": "xkqY3YvGtTr7Q7klsJYlOA==", "request": { "service": "1566376991425378992", "length": 3600000, "range": [ ["2017-12-11T07:23:24.193Z", true ], ["2018-12-11T07:23:24.194Z", false ] ], "eventFields": {}, "locations": [ "in", [["869464380766929383"]] ], "overridePadding": false, "overrideAvailability": false, "chosenStaffing": {} } } ``` Response: A set of available Thing Refs grouped by Role Ref and Location Ref. ``` sample: { "envelopeContents": { "869464380766929383": { "194623494585641297": [ "1219287324465589187", "1282111292060338113", "1599998118193100784" ] } }, "modifiedRefs": {} } ``` ### Step 5: Retrieve the Resources Using Core API's $type/findAndRead calls (i.e. role/findAndRead and thing/findAndRead) we can find the Role and Thing details retrieved on the previous step. ``` sample request/response for role/findAndRead: { "token": "xkqY3YvGtTr7Q7klsJYlOA==", "request": ["in", [["194623494585641297"] ] ] } { "envelopeContents": { "194623494585641297": { "name": "Staff", "thingConstraint": "194624191650768261" } }, "modifiedRefs": {} } ``` ### Step 6: Get Available Creation Times The request data for getAvailableCreationTimes may be identical to that for getAvailableAssignments. Where the former request showed the resources that are available given the query constraints, this returns an array of possible start times for the appointment, given the query constraints. Request: url: service/getAvailableCreationAndBookingTimes method: GET data: See the request for 'getAvailableAssignmentPossibilities' ``` sample: { "token": "xkqY3YvGtTr7Q7klsJYlOA==", "request": { "service": "1566376991425378992", "length": 3600000, "chosenStaffing": { "194623494585641297": "1599998118193100784" }, "range": [["2017-12-11T07:23:24.193Z", true ], ["2017-12-15T07:23:24.194Z", false ] ], "eventFields": {}, "locations": [ "in", [["869464380766929383"] ] ], "overridePadding": false, "overrideAvailability": false, "excludeAssignOnlyByStaff": true } } ``` Response: A set of specific times a service can be booked, and intervals within a day the bookings are available. ``` sample: { "envelopeContents": { "availableCreationTimes": [ "2017-12-12T09:00:00.000Z", "2017-12-12T09:55:00.000Z", "2017-12-12T10:00:00.000Z", "2017-12-12T10:55:00.000Z", "2017-12-12T11:00:00.000Z", "2017-12-12T11:55:00.000Z", "2017-12-12T12:00:00.000Z", "2017-12-13T09:00:00.000Z", "2017-12-13T09:55:00.000Z", "2017-12-13T10:00:00.000Z", "2017-12-13T10:55:00.000Z", "2017-12-13T11:00:00.000Z", "2017-12-13T11:55:00.000Z", "2017-12-13T12:00:00.000Z", "2017-12-14T09:00:00.000Z", "2017-12-14T09:55:00.000Z", "2017-12-14T10:00:00.000Z", "2017-12-14T10:55:00.000Z", "2017-12-14T11:00:00.000Z", "2017-12-14T11:55:00.000Z", "2017-12-14T12:00:00.000Z" ], "availableBookingTimes": { "changes": [ [["2017-12-12T09:00:00.000Z", false ], true ], [["2017-12-12T13:00:00.000Z", false ], false ], [["2017-12-13T09:00:00.000Z", false ], true ], [["2017-12-13T13:00:00.000Z", false ], false ], [["2017-12-14T09:00:00.000Z", false ], true ], [["2017-12-14T13:00:00.000Z", false ], false ] ], "initial": false }, "duration": 3600000 }, "modifiedRefs": { } } ``` ### Step 7: Create Tentative Event This API call officially starts the booking process. Upon a successful request, a tentative appointment will be made that will last a predefined amount of time (usually 4 minutes). The response will include an event ref, which will be used to finalize the booking, as well as a set of requirements for the fields that the customer may fill out to finalize the booking. Request: url: service/createTentativeEvent method: POST data: service: The ref of the service for which to create the event. location: The ref of the location at which to create the event. time: An interval representing the duration of the occurrence. The start time may be a value selected from the response of getAvailableCreationTimes. The end time is the sum of the start time and a valid service duration. chosenStaffing: A mapping from role ref to thing ref, identifying which, if any, resources to use for generating assignments. eventFields: A mapping from field ref to a field value, indicating that all responses returned should be associated with that value. createdOnPlatform: An enumeration value to indicate where the API call is made from. overridePadding: A boolean indicating that the scheduler can override the padding time requirement for resources. overrideAvailability: A boolean indicated that the scheduler can override the booking hours for a resource. excludeAssignOnlyByStaff: A boolean indicating if resources with 'Assign only by staff' flag can be assigned to event. False by default, meaning any resource can be assigned to event. ``` sample: { "token": "xkqY3YvGtTr7Q7klsJYlOA==", "request": { "service": "1566376991425378992", "location": "869464380766929383", "time": [["2017-12-12T09:55:00.000Z", true ], ["2017-12-12T10:55:00.000Z", false ] ], "chosenStaffing": { "194623494585641297": "1219287324465589187" }, "eventFields": {}, "createdOnPlatform": ["customerDesktop", []], "overridePadding": false, "overrideAvailability": false, "excludeAssignOnlyByStaff": true } } ``` Response: An event ref and a set of fields to fill out to complete the booking process. ``` sample: { "envelopeContents": { "Right": [ "2205681808875506008", { "194624391368126035": { "attendeeFields": {}, "paddingAfter": 0, "paddingBefore": 0, "maxAttendees": 1, "minAttendees": 0, "thingFields": { "194623792185743692": { "required": true, "constraint": ["any", []], "precedence": 0 }, "194623678988539542": { "required": true, "constraint": ["any", []], "precedence": 0 }, "194624033048807117": { "required": true, "constraint": ["any", []], "precedence": 0 } }, "matchingThingFields": {} } }, [ "2205681808875506008", "2017-12-12T09:55:00.000Z" ] ] }, "modifiedRefs": {} } ``` ### Step 8: Get Booking Fields. To provide a booking interface for clients, the application must now retrieve two sets of fields, which provide information on the name and the type of the fields associated with the service. The application will receive a set of client fields, which represent information permanently associated with the customer, and attendee fields, which contain information associated with the customer’s attendance at this specific event. The thingFields and attendeeFields associated with the given event are identified on the RoleDetails in the CreateTentativeEventResponse. This can be achieved with the thingField/findAndRead, attendeeField/findAndRead API calls (see Core API). ### Step 9: Finalize Event With values supplied for the fields, the application can now finalize the event. Request: url: service/finalizeEvent method: POST data: roles: Two sets of fields associated with the customer role - a set of client fields, which represent information permanently associated with the customer, and attendee fields, which contain information associated with the customer's attendance at this specific event. event: The ref of the event to finalize. service: The ref of the relevant service. chosenStaffing: A mapping from role ref to thing ref, identifying which, if any, resources to use for generating assignments. time: An interval representing the duration of the occurrence. createdOnPlatform: An enumeration value to indicate where the API call is made from. overridePadding: A boolean indicating that the scheduler can override the padding time requirement for resources. ``` sample:{ "token":"xkqY3YvGtTr7Q7klsJYlOA==", "request":{ "roles":{ "194624391368126035":[ { "canceled":false, "fields":{ }, "thingFields":{ "194623792185743692":[ "email", "test@email.ccc" ], "194623678988539542":[ "text", "1231231231" ], "194624033048807117":[ "text", "Jason" ] } }, "194623611039875186" ] }, "event":"2205681808875506008", "service":"1566376991425378992", "chosenStaffing":{ "194623494585641297":"1219287324465589187" }, "time":[ [ "2017-12-12T09:55:00.000Z", true ], [ "2017-12-12T10:55:00.000Z", false ] ], "createdOnPlatform":[ "customerDesktop", [ ] ], "overridePadding":false } } ``` Response: Ref Role and Ref Thing of the created customer. ``` sample: { "envelopeContents": { "194624391368126035": [ "360974847170332936" ] }, "modifiedRefs": { "event": { "2205681808875506008": 0 } } } ``` ## Run Comprehensive Report ### Step 1: Authenticate We need to obtain user token to use in all subsequent calls See Core API ### Step 2: Get Configuration Parameters You might need the value of 'locationName' parameter from 'frontend/frontend' response in the next step See Core API ### Step 3: Get Location Info If you plan to run the comprehensive report for some specific locations, their ids need to be specified. The ids can be found with location/findAndRead API call as follows Request: url: location/findAndRead method: GET data: a type's constraint. Can be Any, And, Or, In, Ref, or Value ``` sample: { "token": "xkqY3YvGtTr7Q7klsJYlOA==", "request": ["any", []] } ``` Response: A list of location ids mapped to various location information. Location name can be found in 'fields' object using the value of 'locationName' from the step above as a key ``` sample: { "envelopeContents":{ "1043378545562430661":{ "groups":[ ], "smsSendTimeTo":null, "smsNotificationsEnabled":false, "limitSmsSendTime":false, "isValid":true, "geometry":{ "coordinates":[ -111.5418192, 40.720478 ], "type":"Point" }, "smsSendTimeFrom":null, "timezone":"America/Denver", "fields":{ "988218432520154545":[ "text", "UT" ], "164703072086692425":[ "text", "435-575-0231" ], "1035361095183390728":[ "text", "www.bedbathandbeyond.com" ], "411757680216731061":[ "text", "Bed Bath & Beyond" ], "823515360433462121":[ "text", "West" ], "82351536043346213":[ "email", "customer.service@bedbath.com" ], "123":[ "text", "Park City" ], "741163824390115909":[ "text", "Phil Gray" ], "576460752303423485":[ "text", "Tony Lucas" ], "247054608130038637":[ "text", "1678 W. Redstone Center Drive, Park City" ], "905866896476808333":[ "int", 764 ], "1070569968563500757":[ "text", "84098" ], "658812288346769697":[ "text", "Store Manager" ] } }, ... }, "modifiedRefs":{ } } ``` ### Step 4: Run Report Comprehensive report provides detailed information about the appointments for selected location(s) and date range Request: url: reports/comprehensive method: GET data: range: An interval representing the period of time during which to find appointments. The format to represent a date is [[YYYY, MM, DD], INCLUDE], where MM and DD are zero-based indexes for month and day, and INCLUDE is a boolean value indicating whether to include the date into the range. For example, the range from the sample below is Jan, 4 - Jan, 10, 2018. location: A location constraint, limiting results to appointments from chosen locations. ``` sample 1 - running the report for specific locations: { "request": { "range": [[[2018, 0, 3], true], [[2018, 0, 10], false]], "location": ["in", [["1043378545562430661", "2232912076167149977"]]] }, "token": "HWjuRHpMrHAqvrRfUhrxerR4" } sample 2 - running the report for all locations: { "request": { "range": [[[2018, 0, 3], true], [[2018, 0, 10], false]], "location": ["any", []] }, "token": "HWjuRHpMrHAqvrRfUhrxerR4" } ``` Response: A list of column names used in the report, and a list of objects with data for each appointment. ``` sample: { "envelopeContents": { "fields": [ "Location", "Date", "Time", "Time Zone", "Service", "Attendee Name", "Created By", "Time Created", "Cancelled", "Booked On", "Customer Selected Staff", "Waitlisted", "Scheduled By", "Canceled By", "Canceled Reason", "Email", "First Name", "Phone Number", "Last Name", "Staff" ], "rows": [ { "Canceled By": "Admin", "Email": "john@skedge.me", "Location": "Test Location", "Last Name": "", "Service": "Service Name", "Time Created": "1/4/2018 06:07:47", "Time": "12:20:00", "Time Zone": "EST", "Created By": "Customer", "Attendee Name": "John Doe", "Booked On": "CustomerDesktop", "Date": "1/5/2018", "Phone Number": "0987654321", "Scheduled By": "Customer", "First Name": "John", "Waitlisted": "False", "Cancelled": "true", "Canceled Reason": "Cancelled Attendee", "Customer Selected Staff": "False", "Staff": "Aesthetician 1" } ] }, "modifiedRefs": {} } ``` # API Call Examples This section provides examples of GET and POST request to Skedge.me API using Javascript ```javascript var skedgeURL = "https://skedgewidget.qa.skedgeme-test.com/"; function createCustomerToken(callback) { var data = { "request": [], "token": 'p3v0UCDUa1ECz_FKVbYJkQ==' }; callApi('token/createCustomerToken', 'POST', data, callback); }; function getServiceDurations(token, constraint, eventFields, callback) { var data = { "request": { "services": constraint, "eventFields": eventFields }, "token": token }; callApi('service/getServiceDurations', 'GET', data, callback); }; function callApi(api, method, data, callback) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { var response = JSON.parse(xhr.responseText); callback(response['envelopeContents']); } else { console.log(xhr.responseText); console.log(data); console.log(path, method, data['request']); } } }; if (method === "POST") { xhr.open(method, skedgeURL + path); xhr.send(JSON.stringify(data)); } else { xhr.open(method, skedgeURL + path + '?q=' + JSON.stringify(data)); xhr.send(); } }; ```
NARS
Buy Buy Baby
Bed Bath
cle de peau
Clarins