Developer API Reference

The LabHQ GraphQL API provides a powerful and flexible approach to working with the data in the system. It can be used for performing operations such as reading, creating, updating, and deleting resources.

See the GraphQL Documentation for more information.

Contents


Working with GraphQL

Overview

Working with GraphQL offers a powerful and flexible approach to querying and manipulating data. Unlike traditional REST APIs, GraphQL enables clients to request exactly the data they need with a single query, reducing over-fetching and under-fetching issues. The GraphQL Documentation provides comprehensive guidance on how to craft queries, mutations, and subscriptions, and offers insights into schema design and best practices. By leveraging GraphQL’s introspection capabilities, developers can explore and understand the API schema, making it easier to build efficient and responsive applications.

User Interface

To interact with our GraphQL API, you can use the Altair UI, available at Altair GraphQL Client. Altair provides an intuitive interface for crafting and testing GraphQL queries, mutations, and subscriptions. It also supports features like schema exploration, query history, and variable management, making it an ideal tool for both beginners and experienced developers. Using Altair, you can quickly experiment with different queries and mutations, view the API’s schema, and efficiently debug your requests.


Understanding Responses

Unlike traditional APIs where HTTP status codes often indicate errors, our GraphQL API consistently returns an HTTP status code of 200 for all responses, except for 401 Unauthorized errors and 400 Bad Request errors.

In GraphQL, error handling is distinct. Although the HTTP status code is 200 - OK, this does not ensure that the query was processed correctly. If an error occurs during query execution, the response will include an errors array detailing the issue.

Examples

200 OK

{
   "errors":[
      {
         "message":"Operation failed: Unhandled HTTP status code: InternalServerError",
         "extensions":{
            "code":"OPERATION_FAILED",
            "codes":[
               "OPERATION_FAILED"
            ],
            "details":"GraphQL.ExecutionError: Operation failed: Unhandled HTTP status code: InternalServerError"
         }
      }
   ],
   "data":{
      "jobs":null
   }
}

In this example:

  • message"Operation failed: Unhandled HTTP status code: InternalServerError"  - Describes the error that occurred.

    extensions :

    • code"OPERATION_FAILED"  - Indicates the type of error.
    • codes["OPERATION_FAILED"]  - An array containing related error codes.
    • details"GraphQL.ExecutionError: Operation failed: Unhandled HTTP status code: InternalServerError"  - Provides additional context about the error.

      data :

    • jobsnull  - Indicates that the jobs  field could not be populated due to the error.

401 Unauthorized

{
   "errors":[
      {
         "message":"Access denied for schema.",
         "extensions":{
            "code":"ACCESS_DENIED",
            "codes":[
               "ACCESS_DENIED"
            ],
            "details":"GraphQL.Server.Transports.AspNetCore.Errors.AccessDeniedError: Access denied for schema."
         }
      }
   ]
}

In this example:

  • message"Access denied for schema."  - A description of the error.

    extensions :

    • code"ACCESS_DENIED"  - Indicates the error type.
    • codes["ACCESS_DENIED"]  - An array of related error codes.
    • details : Additional context about the error.

400 Bad Request

For 400 Bad Request errors, such as incorrect query syntax or invalid fields, you might see a response like this:

{
   "errors":[
      {
         "message":"Cannot query field 'id123' on type 'TestMethodInputType'.",
         "locations":[
            {
               "line":11,
               "column":9
            }
         ],
         "extensions":{
            "code":"FIELDS_ON_CORRECT_TYPE",
            "codes":[
               "FIELDS_ON_CORRECT_TYPE"
            ],
            "number":"5.3.1",
            "details":"GraphQL.Validation.Errors.FieldsOnCorrectTypeError: Cannot query field 'id2121' on type 'TestMethodInputType'."
         }
      }
   ]
}

In this example:

  • message"Cannot query field 'id123' on type 'TestMethodInputType'."  - Describes the error.
  • locations : Indicates where in the query the error occurred (line 11, column 9).

    extensions :

    • code"FIELDS_ON_CORRECT_TYPE"  - Indicates the nature of the error.
    • codes["FIELDS_ON_CORRECT_TYPE"]  - Error codes associated with the issue.
    • number"5.3.1"  - An internal reference number for the error.
    • details : Provides additional context about the error.

API Reference

Jobs

In LabHQ, a job is a group of samples that are processed through the lifecycle together. A job may consist of samples for any number of products. For more information, see Submit Job.

Getting Jobs

To get a list of jobs, use the jobs endpoint.

The jobs loaded are limited to a maximum of 100. The query accepts a filter property which filters on the Job’s identifier, batch number, description and client name properties.

Query Example

An example query for getting a list of jobs:

{
  jobs(top: 100, skip: 0, filter: "job filter") {
    items {
      id
      identifier
      description
      batchNo
      clientId
      status
      submittedBy
      submittedOn
      createdBy
      createdOn
      updatedBy
      updatedOn
      customFieldValues {
        position
        title
        value
      }
      samples {
        id
        identifier
        index
        label
        description
        comment
        batchNo
        jobId
        dueDate
        status
        createdBy
        createdOn
        updatedBy
        updatedOn
        receivedBy
        receivedOn
        approvedBy
        approvedOn
        customFieldValues {
          position
          title
          value
        }
      }
    }
    totalCount
  }
}

Responses

  • 200 (OK):
    • Jobs returned in an array
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Creating Jobs

To create a new job, use the lifecycleCreate mutation endpoint.

The mutation accepts job and sample data as well as associated client, product, test and custom field data.

Once successful, the job will have a status of "Submitted" and be available for further lifecycle processing.

Custom Field Values

📒 Custom fields are a premium feature. Please click here for more information.

Custom field values must align with the corresponding field’s position configured in LabHQ. If the position doesn’t match, the value will be ignored.

Custom field values should be submitted as a string (See example below). For date custom fields, ensure the format follows the ISO 8601 standard: yyyy-MM-ddThh:mm:ssZ . Date values not in this format may cause the date to be invalid.

Mutation Example

An example mutation for creating a new job:

mutation {
  lifecycleCreate(job: {
    clientId: "123e4567-e89b-12d3-a456-426614174000",
    batchNo: "ABC123",
    description: "This is a detailed description of the Job, which can be up to 2000 characters in length.",
    customFieldValues: [
      { position: 1, value: "text"},
      { position: 2, value: "1991-10-14T00:00:00Z"},
      { position: 3, value: "3" }
    ],
    samples: [
      {
        productId: "123e4567-e89b-12d3-a456-426614174001",
        batchNo: "BATCH01",
        description: "Sample description, which can be quite lengthy, up to 2000 characters.",
        label: "Sample Label up to 300 characters",
        comment: "Sample comment up to 2000 characters",
        customFieldValues: [
          { position: 1, value: "text"},
          { position: 4, value: "1991/10/14T00:00:00Z"}
        ],
        tests: [
          {
            id: "b734c2c0-b59c-4575-bb31-4ba1ba2add51",
          },
          {
            id: "904738b7-1cce-4259-9386-bf3fb1b7967d",
          }
        ]
      }
    ]
  }) {
    id
  }
}

Responses

  • 200 (OK):
    • If the job was successfully created, the response includes the job id within the data field.
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Error Codes

Below is a list of errors that can occur with the lifecycleCreate mutation in conjunction with the standard error codes provided by GraphQL:

  • INVALID_REQUEST: Signifies the request structure is incorrect. This could be but not limited to malformed JSON, incorrect query syntax, or missing required data.
  • RESOURCE_NOT_FOUND: This error is returned when a referenced resource (ie: client ID) does not exist.
  • INTERNAL_ERROR: Represents an error that occurred within the server.

Example Successful Response

{
  "data": {
    "lifecycleCreate": {
      "job": {
        "id": "123e4567-e89b-12d3-a456-426614174000"
      }
    }
  }
}

Example Response with Errors

{
  "errors": [
    {
      "message": "Client not found",
      "extensions": {
        "code": "RESOURCE_NOT_FOUND",
        "codes": [
          "RESOURCE_NOT_FOUND"
        ],
        "details": "GraphQL.ExecutionError: Client not found"
      }
    }
  ],
  "data": {
    "lifecycleCreate": null
  }
}

Deleting Jobs

To delete an existing job, use the deleteJob mutation endpoint.

This deletes the job and all related lifecycle data from the system including job, sample, test and result data.

Once successful, the job will no longer be available for use in the lifecycle.

Mutation Example

An example mutation for deleting a job:

mutation {
  deleteJob(
    id: "123e4567-e89b-12d3-a456-426614174001",
    reason: "Reason for deleting the Job"
  )
}

Responses

  • 200 (OK):
    • If the Job was successfully deleted, the response returns true within the data field.
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Error Codes

Below is a list of errors that can occur with the deleteJob mutation in conjunction with the standard error codes provided by GraphQL:

  • INVALID_REQUEST: This can occur when the value for the reason field is not long enough.
  • RESOURCE_NOT_FOUND: This error is returned when the job ID does not exist.
  • INTERNAL_ERROR: Represents an error that occurred within the server.

Example Successful Response

{
  "data": {
    "deleteJob": true
  }
}

Example Response with Errors

{
  "errors": [
    {
      "message": "Job not found",
      "extensions": {
        "code": "RESOURCE_NOT_FOUND",
        "codes": [
          "RESOURCE_NOT_FOUND"
        ],
        "details": "GraphQL.ExecutionError: Job not found"
      }
    }
  ],
  "data": {
    "deleteJob": false
  }
}

Samples

In LabHQ, a sample represents a group of tests that are processed through the lifecycle together.

Getting Samples

To get a list of samples, use the samples endpoint.

The samples loaded are limited to a maximum of 100. The query accepts a filter property which filters on the sample’s identifier, batch number, label and description properties.

Query Example

An example query for getting a list of samples:

{
  samples(top: 100, skip: 0, jobId: "93d140ae-7f13-4850-b684-479d3780159b", filter: "sample filter") {
    items {
      id
      identifier
      index
      label
      description
      comment
      batchNo
      jobId
      dueDate
      status
      createdBy
      createdOn
      updatedBy
      updatedOn
      receivedBy
      receivedOn
      approvedBy
      approvedOn
      customFieldValues {
        position
        title
        value
      }
    }
    totalCount
  }
}

Responses

  • 200 (OK):
    • Samples returned in an array
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Receiving Samples

To receive samples in the lifecycle, use the lifecycleReceive mutation endpoint.

This processes the given Sample IDs and moves them to the next stage in the lifecycle.

Once successful, the samples will have a status of In Test.

Mutation Example

An example mutation for receiving samples:

mutation {
  lifecycleReceive(ids: [
    "9aeafc51-1099-4903-8619-701d8af0cb19",
    "9aeafc51-1099-4903-8619-701d8af0cb19"
  ])
}

Responses

  • 200 (OK)

If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Error Codes

Below is a list of errors that can occur with the lifecycleReceive mutation:

  • INVALID_REQUEST: The sample ID(s) have already been received.
  • RESOURCE_NOT_FOUND: The sample ID(s) have not been found
  • INTERNAL_ERROR: Represents an error that occurred within the server.

Setting Sample Specifications

To set the specification for a sample in the lifecycle, use the updateSampleSpecification mutation endpoint.

The specification must belong to the product associated with the sample.

Mutation Example

An example mutation for updating a sample specification:

mutation {
  updateSampleSpecification(
    sampleId: "9aeafc51-1099-4903-8619-701d8af0cb19",
    specificationId: "8395f9f5-c0b9-4cd5-8ff7-d4bb226846b2")
}

The specificationId is optional. If unset, the specification will be removed from the sample.

mutation {
  updateSampleSpecification(
    sampleId: "9aeafc51-1099-4903-8619-701d8af0cb19")
}

Responses

  • 200 (OK)

If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Error Codes

Below is a list of errors that can occur with the updateSampleSpecification mutation:

  • RESOURCE_NOT_FOUND: The sample ID or the specification ID has not been found.

Tests

To get a list of tests, use the tests endpoint.

Tests are limited to a maximum of 100 per page. the query supports filtering tests by test ID.

Query Example

An example query for getting a list of tests:

{
  tests(top: 100, skip: 0, id: "0abbeb11-bc1a-4073-95d1-4df072b9ae61") {
    items {
      id
      status
      repeatIndex
      outputs {
        id
        indexNo
        name
        resultCalculation
        roundedResult
        displayCalculation
        displayResult
        rounding
        units
      }
    }
    totalCount
  }
}

Responses

  • 200 (OK):
    • Tests returned in an array
    • Total count of tests
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Products

Product information is required to submit jobs in LabHQ, the below reference can be used to get product information in various ways.

Get Products

To get products, use the getProducts endpoint.

The query accepts multiple possible filters including: "name", "id" and "clientId". (See example below)

The query will return data items for associated clients, test suites, specifications (test methods and outputs) and a total count of products returned.

Query Example

An example query for getting a product:

query GetProducts {
  products(
    top: 10,
    skip: 0,
    name: "Product",
    id: "6e778062-6608-4932-b3ef-a3395f5b05f2",
    clientId: "24b6df0b-9d26-4ba3-994b-a5c6e9b4b42d") {
    items {
      id
      name
      version
      clients {
        id
        name
      }
      testSuites {
        id
        name
      }
      specifications {
        id
        name
        description
        testMethods {
          id
          name
          outputs {
            id
            name
            description
          }
        }
      }
    }
    totalCount
  }
}

Responses

  • 200 (OK):
    • Products returned in an array
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Error Codes

Below is a list of errors that can occur with the getProducts endpoint in conjunction with the standard error codes provided by GraphQL:

  • INVALID_REQUEST: Signifies the request structure is incorrect. This could be but not limited to malformed JSON, incorrect query syntax, or missing required data.
  • INTERNAL_ERROR: Represents an error that occurred within the server.

Example Successful Response

{
  "data": {
    "products": {
      "items": [
        {
          "id": "6e778062-6608-4932-b3ef-a3395f5b05f2",
          "name": "Product A",
          "version": 6,
          "clients": [
            {
              "id": "24b6df0b-9d26-4ba3-994b-a5c6e9b4b42d",
              "name": "Client A"
            }
          ],
          "testSuites": [
            {
              "id": "eb60cf98-c5a6-464e-9ae1-e47797facf22",
              "name": "Test Suite A"
            }
          ],
          "specifications": [
            {
              "id": "624353ab-ce36-4090-b0dc-3b7fa5d2f724",
              "name": "Default specification",
              "description": "Specification description",
              "testMethods": [
                {
                  "id": "6f89ae68-943a-45f9-8d5c-045083d80b40",
                  "name": "TM1",
                  "outputs": [
                    {
                      "id": "3cd40c65-8107-4984-8b8a-e7b45d5a531c",
                      "name": "Output 1",
                      "description": "Output 1 description"
                    },
                    {
                      "id": "f02137d6-18a3-4069-80c1-e46360763653",
                      "name": "Output 2",
                      "description": "Output 2 description"
                    }
                  ]
                }
              ]
            }
          ]
        }
      ],
      "totalCount": 1
    }
  }
}

Test Methods

Get Test Methods

To get test methods, use the testMethods endpoint.

The query accepts an 'id' and a 'name' filter

The query will return data items for inputs, outputs and a total count of test methods returned.

Query Example

An example query for getting a test method:

query testMethods {
  testMethods(
    top: 100
    skip: 0
    name: "Test method 1"
  ) {
    items {
      id
      name
      version
      inputs {
        id
        indexNo
        identifier
        units
        fieldType
        mandatory
      }
      outputs {
        id
        indexNo
        name
        units
        rounding
        resultCalculation
        displayCalculation
      }
    }
    totalCount
  }
}

Responses

  • 200 (OK):
    • Test methods returned in an array
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Error Codes

Below is a list of errors that can occur with the testMethods endpoint in conjunction with the standard error codes provided by GraphQL:

  • INVALID_REQUEST: Signifies the request structure is incorrect. This could be but not limited to malformed JSON, incorrect query syntax, or missing required data.
  • INTERNAL_ERROR: Represents an error that occurred within the server.

Example Successful Response

{
  "data": {
    "testMethods": {
      "items": [
        {
          "id": "4e7b065f-1999-4a2e-a461-e03a08369573",
          "name": "TM1 Weight",
          "version": 1,
          "inputs": [
            {
              "id": "3f5ca996-27de-4813-8258-3d8b46fbb8c1",
              "indexNo": 1,
	      "name": "Weight 1",
              "identifier": "$1",
              "units": "g",
              "fieldType": "numeric",
              "mandatory": true
            }
          ],
          "outputs": [
            {
              "id": "35e88de1-70f1-48cc-a82e-e82f3cd7803e",
              "indexNo": 1,
              "name": "Weight 1",
              "units": "g",
              "rounding": null,
              "resultCalculation": "($1+$2+$3)/3",
              "displayCalculation": "$R"
            }
          ]
        }
      ],
      "totalCount": 1
    }
  }
}

Clients

Get Clients

To get clients, use the clients endpoint. Clients are paginated with a maximum of 100 clients per page.

The query accepts multiple optional filters: idnameisCustomer.

  • IsCustomer: A client is a customer when the client has associated products.

Below is a table outlining how the isCustomer filter functions.

isCustomer Return data
Not set All clients
true Clients who are customers
false Clients who are not customers

Query Example

An example query for getting a client:

{
  clients(
    top: 100,
    skip: 0,
    id: "a83bac98-c2e8-4ee7-b52f-5dfcaad7bdfa",
    name: "client",
    isCustomer: true) {
    items {
      id
      name
      address
      town
      county
      country
      postcode
      telephone
      notes
      isCustomer
      contactEmails
    }
    totalCount
  }
}

Responses

  • 200 (OK):
    • Clients returned in an array
    • If there was an issue with the request, the response includes an errors field detailing the problems encountered and an error code.

Example Successful Response

{
  "data": {
    "clients": {
      "items": [
        {
          "id": "24b6df0b-9d26-4ba3-994b-a5c6e9b4b42d",
          "name": "Client",
          "address": "address",
          "town": "Town",
          "county": "county",
          "country": "country",
          "postcode": "postcode",
          "telephone": "0123456789",
          "notes": "Note",
          "isCustomer": true,
          "contactEmails": [
            "a@a",
            "b@b"
          ]
        }
      ],
      "totalCount": 3
    }
  }
}
Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.

Still need help? Contact Us Contact Us