Introduction
Chemwatch API V2 (Beehive Platform) is a new generation GraphQL API which provides an easy and robust way of intergating Chemwatch data and solutions with other systems, such as ERPs/LIMS/LMS/etc. It exposes a GraphQL interface that can be implemented in any programming language capable of sending and processing web API requests.
GraphQL offers significant advantages over traditional REST APIs, including flexible data retrieval where clients request only the data they need, reducing over-fetching and under-fetching. It uses a single endpoint for multiple resources, improving efficiency. Its strongly typed schema enhances clarity and self-documentation, while supporting real-time data updates through subscriptions. Additionally, it provides a superior developer experience with tools like GraphiQL for interactive API exploration and ensures backward compatibility, making API changes seamless without affecting existing queries. These benefits collectively make GraphQL a robust and efficient solution for building scalable APIs.
Base URLs by Region
- Australia:
beehive.chemwatch.net - EU:
beehive-eu.chemwatch.net - USA:
beehive-usa.chemwatch.net
Authentication
Endpoint
https://{Base URL}/webui-api/login
This endpoint authenticates a user by validating their credentials passed in JSON format. Upon successful authentication, an authentication token is returned in the response, which can be used for subsequent authenticated requests.
Request
URL: https://{Base URL}/webui-api/login
Method: POST
Headers:
- Host: <base_URL>
- Content-Type: application/json
Parameters:
- domainName: Domain or account name
- userName: User login name
- password: User password
Example Request
curl -X POST \ <base_URL>/webui-api/login \ -H 'Content-Type: application/json' \ -H 'Cookie: auth-token=<your token>' \ -d '{"password":"password","userName":"name","domainName":"domain"}'
API Key Management
You can also use API keys for authentication. There are three methods available for managing API keys:
createApiKey(input)— creates an API key and returnskeyIdandtoken.listApiKeys— returns the current user’s API keys (keyId,name,createdAt,expiresAt).revokeApiKey(keyId)— revokes an API key.
Postman Usage Example
- Use the legacy login to get a cookie and call
createApiKey. - Save the token from the response.
- Call GraphQL with the header:
Authorization: Bearer <token>
Examples
Create API Key
mutation CreateApiKey($input: CreateApiKeyInput) { createApiKey(input: $input) { keyId token expiresAt name } }
Response:
{ "data": { "createApiKey": { "keyId": "08d5...", "token": "wH-...", "expiresAt": 1781566139139, "name": "API Key" } } }
List API Keys
query ListApiKeysBearer { listApiKeys { keyId name createdAt expiresAt } }
Response:
{ "data": { "listApiKeys": [ { "keyId": "08d5d9cd-f32e-4d95-a61e-0f7ea552b42b", "name": "API Key", "createdAt": 1773790139458, "expiresAt": 1781566139139 } ] } }
Revoke API Key
mutation RevokeApiKey($keyId: String!) { revokeApiKey(keyId: $keyId) { statusCode } }
Response:
{ "data": { "revokeApiKey": { "statusCode": 200 } } }
Getting Started
Graph QL
A GraphQL query type request is a type of request made to a GraphQL server that allows a client to retrieve data. Unlike traditional REST APIs where the client makes different requests to different endpoints to fetch various data, GraphQL allows the client to specify exactly what data they need in a single query. The server then returns only that data, often in a nested and hierarchical structure.
Here are the main components of a GraphQL query type request:
- Endpoint: The URL of the GraphQL server where the request is sent.
- Headers: Include necessary information such as content type and authentication tokens.
- Query: The actual GraphQL query that specifies the data fields the client wants to retrieve.
- Variables: (Optional) Used to pass dynamic values to the query.
Request Format
GraphQL request is a JSON representation of a query. Below is an example of a request:
MyQuery { listFolders { parent location permissionId address { addAddressToSubFolders addressType city country streetAddress zipCode } } }
This query retrieves information about folders, including their address details, from a GraphQL server.
Fields Requested
listFolders: This is the root field being queried. It returns a list of folder objects. Each folder object contains several fields.
Folder Fields
parent: Retrieves the parent identifier or name of the folder.location: Retrieves the location associated with the folder.permissionId: Retrieves the permission identifier for the folder.
Other Location fields (see schema.graphql type Location)
children: Nested child folder locations (same shape asLocation).properties: Folder metadata (Properties:folderName,folderPath,folderType,storeMaterials, country/language overrides, sharing flags, etc.).
Nested Address Fields
- The
addressfield is a nested object within each folder object. It contains additional fields that provide detailed address information for the folder:
addAddressToSubFolders: A boolean value indicating whether the address should be added to subfolders.addressType: The type of address (e.g., Home, Office).city: The city part of the address.country: The country part of the address.streetAddress: The street address part of the address.zipCode: The zip code part of the address.
Sending Request
To send a request you should use the HTTP structure below.
- URL:
<base_URL>/webui-api/graphql - Method: POST
- Headers:
- Host: <base_URL>
- Cookie: auth-token=
; Path=/; Secure; HttpOnly; SameSite=Lax - Content-Type: application/json
- Body: JSON object containing the GraphQL query and variables (if any).
Example Request
curl -X POST \ <base_URL>/webui-api/graphql \ -H 'Content-Type: application/json' \ -H 'Cookie: auth-token=<your token>' \ -d '{"query":"query MyQuery { listFolders { parent location permissionId address { addAddressToSubFolders addressType city country streetAddress zipCode } } }","variables":{}}'
Methods
Queries
getSocket
Retrieves socket details based on input parameters.
- Input:
GetSocketInput—socketId(String!, required). - Output:
[Socket]
example
MyQuery { getSocket(input: {socketId: "id"}) { annexXIV { applicationDate sunsetDate } activePreferredName attachments fileKey casNumber classification classificationAgg countryCode cwNo datasetKey dateAdded dgc dgs1 dgs2 documentName documentKey domain extractionDate generalNotes goldSdsNotes hCodes { code phaseOut } hasesds hasSilver hasgold hasugd hasvgd hazardRating isHidden licUnit languageCode issueDate licVolume location materialName maxVolume maxUnit msdsType name partNumber partNumbers userPartNumbers { value global } phaseOut { authorizationRequired mode sunsetDate timeZone } phaseOutValue pkg preferredName rCodes { code phaseOut } regulatoryBurden { color level x } rootMaterialName socketId specificGravity state tagNames { module name } allTags { name module redFlag isAutoSet description } un unitCur vendorName volume weWriteOwnerDomain weWriteOwnerProfile } }
listSockets
Lists sockets based on input parameters.
- Input:
ListSocketsInput(optional) —page,pageSize,hasSilver,isShowHidden,groupView,sortColumn,sortTypeColumn,vendorsFilter,classificationFilter,tagsFilter,countriesFilter,languagesFilter,hazardFilterId(all optional; filters and pagination as supported by the API). - Output:
[Socket]
example
MyQuery { listSockets(input: { page: "1", pageSize: "50" }) { location datasetKey documentKey classification classificationAgg isHidden generalNotes goldSdsNotes attachments fileKey weWriteOwnerDomain weWriteOwnerProfile msdsType un partNumber preferredName dateAdded activePreferredName maxVolume licVolume volume phaseOutValue dgc dgs1 dgs2 pkg hasgold hasvgd hasugd hasesds hasSilver casNumber issueDate extractionDate documentName hazardRating state specificGravity unitCur maxUnit licUnit domain cwNo rootMaterialName vendorName countryCode languageCode materialName socketId name } }
listSocketsByFolder
Lists sockets filtered by folder based on input parameters.
- Input:
ListSocketsByFolderInput—location(String!, required); optionalheaderFilters(AWSJSON),page,pageSize. - Output:
[Socket]
example
MyQuery { listSocketsByFolder(input: {location: "id"}) { location datasetKey documentKey classification classificationAgg isHidden generalNotes goldSdsNotes attachments fileKey weWriteOwnerDomain weWriteOwnerProfile msdsType un partNumber preferredName dateAdded activePreferredName maxVolume licVolume volume phaseOutValue dgc dgs1 dgs2 pkg hasgold hasvgd hasugd hasesds hasSilver casNumber issueDate extractionDate documentName hazardRating state specificGravity unitCur maxUnit licUnit domain cwNo rootMaterialName vendorName countryCode languageCode materialName socketId name } }
listFolders
Lists all folders available.
- Output:
[Location]
example
MyQuery { listFolders { parent location permissionId children { location parent } properties { folderName folderPath folderType storeMaterials } address { addAddressToSubFolders addressType city country streetAddress zipCode } } }
ownSearch
Performs a customized search based on input parameters.
- Input:
OwnSearchInput— required:filters([FiltersFieldsInput!]!, each withvalue,field, optionaloperation),page,pageSize. Optional:classificationFilter,countriesFilter,documentKeys,groupView,headersFilters,hazardFilterId,isShowHidden,isSimpleView,location,raControls,showSubFolders,socketIdFilter,sortColumn,sortTypeColumn,tagsFilter,vendorsFilter. - Output:
OwnSearchResponse
example
OwnSearchQuery($input: OwnSearchInput!) { ownSearch(input: $input) { cursor { location datasetKey documentKey classification classificationAgg isHidden generalNotes goldSdsNotes attachments weWriteOwnerDomain weWriteOwnerProfile msdsType un partNumber preferredName dateAdded activePreferredName maxVolume licVolume volume regulatoryBurden { x color level } phaseOut { mode sunsetDate timeZone authorizationRequired } annexXIV { sunsetDate applicationDate } phaseOutValue dgc dgs1 dgs2 pkg hCodes { code phaseOut } rCodes { code phaseOut } hasgold hasvgd hasugd hasesds tagNames { name module } partNumbers casNumber issueDate extractionDate documentName hazardRating state specificGravity unitCur maxUnit licUnit domain cwNo rootMaterialName vendorName countryCode languageCode materialName socketId name } lookup { classifications { cnt name } countries { cnt name } languages { cnt name } tags { cnt name } vendors { cnt name } } totalRows } }
fullSearch
Performs a comprehensive search based on input parameters.
- Input:
FullSearchInput— required:page,pageSize. Optional:exactMatchSort,countriesFilter,vendorsFilter,languagesFilter,classificationFilter,settings(SettingsFieldsInput),filters,filter. - Output:
FullSearchResponse(cursor,totalRows, optionalstatusCode)
example
FullSearchQuery($input: FullSearchInput!) { fullSearch(input: $input) { statusCode cursor { documentKey datasetKey documentName issueDate catalogueName rootMaterialName cwNo countryCode languageCode vendor origin { doc_no } vendorName materialName hasgold hasvgd haswewrite casNumber } totalRows } }
data
Retrieves data points based on input parameters.
- Input:
DataInput—socketIds([String!]!),dataPoints([String!]!). - Output:
[DataPoint]
example
DataQuery($input: DataInput!) { data(input: $input) { socketId data { name value description } } }
updates
Retrieves history items based on update input parameters.
- Input:
UpdatesInputlocation(String!): Folder location ID, or"all"to include all folders.actions([String]): Optional list of action names to filter (see Supported Actions).type(String): Optional additional type filter (see schema).startDate(Float): Optional start date filter.endDate(Float): Optional end date filter.page(Int): Optional page number.pageSize(Int): Optional page size.
- Output:
[HistoryItem]
Supported Actions
| Internal Action Name | Display Message |
|---|---|
| setMaxVolume | Change Max Volume |
| setLicensedVolume | Change Licensed Volume |
| setCurrentVolume | Change Current Volume |
| refillVolume | Refill Volume |
| setPreferredName | Change Preferred Name |
| setActivePreferredName | Active Preferred Name |
| addItem | Add Item |
| publishUgd | Publish UGD |
| unpublishUgd | Unpublish UGD |
| updateSds | Update SDS |
| copyItem | Copy Item |
| moveItem | Move Item |
| restoreItem | Restore Item |
| moveRecycleBinItem | Move Recycle Bin |
| editFolderType | Edit Folder Type |
| editFolder | Edit Folder |
| renameFolder | Rename Folder |
| createFolder | Create Folder |
| moveFolder | Move Folder |
| copyFolder | Copy Folder |
| removeFolder | Remove Folder |
| removeItem | Remove Item |
| restoreFolder | Restore Folder |
| changedRaState | Changed Risk Assessment State |
| changedRaOperatingTemperature | Changed Risk Assessment Operating Temperature |
| changedRaStatus | Changed Risk Assessment Status |
| scaleOfUseLiquidsChanged | Changed Risk Assessment Scale Of Use Liquids |
| scaleOfUseSolidsChanged | Changed Risk Assessment Scale Of Use Solids |
| volatilityChanged | Changed Risk Assessment Volatility |
| frequencyOfUseLongChanged | Changed Risk Assessment Frequency Of Use Long |
| frequencyOfUseShortChanged | Changed Risk Assessment Frequency Of Use Short |
| changedRaDischarge | Changed Risk Assessment Discharge |
| addPartNumber | Add Part Number |
| editPartNumber | Edit Part Number |
| removePartNumber | Remove Part Number |
| extractVgd | Extract VGD |
example 1
UpdatesQuery($input: UpdatesInput!) { updates(input: $input) { id domain user action timestamp originvalue targetvalue locationorigin locationtarget fullpathorigin fullpathtarget socketidorigin socketidtarget socketorigin sockettarget cwnumber materialname vendor documentkey raid gridtype productkey receiptkey stocktakekey transferrequestnumber cataloguename stocktakerequestnumber barcodes calledapp containerkeys stocktakestatus module isfromsisot } }
example 2
query MyQuery { updates(input: { location: "all", actions: ["addItem"] }) { action domain user timestamp documentkey cwnumber } }
document
Retrieves document details based on input parameters.
- Input:
DocumentInput—documentKey(String!, required); optionalcountryCode,languageCode,type. - Output:
String
example
{ document(input: { documentKey: "6d2d9c5a-5569-4cbd-91b9-977a310c0dc5" }) }
dictionary
Retrieves dictionaries for countries and languages.
- Output:
Dictionary
example
{ dictionary { countries { code name } languages { code name } } }
fullData
Retrieves full data points.
- Input:
FullDataInput—datasetKeys([String!]!),dataPoints([String!]!); optionalcountryCode,languageCode. - Output:
[FullDataResult]
example
FullDataQuery($input: FullDataInput!) { fullData(input: $input) { datasetKey data { name value description } } }
userId
Retrieves user ID information based on domain and username.
- Input:
UserIdInput—domainName(String!),userName(String!). - Output:
String
example
UserIdQuery($input: UserIdInput!) { userId(input: $input) }
domainUsers
Retrieves domain users information.
- Input:
DomainUsersInput— optionallimit,offset. - Output:
[DomainUsersResponse]
example
DomainUsersQuery($input: DomainUsersInput!) { domainUsers(input: $input) { userId name } }
container
Retrieves detailed information about a container.
- Input:
ContainerInput—containerId(String!, required). - Output:
[Container]
example
ContainerQuery($input: ContainerInput!) { container(input: { containerId: "your-container-id" }) { productName cas barcode manufacture cat uom containerType containerSize physicalForm inventoryDate folderPath } }
getContainer
Retrieves container detail based on container ID.
- Input:
ContainerInput—containerId(String!, required). - Output:
ContainerDetail
example
GetContainerQuery($input: ContainerInput!) { getContainer(input: { containerId: "your-container-id" }) { containerKey productKey barcode catalogueName vendor location statusId } }
listContainers
Lists containers based on inputs.
- Input:
ListContainersInput—documentKey(String!, required). - Output:
[ListContainerDetail]
example
ListContainersQuery($input: ListContainersInput!) { listContainers(input: { documentKey: "your-document-key" }) { containerKey productKey documentKey location ContainerType ContainerStatus } }
listContainersByFolder
Lists containers based on folder location.
- Input:
ListContainersByFolderInput—location(String!, required). Optional:page,pageSize,sortColumn,sortTypeColumn,headerFilters(AWSJSON),productKeys,showSubFolders,hideSetAside,groupView. - Output:
ListContainersByFolderResponse—statusCode,cursor([ContainerDetail]).
ownSearchContainer
Performs a customized search for containers.
- Input:
OwnSearchContainerInput—location(String!, required). Optional:raControls,groupView,page,pageSize,filters,grid,socketIdFilter,showSubFolders,vendorsFilter,classificationFilter,isShowHidden,tagsFilter,countriesFilter,languagesFilter,documentKeys,hazardFilterId,sortColumn,sortTypeColumn,isSimpleView,headerFilters(AWSJSON). - Output:
OwnSearchContainerResponse—statusCode,cursor([ContainerDetail]).
getRiskAssessment
Retrieves a specific risk assessment.
- Input:
GetRiskAssessmentInput—riskAssessmentId(String!, required). - Output:
RiskAssessmentResponse
example
GetRiskAssessmentQuery($input: GetRiskAssessmentInput!) { getRiskAssessment(input: $input) { statusCode riskAssessment { id status task gridTypeUn gridTypeIlo riskAssessmentHazardRatingDg socketId unRiskBand { rating } iloRiskBand { rating } riskBand { rating } ilo { protectiveEquipment controls } un { protectiveEquipment controls } job { approvedBy date reviewDate operatingProcedure } riskAssessmentHazardRating { rating } } } }
listRiskAssessments
Lists risk assessments.
- Input:
ListRiskAssessmentsInput—socketId(String!, required); optionalpage,pageSize(strings, as in schema). - Output:
RiskAssessmentListResponse—statusCode,riskAssessments,totalCount.
example
query ListRiskAssessmentsQuery($input: ListRiskAssessmentsInput!) { listRiskAssessments(input: $input) { statusCode totalCount riskAssessments { id status task } } }
retrieveContainerInfo
Retrieves info about a container.
- Input:
RetrieveContainerInfoInput—formId(String!),type(String!),location(String!); optionalproductKey,containerKey. - Output:
RetrieveContainerInfoResponse—statusCode,body(action,resultContainer,resultForm, each withRetrieveContainerResult:Count,ScannedCount,ItemswithformVersion,isContainer,formId,timestamp,socket,domain,type,formData).
example
query RetrieveContainerInfoQuery($input: RetrieveContainerInfoInput!) { retrieveContainerInfo(input: $input) { statusCode body { action resultContainer { Count ScannedCount Items { formId isContainer timestamp } } } } }
Mutations
API key mutations createApiKey and revokeApiKey, and the listApiKeys query, are documented under Authentication above.
createSocket
Creates a new socket with the specified input parameters.
- Input:
CreateSocketInput—location,materials(CreateSocketMaterialsInputentries with country/language, vendor/material/cas/cwNo, optional keys),shared(Boolean). - Output:
CreateSocketResult
example
CreateSocketMutation($input: CreateSocketInput!) { createSocket(input: $input) { statusCode duplicateMessage duplicate socketIds } }
updateSocket
Updates an existing socket based on the input parameters.
- Input:
UpdateSocketInput—domain,name,volume,unit,socketId,density,location,documentKey,datasetKey,typeVolume(see schema for types). - Output:
StatusCode
example
UpdateSocketMutation($input: UpdateSocketInput!) { updateSocket(input: $input) { statusCode } }
deleteSocket
Deletes a socket based on the input parameters.
- Input:
DeleteSocketInput—location,materials(socketId,pathperMaterialsInput),shared. - Output:
StatusCode
example
DeleteSocketMutation($input: DeleteSocketInput!) { deleteSocket(input: $input) { statusCode } }
createLocation
Creates a new location with the specified input parameters.
- Input:
CreateLocationInput— optionalfolder(FolderInput: nestedproperties/address), optionalparent. - Output:
StatusCode
example
CreateLocationMutation($input: CreateLocationInput!) { createLocation(input: $input) { statusCode } }
deleteLocation
Deletes a location based on the input parameters.
- Input:
DeleteLocationInput—location,path(both required). - Output:
StatusCode
example
DeleteLocationMutation($input: DeleteLocationInput!) { deleteLocation(input: $input) { statusCode } }
msdsRequest
Submits a MSDS (Material Safety Data Sheet) request using the provided input parameters.
- Input:
MsdsRequestInput— large nested structure (region,domain,quantity,client,creator,creatorEmail, document flags,path, optionalcomment/emailCc/isUrgent, andregistrationswith attachments and product/vendor data). SeeMsdsRequestInput/MsdsRequestRegistrationin the schema. - Output:
StatusCode
example
MsdsRequestMutation($input: MsdsRequestInput!) { msdsRequest(input: $input) { statusCode } }
createContainer
Creates a new container.
- Input:
CreateContainerInput—catalogName,catalogNumber,containerSizeUnits,containerSize,deliveryLocation,quantity(required strings); optional barcode/SARA/material fields per schema. - Output:
CreateContainerResponse(statusCode,productswith nestedProductData/ContainerData).
addUserPartNumber
Adds a user part number.
- Input:
SaveUserPartNumberInput—documentKey,location,partNumber(UserPartNumberInput:value,oldValue,global,oldGlobal,fullPathOrigin,userName); optionalsocketId. - Output:
SaveUserPartNumberResponse
deleteUserPartNumber
Deletes a user part number.
- Input:
SaveUserPartNumberInput(same shape as add). - Output:
SaveUserPartNumberResponse
Contacts
Please direct your questions to mailto:it@chemwatch.net.
Powered by Chemwatch Beehive Platform.
Last updated:
