Using the API
Subscription Tier Required
This feature requires the Premier subscription tier or higher.
There are situations where it is useful to interact with GS without using a web browser. Some examples include:
- Automated data collection with no user interaction.
- Synchronizing data between GS and another system.
- Building an alternative frontend for users to interact with.
This guide will walk through setting up the system in the same was as the Getting Started, using the API. Although this guide is available in Python and Javascript, any programming language capable of making HTTP requests may be used.
This guide assumes that the reader has a basic understanding of the chosen programming language and the ability to use a command line interface. All steps involving the command line in this guide were completed using Windows PowerShell, but can easily be translated to any other command line environment (CMD, Bash, Zsh).
Warning
If you have already followed the Getting Started guide, you will need to update the names of the entities created in this guide, or you will receive 409 errors, indicating that you are attempting to create duplicate entities.
Creating an API Key
Before the API can be used, an API key must be created.
- Navigate to the API Key page.
- Press the Add button.
- Fill in the Name and Role fields.
- Press the Save button.
- Copy the resulting Secret.
Information
For the purpose of this guide, it is assumed that the API Key will have at least the Engineer role. In production, it is recommended that API Keys be given the most restrictive Role possible.
Storing API Keys
The examples provided in this guide have the API key inserted directly into the source code. This is done for illustration purposes only, and should not be used in production.
Some common ways to store and load secrets are:
- Use a cloud based secret manager, like AWS Secrets Manager, Azure Key Vault, or the Google Cloud Secret Manager.
- Store them in Environment Variables
- Use a local credential manager, like the Windows Credential Manager
The exact solution used to protect your API keys will depend on the nature of the application being developed.
Principles
The GS API may be accessed by issuing an HTTP request to the appropriate API URL. The origin of the GS API for your account may be found on the Account Info page.
Authentication
Two HTTP headers are required in order to authenticate with the GS API. If these headers are not provided, the user will receive a 401 Unauthorized status.
| Header | Value |
|---|---|
| GS-Api-Key | The value of the API key copied from Creating an API Key. |
| GS-Device-Id | The unique ID of the device making the request. While any value will be accepted, this value should remain consistent for a given physical device. |
Request Method
The GS API accepts the following request methods:
GET: Used to retrieve entities or data.POST: Used to create or update entities and data.DELETE: Used to delete entities and data.
For information about which method to use for a given endpoint, see the API Reference.
Request Body
Unless otherwise specified in the API Reference, the request body POST requests should be provided as serialized JSON, and the Content-Type header should be set to application/json.
GET and DELETE requests should never provide a body.
Responses
Unless otherwise specified in the API Reference, responses will be returned as JSON. The reference contains the specific JSON fields which will be returned for each request.
If the request was executed successfully, GS will return a 200 OK status. Other status codes indicate that the request did not complete successfully.
| Status Code | Description | Troubleshooting |
|---|---|---|
| 200 | The request completed successfully. | |
| 400 | The request was not valid. | Check the API documentation to ensure that the correct fields were supplied. Check the response body for additional information about which fields were not valid. |
| 401 | The request did not supply valid credentials. | Check that all required headers were supplied. Check that the API Key exists and is correct. |
| 403 | The supplied credentials are valid, but the API key issuing the request does not have access to the endpoint. | Check that the Role of the API Key has access to the requested resource. |
| 404 | The requested entity does not exist. | Check that the ID given to the endpoint exists. Check that the correct endpoint is being used. |
| 409 | The request attempted to create an entity which already exists. | Check that the name of the resource being created does not already exist. It may have been hidden. |
| 429 | Too many requests have been made. | Wait longer between issuing requests. Contact sales to discuss increasing your account rate limits. |
| 500 | The server encountered an error when attempting to process the request. | The response may contain additional details about the error. Contact support to report a bug. |
| 501 | The request attempted to access a feature which has not been implemented. | Contact support to request that the feature is prioritized for development. |
| 503 | The server is temporarily unavailable. | Check if routine maintenance is being performed. Contact support if this error is received unexpectedly. |
Creating the Project
This guide has the following requirements:
- Python is installed with a version >= 3.8.
- Familiarity with the requests Python library
- Node.js is installed, with a version >= 20.0
- Familiarity with
fetch - Familiarity with asynchronous programming
Begin by setting up a new project:
Information
Although it is not necessary to complete this guide, it is recommended to utilize virtual environments for Python development.
- Create a new folder.
- Navigate to the folder.
- Install the requests module.
- Create a file named
app.py. - Open
app.pyin your favorite code editor.
- Create a new folder.
- Navigate to the folder.
- Create a file named
app.js. - Open
app.jsin your favorite code editor.
Next, add some helper functions to access the API:
import requests
API_KEY = "YOUR API KEY HERE"
BASE_URL = "YOUR URL"
DEVICE_ID = "MACHINE-1"
def gs_request(endpoint, method, query_params = None, body = None):
# Establish the necessary headers
headers = {
"GS-Api-Key": API_KEY,
"GS-Device-Id": DEVICE_ID
}
# Construct the URL
url = f"{BASE_URL}{endpoint}"
if method == "GET":
# Handle GET requests, which have no body
return requests.get(url, headers=headers, params=query_params)
elif method == "DELETE":
# Handle DELETE requests, which have no body
return requests.delete(url, headers=headers, params=query_params)
elif method == "POST":
# Handle POST requests, and let the API know that JSON is being passed in
headers["Content-Type"] = "application/json"
return requests.post(url, headers=headers, json=body, params=query_params)
else:
raise ValueError("Invalid method type.")
const API_KEY = 'YOUR API KEY HERE';
const BASE_URL = 'YOUR URL';
const DEVICE_ID = 'MACHINE-1';
function gsRequest(endpoint, method, queryParams, body) {
// Establish the necessary headers.
const headers = {
"GS-Api-Key": API_KEY,
"GS-Device-Id": DEVICE_ID
};
if (method === 'POST') {
headers['Content-Type'] = 'application/json';
}
// Construct the full URL
let url = `${BASE_URL}${endpoint}`;
// Add URL parameters
if (queryParams) {
url += '?' + new URLSearchParams(queryParams).toString();
}
return fetch(url, {
method: method,
headers: headers,
body: body ? JSON.stringify(body) : undefined,
});
}
The API can now be tested. In the same file, try retrieving your Customer's name from the Permissions endpoint:
At the bottom of the file, add:
Finally, execute your code:
If the program executed successfully, you should see the name of your GS customer.
Set Up Entities
Now that the GS API has been connected to successfully, you may begin setting up entities.
Create a Process
In order to create a Process, replace the contents of the run function with a call to the GS API using the POST method:
Storing the result of the call in the processId variable allows you to keep track of the ID of the newly created process so that it may be used to insert data later.
However, this assumes that a Process named Welding does not already exist. Instead of assuming that the Process must be created, first attempt to retrieve the ID, and only create it if it does not exist. Replace the above code:
# Attempt to retrieve the process using the name as a query parameter.
get_process_by_name_response = gs_request("setup/v1/process/name", "GET", { "name": "Welding" })
if get_process_by_name_response.status_code == 200:
#The Welding process was found
process_id = get_process_by_name_response.json()
else:
# The process could not be found. Create it instead.
process_id = gs_request("setup/v1/process", "POST", None, {
"name": "Welding",
"sampleSize": 10,
"ncuCost": 0.0
}).json()
let processId;
// Attempt to retrieve the process using the name as a query parameter.
const getProcessByNameResponse = await gsRequest('setup/v1/process/name', 'GET', { name: 'Welding' });
if (getProcessByNameResponse.status === 200) {
// The Welding process was found
processId = await getProcessByNameResponse.json();
} else {
// The process could not be found. Create it instead.
const createProcessResponse = await gsRequest('setup/v1/process', 'POST', undefined, {
name: 'Welding',
sampleSize: 10,
ncuCost: 0.0
})
processId = await createProcessResponse.json();
}
Several entities will be created using this pattern. As an exercise, see if you can write a function to first check if an entity exists and create it if it does not.
Create Traceability
Traceability can be created in a similar method:
get_traceability_by_name_response = gs_request("setup/v1/trace/name", "GET", { "name": "Shift" })
if get_traceability_by_name_response.status_code == 200:
traceability_id = get_traceability_by_name_response.json()
else:
traceability_id = gs_request("setup/v1/trace", "POST", None, {
"name": "Shift",
"type": "text",
"filterRTFs": False,
"required": "never",
"isValueSpecific": False,
"textOptions": {
"restricted": False
}
}).json()
let traceabilityId;
const getTraceabilityByNameResponse = await gsRequest('setup/v1/trace/name', 'GET', { name: 'Shift' });
if (getTraceabilityByNameResponse.status === 200) {
traceabilityId = await getTraceabilityByNameResponse.json();
} else {
const createTraceabilityResponse = await gsRequest('setup/v1/trace', 'POST', undefined, {
name: 'Shift',
type: 'text',
filterRTFs: false,
required: 'never',
isValueSpecific: false,
textOptions: {
restricted: false
}
})
traceabilityId = await createTraceabilityResponse.json();
}
Create a Part and Unit
Next, create a Part.
As an exercise, use the API to create a Part named 3-Inch Bolt. Then create a Unit named Inches. Make sure you store the ID of the part and unit for use later. Reference the API documentation to look up the Create endpoints for Parts and Units. If you get stuck, the full code for this guide is available at the bottom of the article.
Create a Characteristic
Although the code for creating a Characteristic with the API follows the same pattern as the entities created above, it requires links to the previous entities, which must be provided in the form of the numeric internal ID. In addition, retrieving a Characteristic by name also requires specifying the name of the part, as multiple Characteristics may have the same name.
get_characteristic_by_name_response = gs_request("setup/v1/spccharacteristic/name", "GET", { "name": "Thread Pitch", "partName": "3-Inch Bolt" })
if get_characteristic_by_name_response.status_code == 200:
characteristic_id = get_characteristic_by_name_response.json()
else:
characteristic_id = gs_request("setup/v1/spccharacteristic", "POST", None, {
"name": "Thread Pitch",
"partId": part_id, # From the previously created part
"unitId": unit_id, # From the previously created unit
"subgroupSize": 3,
"rangeType": "movingRange",
"controlLimitNltZero": False,
"displayFormat": "0.##",
"targetX": 0.45,
"lowerSpec": 0.449,
"upperSpec": 0.451
}).json()
let characteristicId;
const getCharacteristicByNameResponse = await gsRequest('setup/v1/spccharacteristic/name', 'GET', { name: 'Thread Pitch', partName: '3-Inch Bolt' });
if (getCharacteristicByNameResponse.status === 200) {
characteristicId = await getCharacteristicByNameResponse.json();
} else {
const createCharacteristicResponse = await gsRequest('setup/v1/spccharacteristic', 'POST', undefined, {
name: 'Thread Pitch',
partId: partId, // From the previously created part
unitId: unitId, // From the previously created unit
subgroupSize: 3,
rangeType: 'movingRange',
controlLimitNltZero: false,
displayFormat: '0.##',
targetX: 0.45,
lowerSpec: 0.449,
upperSpec: 0.451
})
characteristicId = await createCharacteristicResponse.json();
}
Create a Defect
As an exercise, create a Defect. For the purpose of this guide, only the Scratch Defect will be created, and no Defect Category is required.
Submitting Data
Using the API to collect data can be done with the Dataset endpoint. This endpoint corresponds to a collection of data collected together, as with a Sub-Inspection.
To submit data, begin by constructing the data set to be stored. This data set will include:
- The current date
- The Process created above
- The Part created above
- The Shift Traceability
- Data for the Thread Pitch Characteristic
- Data for the Scratch Defect
For more information about the structure of the data request object, see the data request entry in the API reference.
First, import the datetime library:
data = {
"processStandardId": process_id,
"partId": part_id,
"dateTime": datetime.datetime.now().isoformat(),
"traceability": [
{
"id": traceability_id,
"value": "Shift 1"
}
],
"data": [{
"traceability": [],
"type": "spc",
"data": {
"characteristicStandardId": characteristic_id,
"anchorPoint": False,
"values": [{
"value": 0.4499
}, {
"value": 0.4502
}, {
"value": 0.4511
}]
}
}, {
"traceability": [],
"type": "dms",
"data": {
"ncu": 1,
"defects": [{
"defectId": defect_id,
"count": 1
}]
}
}]
}
const data = {
processStandardId: processId,
partId: partId,
dateTime: new Date().toISOString(),
traceability: [
{
id: traceabilityId,
value: 'Shift 1'
}
],
data: [{
traceability: [],
type: 'spc',
data: {
characteristicStandardId: characteristicId,
anchorPoint: false,
values: [{
value: 0.4499
}, {
value: 0.4502
}, {
value: 0.4511
}]
}
}, {
traceability: [],
type: 'dms',
data: {
ncu: 1,
defects: [{
defectId: defectId,
count: 1
}]
}
}]
};
Information
If you have multiple locations set in your account, you will also need to provide the locationId field as a top level property of the object.
To submit the data, issue a POST request to the Dataset endpoint, using the above constructed data as the body:
Executing the above code should show a 200 response code, indicating that the data was inserted successfully.
Real-Time Failures
In order to check if there were any failures in the generated data set, you will first need to create a Real-Time Failure Group and attach it to the Characteristic. This may be done anywhere in the code after the creation of the Characteristic.
getRTFGroupgByNameResponse = gs_request("setup/v1/realtimefailuregroup/name", "GET", { "name": "Specs" })
if getRTFGroupgByNameResponse.status_code != 200:
# Create the RTF Group
rtf_group_id = gs_request("setup/v1/realtimefailuregroup", "POST", None, {
"name": 'Specs',
"type": 'spc',
"addedRealTimeFailures": ["xAboveSpec", "xBelowSpec"]
}).json()
# Add it to the characteristic
# Only do this on creation, otherwise it would attempt to add the same group multiple times.
gs_request(f"setup/v1/spccharacteristic/{characteristic_id}", "POST", None, {
"addedRTFGroups": [rtf_group_id]
})
const getRTFGroupgByNameResponse = await gsRequest('setup/v1/realtimefailuregroup/name', 'GET', { name: 'Specs' });
if (getRTFGroupgByNameResponse.status !== 200) {
// Create the RTF Group
const rtfGroupResponse = await gsRequest('setup/v1/realtimefailuregroup', 'POST', undefined, {
name: 'Specs',
type: 'spc',
addedRealTimeFailures: ['xAboveSpec', 'xBelowSpec']
});
const rtfGroupId = await rtfGroupResponse.json();
// Add it to the characteristic
// Only do this on creation, otherwise it would attempt to add the same group multiple times.
await gsRequest(`setup/v1/spccharacteristic/${characteristicId}`, 'POST', undefined, {
addedRTFGroups: [rtfGroupId]
});
}
Now that a Real-Time Failure Group has been attached to the Characteristic, the Data Entry Real-Time Failure endpoint may be used to check for failures in a data set. Before submitting your data set, check for Real-Time Failures:
Under Construction
We're still working on this section.
Sending Alerts
Under Construction
We're still working on this section.
Analyzing Data
Now that some data has been entered, it may be analyzed. The API for retrieving data is complex, and it is recommended that data is analyzed by either exporting it as a CSV or using a Dashboard.
However, if you wish to use the API to analyze data, you may make requests to the data retrieval endpoint. The following code will retrieve the CPK statistic for the Process you created earlier:
analysisResponse = gs_request("analysis/v1/dataRetrieval", "POST", None, {
"dataType": "spc",
"datePeriod": {
"type": "relative",
"relative": "current",
"timePeriod": "day"
},
"timeOffset": int(datetime.datetime.now().astimezone().utcoffset().total_seconds() / 60),
"maxRecords": 25,
"retrieve": [{
"id": "myCPK",
"type": "statsGrid",
"stats": ["Capability"],
"splitBy": [{ "type": "process" }]
}],
"standards": {
"processCharacteristicIds": [{
"characteristicStandardId": characteristic_id,
"processStandardIds": [process_id]
}]
},
"source": "dashboard"
}).json()
statsGridDetail = [x for x in analysisResponse["response"] if x["id"] == "myCPK"][0]
cpk = statsGridDetail["details"][0]["stats"]["cpk"]
print(f"Retrieved CPK: {cpk}")
const analysisResponse = await gsRequest('analysis/v1/dataRetrieval', 'POST', undefined, {
dataType: 'spc',
datePeriod: {
type: 'relative',
relative: 'current',
timePeriod: 'day'
},
timeOffset: new Date().getTimezoneOffset() * -1,
maxRecords: 25,
retrieve: [{
id: 'myCPK',
type: 'statsGrid',
stats: ['Capability'],
splitBy: [{ type: 'process' }]
}],
standards: {
processCharacteristicIds: [{
characteristicStandardId: characteristicId,
processStandardIds: [processId]
}]
},
source: 'dashboard'
});
const retrievedData = await analysisResponse.json();
const statsGridDetail = retrievedData.response.find(x => x.id === 'myCPK');
console.log(`Retrieved CPK: ${statsGridDetail.details[0].stats.cpk}`);
Final Code
The full code for this sample is:
import requests
import datetime
API_KEY = "YOUR API KEY HERE"
BASE_URL = "YOUR URL"
DEVICE_ID = "MACHINE-1"
def gs_request(endpoint, method, query_params = None, body = None):
# Establish the necessary headers
headers = {
"GS-Api-Key": API_KEY,
"GS-Device-Id": DEVICE_ID
}
# Construct the URL
url = f"{BASE_URL}{endpoint}"
if method == "GET":
# Handle GET requests, which have no body
return requests.get(url, headers=headers, params=query_params)
elif method == "DELETE":
# Handle DELETE requests, which have no body
return requests.delete(url, headers=headers, params=query_params)
elif method == "POST":
# Handle POST requests, and let the API know that JSON is being passed in
headers["Content-Type"] = "application/json"
return requests.post(url, headers=headers, json=body, params=query_params)
else:
raise ValueError("Invalid method type.")
def run():
# Attempt to retrieve the process using the name as a query parameter.
get_process_by_name_response = gs_request("setup/v1/process/name", "GET", { "name": "Welding" })
if get_process_by_name_response.status_code == 200:
#The Welding process was found
process_id = get_process_by_name_response.json()
else:
# The process could not be found. Create it instead.
process_id = gs_request("setup/v1/process", "POST", None, {
"name": "Welding",
"sampleSize": 10,
"ncuCost": 0.0
}).json()
#Traceability
get_traceability_by_name_response = gs_request("setup/v1/trace/name", "GET", { "name": "Shift" })
if get_traceability_by_name_response.status_code == 200:
traceability_id = get_traceability_by_name_response.json()
else:
traceability_id = gs_request("setup/v1/trace", "POST", None, {
"name": "Shift",
"type": "text",
"filterRTFs": False,
"required": "never",
"isValueSpecific": False,
"textOptions": {
"restricted": False
}
}).json()
# Part
get_part_by_name_response = gs_request("setup/v1/part/name", "GET", { "name": "3-Inch Bolt" })
if get_part_by_name_response.status_code == 200:
part_id = get_part_by_name_response.json()
else:
part_id = gs_request("setup/v1/part", "POST", None, {
"name": "3-Inch Bolt",
}).json()
# Unit
get_unit_by_name_response = gs_request("setup/v1/unit/name", "GET", { "name": "Inch" })
if get_unit_by_name_response.status_code == 200:
unit_id = get_unit_by_name_response.json()
else:
unit_id = gs_request("setup/v1/unit", "POST", None, {
"name": "Inch",
}).json()
# Characteristic
get_characteristic_by_name_response = gs_request("setup/v1/spccharacteristic/name", "GET", { "name": "Thread Pitch", "partName": "3-Inch Bolt" })
if get_characteristic_by_name_response.status_code == 200:
characteristic_id = get_characteristic_by_name_response.json()
else:
characteristic_id = gs_request("setup/v1/spccharacteristic", "POST", None, {
"name": "Thread Pitch",
"partId": part_id,
"unitId": unit_id,
"subgroupSize": 3,
"rangeType": "movingRange",
"controlLimitNltZero": False,
"displayFormat": "0.##",
"targetX": 0.45,
"lowerSpec": 0.449,
"upperSpec": 0.451
}).json()
getRTFGroupgByNameResponse = gs_request("setup/v1/realtimefailuregroup/name", "GET", { "name": "Specs" })
if getRTFGroupgByNameResponse.status_code != 200:
# Create the RTF Group
rtf_group_id = gs_request("setup/v1/realtimefailuregroup", "POST", None, {
"name": 'Specs',
"type": 'spc',
"addedRealTimeFailures": ["xAboveSpec", "xBelowSpec"]
}).json()
# Add it to the characteristic
# Only do this on creation, otherwise it would attempt to add the same group multiple times.
gs_request(f"setup/v1/spccharacteristic/{characteristic_id}", "POST", None, {
"addedRTFGroups": [rtf_group_id]
})
# Defect
get_defect_by_name_response = gs_request("setup/v1/defect/name", "GET", { "name": "Scratch" })
if get_defect_by_name_response.status_code == 200:
defect_id = get_defect_by_name_response.json()
else:
defect_id = gs_request("setup/v1/defect", "POST", None, {
"name": "Scratch",
"defectCost": 0.0
}).json()
# Data
data = {
"processStandardId": process_id,
"partId": part_id,
"dateTime": datetime.datetime.now().isoformat(),
"traceability": [
{
"id": traceability_id,
"value": "Shift 1"
}
],
"data": [{
"traceability": [],
"type": "spc",
"data": {
"characteristicStandardId": characteristic_id,
"anchorPoint": False,
"values": [{
"value": 0.4499
}, {
"value": 0.4502
}, {
"value": 0.4511
}]
}
}, {
"traceability": [],
"type": "dms",
"data": {
"ncu": 1,
"defects": [{
"defectId": defect_id,
"count": 1
}]
}
}]
}
dataResponse = gs_request('dataentry/v1/dataset', 'POST', None, data)
print(dataResponse.status_code)
analysisResponse = gs_request("analysis/v1/dataRetrieval", "POST", None, {
"dataType": "spc",
"datePeriod": {
"type": "relative",
"relative": "current",
"timePeriod": "day"
},
"timeOffset": int(datetime.datetime.now().astimezone().utcoffset().total_seconds() / 60),
"maxRecords": 25,
"retrieve": [{
"id": "myCPK",
"type": "statsGrid",
"stats": ["Capability"],
"splitBy": [{ "type": "process" }]
}],
"standards": {
"processCharacteristicIds": [{
"characteristicStandardId": characteristic_id,
"processStandardIds": [process_id]
}]
},
"source": "dashboard"
}).json()
statsGridDetail = [x for x in analysisResponse["response"] if x["id"] == "myCPK"][0]
cpk = statsGridDetail["details"][0]["stats"]["cpk"]
print(f"Retrieved CPK: {cpk}")
if __name__ == "__main__":
run()
const API_KEY = 'YOUR API KEY HERE';
const BASE_URL = 'YOUR URL';
const DEVICE_ID = 'MACHINE-1';
function gsRequest(endpoint, method, queryParams, body) {
// Establish the necessary headers.
const headers = {
"GS-Api-Key": API_KEY,
"GS-Device-Id": DEVICE_ID
};
if (method === 'POST') {
headers['Content-Type'] = 'application/json';
}
// Construct the full URL
let url = `${BASE_URL}${endpoint}`;
// Add URL parameters
if (queryParams) {
url += '?' + new URLSearchParams(queryParams).toString();
}
return fetch(url, {
method: method,
headers: headers,
body: body ? JSON.stringify(body) : undefined,
});
}
async function run() {
let processId;
// Attempt to retrieve the process using the name as a query parameter.
const getProcessByNameResponse = await gsRequest('setup/v1/process/name', 'GET', { name: 'Welding' });
if (getProcessByNameResponse.status === 200) {
// The Welding process was found
processId = await getProcessByNameResponse.json();
} else {
// The process could not be found. Create it instead.
const createProcessResponse = await gsRequest('setup/v1/process', 'POST', undefined, {
name: "Welding",
sampleSize: 10,
ncuCost: 0.0
});
processId = await createProcessResponse.json();
}
// Traceability
let traceabilityId;
const getTraceabilityByNameResponse = await gsRequest('setup/v1/trace/name', 'GET', { name: 'Shift' });
if (getTraceabilityByNameResponse.status === 200) {
traceabilityId = await getTraceabilityByNameResponse.json();
} else {
const createTraceabilityResponse = await gsRequest('setup/v1/trace', 'POST', undefined, {
name: 'Shift',
type: 'text',
filterRTFs: false,
required: 'never',
isValueSpecific: false,
textOptions: {
restricted: false
}
});
traceabilityId = await createTraceabilityResponse.json();
}
// Part
let partId;
const getPartByNameResponse = await gsRequest('setup/v1/part/name', 'GET', { name: '3-Inch Bolt' });
if (getPartByNameResponse.status === 200) {
partId = await getPartByNameResponse.json();
} else {
const createPartResponse = await gsRequest('setup/v1/part', 'POST', undefined, {
name: '3-Inch Bolt',
});
partId = await createPartResponse.json();
}
// Unit
let unitId;
const getUnitByNameResponse = await gsRequest('setup/v1/unit/name', 'GET', { name: 'Inch' });
if (getUnitByNameResponse.status === 200) {
unitId = await getUnitByNameResponse.json();
} else {
const createUnitResponse = await gsRequest('setup/v1/unit', 'POST', undefined, {
name: 'Inch',
});
unitId = await createUnitResponse.json();
}
// Characteristic
let characteristicId;
const getCharacteristicByNameResponse = await gsRequest('setup/v1/spccharacteristic/name', 'GET', { name: 'Thread Pitch', partName: '3-Inch Bolt' });
if (getCharacteristicByNameResponse.status === 200) {
characteristicId = await getCharacteristicByNameResponse.json();
} else {
const createCharacteristicResponse = await gsRequest('setup/v1/spccharacteristic', 'POST', undefined, {
name: 'Thread Pitch',
partId: partId,
unitId: unitId,
subgroupSize: 3,
rangeType: 'movingRange',
controlLimitNltZero: false,
displayFormat: '0.##',
targetX: 0.45,
lowerSpec: 0.449,
upperSpec: 0.451
})
characteristicId = await createCharacteristicResponse.json();
}
// Real-Time Failure Group
const getRTFGroupgByNameResponse = await gsRequest('setup/v1/realtimefailuregroup/name', 'GET', { name: 'Specs' });
if (getRTFGroupgByNameResponse.status !== 200) {
// Create the RTF Group
const rtfGroupResponse = await gsRequest('setup/v1/realtimefailuregroup', 'POST', undefined, {
name: 'Specs',
type: 'spc',
addedRealTimeFailures: ['xAboveSpec', 'xBelowSpec']
});
const rtfGroupId = await rtfGroupResponse.json();
// Add it to the characteristic
// Only do this on creation, otherwise it would attempt to add the same group multiple times.
await gsRequest(`setup/v1/spccharacteristic/${characteristicId}`, 'POST', undefined, {
addedRTFGroups: [rtfGroupId]
});
}
// Defect
let defectId;
const getDefectByNameResponse = await gsRequest('setup/v1/defect/name', 'GET', { name: 'Scratch' });
if (getDefectByNameResponse.status === 200) {
defectId = await getDefectByNameResponse.json();
} else {
const createDefectResponse = await gsRequest('setup/v1/defect', 'POST', undefined, {
name: 'Scratch',
defectCost: 0
});
defectId = await createDefectResponse.json();
}
// Data
const data = {
processStandardId: processId,
partId: partId,
dateTime: new Date().toISOString(),
traceability: [
{
id: traceabilityId,
value: 'Shift 1'
}
],
data: [{
traceability: [],
type: 'spc',
data: {
characteristicStandardId: characteristicId,
anchorPoint: false,
values: [{
value: 0.4299
}, {
value: 0.4502
}, {
value: 0.4521
}]
}
}]
};
const dataResponse = await gsRequest('dataentry/v1/dataset', 'POST', undefined, data);
console.log(dataResponse.status);
const analysisResponse = await gsRequest('analysis/v1/dataRetrieval', 'POST', undefined, {
dataType: 'spc',
datePeriod: {
type: 'relative',
relative: 'current',
timePeriod: 'day'
},
timeOffset: new Date().getTimezoneOffset() * -1,
maxRecords: 25,
retrieve: [{
id: 'myCPK',
type: 'statsGrid',
stats: ['Capability'],
splitBy: [{ type: 'process' }]
}],
standards: {
processCharacteristicIds: [{
characteristicStandardId: characteristicId,
processStandardIds: [processId]
}]
},
source: 'dashboard'
});
const retrievedData = await analysisResponse.json();
const statsGridDetail = retrievedData.response.find(x => x.id === 'myCPK');
console.log(`Retrieved CPK: ${statsGridDetail.details[0].stats.cpk}`);
}
run();