This guide will review updating an Appointments questions using our API.
When can Appointment be updated?
Appointments must have a Status of Assigned/Completed/Audit Failed.
When an Appointment has progressed to an Audited status to protect the Audits integrity only Failed sub status can be changed.
Appointment with Submissions or with RCTI Invoices finalized are locked from changes to protect their integrity.
The update API will return an error response if appointment has an invalid status.
NOTE: The update endpoint will change the status of the Appointment to ``Completed-Partial` and the Certificates and Products are re-calculated using the new answers.
Overview of Endpoints
These are endpoints used in this guide:
-
To view existing answer of an Appointment GET
/{instance}/appointments/{appointment_id}/answers
-
To save the answers of an Appointment POST
/{instance}/appointments/{appointment_id}/questions
-
Data Dictionary for Question and Answers GET
/{instance}/questions/{question_id}
and GET/{instance}/questions/{question_id}/answers
The endpoint POST /{instance}/appointments/{appointment_id}/questions
will DELETE all existing answers from the Appointment and replace with those provided.
When changing an existing appointment we recommend the use of the endpoint GET /{instance}/appointments/{appointment_id}/answers
to load existing answers make the changes to the data structure and then use the endpoint POST /{instance}/appointments/{appointment_id}/questions
to save the changes.
If updates are made to choice fields the dictionary endpoints can be used to fetch the right answerId (detailed further in this guide).
Question Answer Data Structure
Both endpoints GET /{instance}/appointments/{appointment_id}/answers
and POST /{instance}/appointments/{appointment_id}/questions
have same
data-structure below.
{
"appointmentId": 0,
"blockAnswers": [
{
"questionBlockTypeId": 0,
"blocks": [
{
"answers": [
{
"questionId": 0,
"answerValue": "string"
}
]
}
]
}
],
"answers": [
{
"questionId": 0,
"answerValue": "string"
}
]
}
Top level strut.
{
"appointmentId": 0,
"blockAnswers": []
"answers": []
}
appointmentId
is integer and match the appointment in url of endpoint.
blockAnswers
is array for question block questions.
answers
is an array of non-block question answers.
If a block question is used under answers
a validation error will be returned.
Answer strut.
{
"questionId": 0,
"answerValue": "string"
}
questionId
is required field and must be an integer while answerValue
is expected to be a string.
The Following question types are not supported:
- Image - Derived from Files uploaded with file category which matches the question.
- Check Box Groups - Checkbox Options which are saved not the group
- Dummy Text - Display only
The value of answerValue
changes based on the Question Type:
Question Type | Expected Value |
---|---|
Text Question | String less than 4000 characters with answer |
Text Area Question | String less than 4000 characters with answer |
Quantity Question | Stringified integer e.g “answerValue”: “3” |
Number Question | Stringified Number e.g “answerValue”: “3.78” |
Barcodes/Serial Numbers | String less than 4000 characters each barcode split by and End of Line (EOL) character” |
Image Question | Not supported |
Dummy Text | Not supported |
Checkbox Groups | Not supported |
Checkbox Options | string of ‘Yes’ if checked and ‘No’ if unchecked or empty string |
Select | Stringified integer the answerId e.g “answerValue”: “4523” |
Radio | Stringified integer the answerId e.g “answerValue”: “4523” |
Fieldworker | Stringified integer the answerId e.g “answerValue”: “4523” do not use the fieldworkerId or name |
Product | Stringified integer the answerId e.g “answerValue”: “4523” do not use the productId or name |
Date or Time | string with date or time in required format |
Choice Field Question Types like Question types like Radio,Select,Product and Fieldworker use an answerId
as their value.
The question dictionary endpoints can be used to lookup both the question type and answers.
Block Type strut
{
"questionBlockTypeId": 0,
"blocks": [
{
"answers": []
},
{
"answers": []
},
{
"answers": []
}
]
}
questionBlockTypeId
integer and question block type.
blocks
array contain data for each area.
answers
array of answers for this block only.
Using the Dictionary Endpoints.
Data Dictionary for Question and Answers GET /{instance}/questions/{question_id}
and GET /{instance}/questions/{question_id}/answers
To lookup this question, using request like:
curl -X GET "https://asap-api.dataforce.com.au/DATAFORCE_ESS/questions/1247" -H "accept: application/json" -H "Authorization: Bearer xxxxxx"
Return a response like:
{
"questionId": 1247,
"question": "Customers Average energy price (cents per KWh)",
"type": "Appointment",
"fieldType": "Number",
"checkboxId": 0,
"dataCategoryId": 0,
"dataCategory": "",
"sortOrder": 20,
"mandatory": true,
"category": "Standard",
"customerType": "",
"createdDate": "2016-09-19T14:07:48+10:00",
"questionBlockTypeId": 0,
"questionBlockTypeName": "",
"parentQuestion": [],
"workType": [
4,
7,
13
],
"agent": [],
"calculationZone": [],
"fieldworkerAbility": []
}
Look for the property fieldType
see that in this example it is Number, this means that no choice answers.
If look up a non-block Choice question
To lookup this question, using request like:
curl -X GET "https://asap-api.dataforce.com.au/DATAFORCE_ESS/questions/1243" -H "accept: application/json" -H "Authorization: Bearer xxxxxx"
Return a response like:
{
"questionId": 1243,
"question": "Is the site a Residential Building or a Business Building?",
"type": "Appointment",
"fieldType": "Radio",
"checkboxId": 0,
"dataCategoryId": 0,
"dataCategory": "",
"sortOrder": 8,
"mandatory": true,
"category": "Standard",
"customerType": "",
"createdDate": "2016-09-13T15:45:07+10:00",
"questionBlockTypeId": 0,
"questionBlockTypeName": "",
"parentQuestion": [],
"workType": [
4,
7,
13
],
"agent": [],
"calculationZone": [],
"fieldworkerAbility": []
}
The fieldType
has Radio this means that we need to lookup the answer to find right answerId
.
We use the answer endpoint, using request like:
curl -X GET "https://asap-api.dataforce.com.au/DATAFORCE_ESS/questions/1243/answers -H "accept: application/json" -H "Authorization: Bearer xxxxxx"
We get a response like :
{
"totalCount": 2,
"records": [
{
"answerId": 6742,
"questionId": 1243,
"answerValue": "residential building",
"answerText": "Residential Building",
"sortOrder": 0,
"mandatory": 0,
"enabled": false
},
{
"answerId": 6743,
"questionId": 1243,
"answerValue": "small business building",
"answerText": "Business Building",
"sortOrder": 1,
"mandatory": 0,
"enabled": false
}
]
}
The field answerId
is what will be needed.
In this strut answerValue
is what will be print onto forms or submission data files the answerText
is the value displayed on our screen/Runabout a human name.
When completing the answer strut for the save endpoint use the value under answerId
as the value.
Using the GET endpoint for existing questions.
To view an existing appointment question the use this endpoint GET /{instance}/appointments/{appointment_id}/answers
.
Use a request like:
curl -X GET "https://asap-api-dev.dataforce.com.au/DATAFORCE_ESS/appointments/204327/answers" -H "accept: application/json" -H "Authorization: Bearer xxxxxx"
Get the result in common format:
{
"appointmentId": 204327,
"blockAnswers": [
{
"questionBlockTypeId": 9,
"blocks": [
{
"answers": [
{
"questionId": 1151,
"answerValue": "6643"
},
{
"questionId": 1164,
"answerValue": "6667"
},
{
"questionId": 1200,
"answerValue": "8"
},
{
"questionId": 1332,
"answerValue": "7231"
},
{
"questionId": 1970,
"answerValue": "8177"
},
{
"questionId": 2050,
"answerValue": "9089"
},
{
"questionId": 2057,
"answerValue": "bathroom"
},
{
"questionId": 2169,
"answerValue": "10028"
},
{
"questionId": 2184,
"answerValue": "4444"
}
]
}
]
}
],
"answers": [
{
"questionId": 1204,
"answerValue": "6714"
},
{
"questionId": 1208,
"answerValue": "6723"
},
{
"questionId": 1241,
"answerValue": "6741"
},
{
"questionId": 1243,
"answerValue": "6742"
},
{
"questionId": 1247,
"answerValue": "30"
},
{
"questionId": 1301,
"answerValue": "555565"
},
{
"questionId": 1346,
"answerValue": "7520"
},
{
"questionId": 1347,
"answerValue": "7522"
}
]
}
You will need to submit this format to next end-point.
Using the POST endpoint to save changes.
Using save endpoint at POST /{instance}/appointments/{appointment_id}/questions
will save these answers
Using a POST request like below
curl -X POST "https://asap-api.dataforce.com.au/DATAFORCE_ESS/appointments/204327/questions" -H "accept: application/json" -H "Authorization: Bearer xxxxxx" -H "Content-Type: application/json" -d "{\"appointmentId\":204327,\"blockAnswers\":[{\"questionBlockTypeId\":9,\"blocks\":[{\"answers\":[{\"questionId\":1151,\"answerValue\":\"6643\"},{\"questionId\":1164,\"answerValue\":\"6667\"},{\"questionId\":1200,\"answerValue\":\"8\"},{\"questionId\":1332,\"answerValue\":\"7231\"},{\"questionId\":1970,\"answerValue\":\"8177\"},{\"questionId\":2050,\"answerValue\":\"9089\"},{\"questionId\":2057,\"answerValue\":\"bathroom\"},{\"questionId\":2169,\"answerValue\":\"10028\"},{\"questionId\":2184,\"answerValue\":\"4444\"}]}]}],\"answers\":[{\"questionId\":1204,\"answerValue\":\"6714\"},{\"questionId\":1208,\"answerValue\":\"6723\"},{\"questionId\":1241,\"answerValue\":\"6741\"},{\"questionId\":1243,\"answerValue\":\"6742\"},{\"questionId\":1247,\"answerValue\":\"30\"},{\"questionId\":1301,\"answerValue\":\"555565\"},{\"questionId\":1346,\"answerValue\":\"7520\"},{\"questionId\":1347,\"answerValue\":\"7522\"}]}"
The backend will send back a 201 code with following response.
{
"appointmentId": 204327
}
Validation Failures
If we tried to submit a an invalid answerId with answerValue
we get error like below.
{
"message": "Unable to complete the process with validation error",
"errors": [
{
"type": "answers/6/answerValue",
"description": "Answer Value does not match one of the Answers for this question, please use an answerId not answer text"
}
]
}
The type
property has message answers/6/answerValue.
From answers property look for 7th record (0 based array) and answerValue field which has incorrect value.
If we tried to submit a non-block question in a block strut will see error like below.
{
"message": "Unable to complete the process with validation error",
"errors": [
{
"type": "blockAnswers/0/blocks/0/answers/9/questionId",
"description": "Question does not exists for this Stage or in this Question Block Type"
}
]
}
From the blockAnswers property look for the 1st Block Type and in 1st block and in 10th record in answer array and the error is from the questionId field.
If questionId does not exist or its for a Job/Customer/Audit stage question an error like below will be returned.
{
"message": "Unable to complete the process with validation error",
"errors": [
{
"type": "answers/7/questionId",
"description": "Question does not exists at the current stage"
}
]
}
If and invalid datetime format was submitted like below:
{
"questionId": 2189,
"answerValue": "25/12/2023"
}
This field type requires (dd/mm/yy) and the above submits (dd/mm/yyyy).
We get error like the following.
{
"message": "Unable to complete the process with validation error",
"errors": [
{
"type": "answers/8/answerValue",
"description": "Answer Value must be date with format 'd/m/y'"
}
]
}
The formats using PHP DateTime format.
The question dictionary will have the format in the fieldType
property.
{
"questionId": 2189,
"question": "Test Date Format",
"type": "Appointment",
"fieldType": "Date (DD/MM/YY)",
"checkboxId": 0,
"dataCategoryId": 0,
"dataCategory": "",
"sortOrder": 3000,
"mandatory": false,
.....
}