Homepage Integrity Systems
NAV

Introduction

A wholly owned subsidiary of Meat & Livestock Australia, the Integrity Systems Company (ISC) is responsible for delivering the red meat industry’s on-farm assurance and through-chain traceability programs. These are the Livestock Production Assurance (LPA) program, and the National Livestock Identification System (NLIS) which together make up Australia’s red meat integrity system.

These programs are connected through LPA National Vendor Declarations (LPA NVDs), which link on-farm assurance to livestock traceability. This makes LPA NVDs the legal document guaranteeing the quality, safety and traceability of Australian red meat products.

The ISC is also responsible for the development and delivery of the Digital Value Chain Strategy which will ensure the Australian red meat industry can make better use of existing and new data. The strategy will deliver improved feedback systems for producers including Livestock Data Link (LDL), along with conducting research and development that seeks to find the best digital technology and database management systems that will strengthen our integrity systems over time.

ISC’s mission is to grow red meat value chain opportunities through integrity and information systems innovation. It is essential to enhance our systems and technologies to stay ahead of our global competitors, maintain our point of difference, and enable Australia’s red meat industry to capture price premiums from consumers and customers who are willing to pay more for higher levels of product assurance.

Our API’s are a combination of SOAP, REST and GraphQL. Our API has predictable, resource-oriented URLs, and uses HTTP response in combination with API Status codes to indicate API errors. We use built-in HTTP features, like HTTP verbs, which are understood by off-the-shelf HTTP clients. JSON and XML is returned in all API responses including errors.

For further information about ISCs APIs contact:

Peter Quigley

ISC Integrator Analyst

pquigley@integritysystems.com.au

02 9436 9246

eNVD

About eNVD

The Livestock Production Assurance (LPA) National Vendor Declaration (NVD) communicates the food safety and treatment status of sheep, cattle or goats every time they move – between properties, to saleyards, or to processors.

NVDs are a legal document that are key to Australian red meat’s traceability and market access. It is crucial that the NVD is filled out accurately. When users tick a box or answer a question on the LPA NVD, they are declaring their on-farm practices meet LPA requirements, and ultimately customer expectations.

Their tick must be backed up by accurate farm records. This is a pledge that the meat from their farm has been produced safely, ethically and meets biosecurity requirements – it means they they stand by what they sell.

The LPA electronic National Vendor Declaration (eNVD) system is a faster, easier way to complete livestock consignments. The eNVD system is not just a place to fill out a NVD – it is a system for completing all consignment paperwork digitally including livestock assurance and health declarations. The system will be continuously improved to create better experiences for users and add value to our industry’s integrity. For more information, visit the ISC website here.

1. Introduction

The eNVD (electronic National Vendor Declaration) API is a powerful tool that allows developers to integrate livestock consignment management functionality into their applications. It provides a comprehensive set of endpoints to create, manage, and retrieve consignment and template data.

This developer portal is designed for software developers, system integrators, and other technical professionals who want to leverage the eNVD API to build applications and services related to livestock consignment management.

1.1 The New Account Dynamic within eNVD

The eNVD system introduces a new account dynamic that simplifies user management and access control. Instead of managing multiple logins for different systems (e.g., LPA, NLIS), users now have a single myMLA login and profile that encompasses all their associated accounts.

Within a single myMLA login, a user can have multiple accounts, such as:

*Linking of NLIS and LPA accounts to a myMLA user is not handled within the eNVD platform. To link these accounts, please direct the user to log into the myMLA dashboard and select to link their respective product accounts.

Each account is identified using a new eNVD Account Id (eNVDAccountId) and must be provided with any eNVD API request.

Different accounts are assigned different roles which determine the level of access an account has to the eNVD system. For example, LPA accounts are assigned the producer role, which is the only role with permission to create consignments.

More detail on the new eNVD roles and their permissions is covered in section 7 of this document.

2. Getting Started

To start using the eNVD API, you’ll need to set up your development environment and obtain the necessary credentials. Follow the steps below to get started:

  1. API Endpoints:

Choose the appropriate endpoint based on your development stage and requirements.

  1. Authentication and Authorisation:

    • The eNVD API uses myMLA as the identity provider and OAuth 2.0 for authentication and authorisation.
    • To access protected resources and perform actions on behalf of users, you need to include an OAuth 2.0 access token in the authorization header of each API request.
    • Access tokens can be obtained by following the OAuth 2.0 authorisation Code flow, which involves redirecting the user to the myMLA login page, obtaining an authorisation code, and exchanging it for an access token.
  2. Obtaining OAuth Client Credentials:

    • To integrate your application with the eNVD API, you need to register your application and obtain OAuth client credentials (client ID and client secret).
    • Contact the eNVD support team at support@integritysystems.com.au to request client credentials. Provide them with your application details and the intended use case.
  3. API Request and Response Format:

    • The eNVD API follows the GraphQL specification, which provides a flexible and efficient way to query and mutate data.
    • API requests should be sent as POST requests to the appropriate endpoint, with the GraphQL query or mutation included in the request body.
    • The request and response data format is JSON.

Once you have obtained the necessary credentials and set up your development environment, you’re ready to start making API requests and integrating the eNVD API into your application.

3. Authentication and authorisation

The eNVD API uses OAuth 2.0, with myMLA as the identity provider, to ensure secure access to protected resources and user data. OAuth 2.0 is an industry-standard protocol that allows users to grant limited access to their data without exposing their credentials.

The recommended OAuth flow for the eNVD API is the authorisation Code Flow, which provides a secure way to obtain access tokens and refresh tokens. This flow involves the following steps:

  1. Redirecting the user to the myMLA login page to authenticate and authorize your application.
  2. Obtaining an authorisation code upon successful authentication and authorisation.
  3. Exchanging the authorisation code for an access token and a refresh token.
  4. Using the access token to make authenticated API requests on behalf of the user.
  5. Using the refresh token to obtain a new access token when the current one expires.

The authorisation Code Flow provides several advantages, including:

3.1 Generating an Access Token

To generate an access token using the authorisation Code Flow, follow these steps:

  1. Request the authorisation Code:
https://sso-s.mla.com.au/authorize?response_type=code&scope=openid profile email offline_access&client_id=<YOUR_CLIENT_ID>&redirect_uri=https://localhost:3030/callback&audience=https://api.uat.integritysystems.com.au/graphql&state=<Your State>


  1. Exchange the authorisation Code for an Access Token:
curl -X POST 'https://sso-s.mla.com.au/oauth/token' \
  --header 'Content-Type: application/x-www-form-urlencoded'\
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode 'redirect_uri=https://localhost:3030/callback' \
  --data-urlencode 'client_id=<YOUR_CLIENT_ID>' \
  --data-urlencode 'code=<authorisation_CODE>'




  1. Use the Access Token:
authorisation: Bearer <ACCESS_TOKEN>

Now you can make authenticated API calls to the eNVD API using the obtained access token.


3.2 Refreshing Access Tokens

curl -X POST 'https://sso-s.mla.com.au/oauth/token' \
  --header 'Content-Type: application/x-www-form-urlencoded'\
  --data-urlencode 'grant_type=refresh_token' \
  --data-urlencode 'client_id=<YOUR_CLIENT_ID>' \
  --data-urlencode 'refresh_token=<REFRESH_TOKEN>'

Access tokens have an expiration time, typically set to 24 hours. To continue making authenticated requests after the access token expires, you can use the refresh token to obtain a new access token without requiring the user to re-authenticate.

To refresh an access token:

  1. Make a POST request to the myMLA token endpoint, including the refresh token, client ID, client secret, and grant type.

  2. myMLA will respond with a new access token and refresh token.

  3. Update your application to use the new access token for subsequent API requests.

Refresh tokens have a longer lifespan compared to access tokens, typically around 30 days. It’s important to securely store refresh tokens and handle them with care, as they can be used to obtain new access tokens without user interaction.

3.3 Optional PKCE Code Challenge


https://sso-s.mla.com.au/authorize?response_type=code&client_id=<YOUR_CLIENT_ID>&redirect_uri=https://localhost:3030/callback&scope=openid profile email offline_access&audience=https://api.uat.integritysystems.com.au/graphql&state=<YOUR_STATE>&code_challenge=<CODE_CHALLENGE>&code_challenge_method=S256

For enhanced security, you can optionally implement the Proof Key for Code Exchange (PKCE) extension to the authorisation Code Flow. PKCE adds an additional layer of protection against authorisation code interception attacks.

To use PKCE:

curl -X POST 'https://sso-s.mla.com.au/oauth/token' \
  --header 'Content-Type: application/x-www-form-urlencoded'\
  --data-urlencode 'grant_type=authorisation_code' \
  --data-urlencode 'redirect_uri=https://localhost:3030/callback' \
  --data-urlencode 'client_id=<YOUR_CLIENT_ID>' \
  --data-urlencode 'code=<authorisation_CODE>' \
  --data-urlencode 'code_verifier=<CODE_VERIFIER>'

By implementing PKCE, you add an extra layer of security to the authorisation process, mitigating the risk of authorisation code interception and replay attacks.

  1. Generate a code verifier and code challenge:
  1. Include the code challenge and code challenge method in the authorisation request:

  2. When exchanging the authorisation code for an access token, include the code verifier in the token request:

4. The eNVD v2 API

To leverage the v2 eNVD API, there are a few key areas that have changed from your existing integration. This section will guide you through the necessary steps to migrate your application to the new API.

4.1 myMLA and eNVD User Registration

  1. Users must create their myMLA account via the myMLA website (https://mymla.com.au/). Once they have registered their myMLA account, they will be able to link any of their existing NLIS or LPA accounts via the myMLA dashboard “linked services” menu.

  2. After linking all services, users must also register themselves with the eNVD system. The easiest way to get users registered in the eNVD system is to direct them to the new eNVD website or mobile application. Once they sign in with their myMLA account, if they have not already registered, they will be stepped through the eNVD registration process.

4.2 Updating the API URL

The API endpoints have changed for the new eNVD API. Update your application to use the following URLs:

4.3 Changing Authentication/authorisation Flows

The new eNVD API uses OAuth 2.0 with the authorisation Code Flow for authentication and authorisation. You will need to update your application to follow this flow:

  1. Redirect the user to the myMLA authorisation endpoint to obtain an authorisation code.
  2. Exchange the authorisation code for an access token and refresh token.
  3. Use the access token to make authenticated API requests.
  4. Use the refresh token to obtain a new access token when the current one expires.

Refer to section 3 of this document for detailed instructions on implementing the OAuth 2.0 authorisation Code Flow.

4.4 Using the System

  1. Users must ’log in’ to the eNVD system to use the APIs correctly. There are two scenarios on login:
  1. All calls to the new API must include the myMLA access token as a bearer token in the authorization header.

  2. Some GraphQL queries and mutations now require a new parameter (envdAccountId) to specify the account to perform the action under. Ensure that you include this parameter in the relevant API requests.

Refer to section 5 of this document to learn how to determine if a user is registered in the eNVD system.

5. User Registration and Management

This section covers the process of determining if a user is registered in the eNVD system, registering a user, and managing user accounts.

5.1 Determining if a User is Registered

query UserSignInQuery {
userDetailsQuery() {
 data {
   auth0Id
   isNewUser
   email
   firstName
   lastName
   mobilePhone
   defaultAccount
   accounts {
     envdAccountId
     accountLabel
     accountId
     accountType
     email
     properties {
       // Any LPA/NLIS/Transporter properties can be requested here.
       // See the GraphQL playground for full schema
     }
   }
 }
}
}

To determine if a user is registered in the eNVD system, follow these steps:

  1. Call the signIn query, authenticated using the myMLA token. No need to specify any user parameters, as this is determined directly from the myMLA token.

  2. Check the value of the isNewUser field in the response:

Example signIn query:


Example response for an unregistered user:

{
  "auth0Id": "1234abcd",
  "isNewUser": true,
  "email": "bobby@farm.com",
  "firstName": "",
  "lastName": "",
  "mobilePhone": "",
  "defaultAccount": "",
  "accounts": [
    {
      "envdAccountId": "11223344",
      "accountLabel": "QAZZ7777",
      "accountId": "1234567",
      "accountType": "LPA",
      "email": "bobby@farm.com",
      "properties": {}
    }
  ]
}




Example response for a registered user:

{
  "auth0Id": "1234abcd",
  "isNewUser": false,
  "email": "bobby@farm.com",
  "firstName": "Bobby",
  "lastName": "Smith",
  "mobilePhone": "0404555666",
  "defaultAccount": "envd-11223344",
  "accounts": [
    {
      "envdAccountId": "11223344",
      "accountLabel": "QAZZ7777",
      "accountId": "1234567",
      "accountType": "LPA",
      "email": "bobby@farm.com",
      "properties": {}
    }
  ]
}




5.2 Registering a User in eNVD

To register a user in the eNVD system:

Direct the user to the new eNVD website or mobile application. Prompt the user to sign in with their myMLA account. If the user is not already registered, they will be automatically stepped through the eNVD registration process.

Note: Users who have previously used the eNVD mobile app or new eNVD website will already be registered.

5.3 Linking NLIS and LPA Accounts to myMLA

To link NLIS and LPA accounts to a myMLA user:

Direct the user to log into the myMLA dashboard. Instruct the user to navigate to the “linked services” menu. Guide the user to link their NLIS and LPA accounts.

Note: Linking NLIS and LPA accounts is not handled within the eNVD platform itself. It must be done through the myMLA dashboard.

6. Using the API

This section provides an overview of how to use the eNVD API, including GraphQL basics, authorisation, queries, mutations, and the envdAccountId parameter.

6.1 GraphQL API Overview

The eNVD API is built using GraphQL, a query language for APIs that provides a flexible and efficient way to request and manipulate data. GraphQL allows you to define the structure of your data, specify the fields you need, and retrieve only the relevant information in a single request.

Key concepts in GraphQL:

To learn more about GraphQL and its concepts, refer to the official GraphQL documentation: https://graphql.org/learn/

6.2 authorisation Header and Bearer Token

authorisation: Bearer <ACCESS_TOKEN>

All requests to the eNVD API must include an authorisation header with a valid access token. The access token should be included as a bearer token in the authorization header of the request.

Replace <ACCESS_TOKEN> with the actual access token obtained through the OAuth 2.0 authorisation Code Flow (refer to section 3 for more details).

6.3 Queries and Mutations

Example query to retrieve a list of consignments:

query fetchConsignments($envdAccountId: String!, $first: Int, $after: String) {
  consignments(envdAccountId: $envdAccountId, first: $first, after: $after) {
    totalCount
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      cursor
      node {
        id
        number
        status
        # Include other fields as needed #
      }
    }
  }
}

Example mutation to create a new consignment:

mutation createConsignment(
  $envdAccountId: String!
  $input: CreateOrSaveConsignmentInput!
) {
  createOrSaveConsignment(envdAccountId: $envdAccountId, input: $input) {
    data {
      id
      number
      status
      # Include other fields as needed #
    }
  }
}

The eNVD API provides a set of GraphQL queries and mutations to interact with the system. Queries are used to fetch data, while mutations are used to modify data.

For a complete list of available queries and mutations, refer to the eNVD API documentation or explore the GraphQL schema using the GraphQL playground (see section 6.5).




6.4 Using the envdAccountId Parameter

query Consignments($envdAccountId: String!) {
  consignments(envdAccountId: $envdAccountId) {
    totalCount
    #Include fields as needed#
  }
}

With the introduction of the new user paradigm in the eNVD API, some queries and mutations now require an envdAccountId parameter to specify the account under which the action should be performed. The envdAccountId is mandatory for these operations.

To obtain the envdAccountId, make a request to the userDetailsQuery (refer to section 5.1 for an example). The envdAccountId can be found in the accounts array of the response.

6.5 GraphQL Playground

The eNVD API provides a GraphQL playground, an interactive tool for exploring and testing the API. The playground allows you to browse the schema, execute queries and mutations, and view the responses. To access the GraphQL playground:

UAT/Staging environment: https://api.uat.integritysystems.com.au/v2/ui/playground

Use the playground to familiarize yourself with the available queries, mutations, and the structure of the GraphQL schema.

6.6 Consignments, Forms, Questions, and Answers

6.6.1 Consignment

A consignment represents a shipment or movement of livestock from one location to another. It contains all the relevant information about the livestock being transported, including the origin, destination, owner, consignee, and specific details about the animals.

6.6.2 Forms

Forms are associated with a consignment and represent different types of documents or declarations required for the movement of livestock.

Forms capture all the information related to the livestock within the consignment. The information captured on a form is determined by the program owner.

An eNVD user can only create a form for the programs they are accredited to (i.e. user must be both LPA and EU accredited to be able to create an EU vendor declaration).

All forms in the eNVD platform are identified with a unique Form ID. As new versions of forms are published, the form ID will also be updated to identify the change.

As of May 2024, the current form versions are:

Form IDProgramForm NameSpecies
LPAC1LPALPA National Vendor DeclarationCattle
EUC1LPALPA European Union National Vendor DeclarationCattle
LPABC1LPALPA National Vendor DeclarationBobby Calves
LPASL1LPALPA National Vendor DeclarationSheep
LPAG2LPALPA National Vendor DeclarationGoats
NFASC0NFASNFAS Form BCattle
NFASDDC1NFASNFAS Delivery DocketCattle
NFASEUC1NFASNFAS Delivery Docket European Union Grain Fed High Quality BeefCattle
MSAC1MSAMSA Cattle Vendor DeclarationCattle
HSSL1National Sheep Health DeclarationSheep
HSG0National Goat Health DeclarationGoats
HSC2National Cattle Health DeclarationCattle

6.6.3 Questions

Questions are the individual pieces of information that need to be collected for a consignment. They are defined in the GraphQL schema and have properties such as:

6.6.4 Question IDs and Answers

When creating or updating a consignment, the answers to the questions are provided in the form of an answers array. Each answer object contains the following properties:

The questionId in the answers array corresponds to the id of the question defined in the GraphQL schema. This establishes the relationship between the questions and their respective answers within a consignment.

6.6.5 Child Questions

Child questions are sub-questions that are conditionally displayed based on the answer provided to a parent question. They follow the same structure as regular questions and can have their own triggers, validators, and acceptable answers. Child questions are defined within the childQuestions array of a parent question.

6.6.6 Retrieving a list of Questions, Answers and Validators

{
  query {
    questions(envdAccountId: "880cafc7-3712-4bdf-59fb-08dc4de5d367") {
      items {
        id
        order
        text
        readOnly
        forms
        type
        triggers {
          questionId
          value
        }
        validators {
          type
          parameter
          errorMessage
        }
        acceptableAnswers {
          displayName
          value
        }
        childQuestions {
          id
          order
          text
          readOnly
          forms
          type
          triggers {
            questionId
            value
          }
          validators {
            type
            parameter
            errorMessage
          }
          acceptableAnswers {
            displayName
            value
          }
          childQuestions {
            id
            order
            text
            readOnly
            forms
            type
            triggers {
              questionId
              value
            }
            acceptableAnswers {
              displayName
              value
            }
            validators {
              type
              parameter
              errorMessage
            }
          }
        }
      }
    }
  }
}

Here’s an example of how to obtain a list of questions and answers from the GraphQL API using a query:

In this query:

You can use this query to retrieve the list of questions and their details from the GraphQL API. The response can be used to dynamically generate forms, validate answers, and handle the logic of displaying child questions based on the answers provided.





Here’s an example response ):

{
  "data": {
    "questions": {
      "items": [
        {
          "id": "1",
          "order": 1,
          "text": "Please provide a description of the livestock moving",
          "readOnly": false,
          "forms": [
            "LPAC1",
            "EUC1",
            "LPABC1",
            "LPASL1",
            "LPAG2",
            "NFASC0",
            "NFASDDC1",
            "NFASEUC1"
          ],
          "type": "REPEATABLE",
          "triggers": null,
          "validators": [
            {
              "type": "required",
              "parameter": "",
              "errorMessage": "Required field"
            }
          ],
          "acceptableAnswers": [],
          "childQuestions": [
            {
              "id": "2",
              "order": 2,
              "text": "Age (dentition)",
              "readOnly": false,
              "forms": ["NFASC0", "NFASDDC1", "NFASEUC1"],
              "type": "SINGLE_CHOICE",
              "triggers": null,
              "validators": [],
              "acceptableAnswers": [
                {
                  "displayName": "0-2",
                  "value": "2"
                },
                {
                  "displayName": "0-4",
                  "value": "4"
                }
                // ...
              ],
              "childQuestions": []
            }
            // ...
          ]
        }
        // ...
      ]
    }
  }
}

In this example response, we can see the structure of the questions and their associated details. Each question has an id, order, text, readOnly, forms, type, triggers, validators, acceptableAnswers, and childQuestions. The childQuestions field contains an array of nested child questions that follow the same structure.





6.7 API Validation Rules and Errors

This section provides information about the inner validation rules and errors that can be triggered from the eNVD API.

6.7.1 Validation Errors

The eNVD API performs various validations on the input data and returns appropriate error responses when the validation rules are violated. The following table lists the common validation scenarios and their corresponding error responses:

{
    "errors": [
        {
            "message": "The access token is invalid.",
            "path": [
                "createOrSaveConsignment"
            ],
            "extensions": {
                "data": {
                    "Code": "Unauthorized",
                    "Message": "The access token is invalid.",
                    "Description": null,
                    "OutcomeStatus": null
                }
            }
        }
    ]
}

Invalid or expired token (Error)


{
    "errors": [
        {
            "message": "Internal server error",
            "path": [
                "createOrSaveConsignment"
            ],
            "extensions": {
                "data": {
                    "Code": "",
                    "Message": "Internal server error",
                    "Description": null,
                    "OutcomeStatus": "ERROR"
                }
            }
        }
    ]
}

Trying to update a non-existing consignment or if the user doesn’t have permission to the consignment (Error)




{
    "errors": [
        {
            "message": "GraphQL.ExecutionError: Invalid type. Expected String but got Null.",
            "path": [
                "createOrSaveConsignment",
                "species"
            ],
            "extensions": {
                "data": {
                    "Code": "species",
                    "Message": "Invalid type. Expected String but got Null.",
                    "Description": null,
                    "OutcomeStatus": "Error"
                }
            }
        },
        {
            "message": "GraphQL.ExecutionError: Array item count 0 is less than minimum count of 1.",
            "path": [
                "createOrSaveConsignment",
                "programs"
            ],
            "extensions": {
                "data": {
                    "Code": "programs",
                    "Message": "Array item count 0 is less than minimum count of 1.",
                    "Description": null,
                    "OutcomeStatus": "Error"
                }
            }
        }
    ]
}

Empty forms in the payload (Error)




{
    "errors": [
        {
            "message": "Variable '$input.forms[0]' is invalid. Unable to convert 'Form1' to 'EFormType'",
            "locations": [
                {
                    "line": 2,
                    "column": 3
                }
            ],
            "extensions": {
                "code": "INVALID_VALUE",
                "codes": [
                    "INVALID_VALUE",
                    "INVALID_OPERATION"
                ],
                "number": "5.8"
            }
        }
    ]
}

Invalid form provided (Error)






{
    "errors": [
        {
            "message": "Bad request",
            "path": [
                "createOrSaveConsignment"
            ],
            "extensions": {
                "data": {
                    "Code": "",
                    "Message": "Bad request",
                    "Description": "Programs 'Castle.Proxies.FormModelProxy,Castle.Proxies.FormModelProxy,Castle.Proxies.FormModelProxy,Castle.Proxies.FormModelProxy' linked to more than one species 'Cattle,Goat'",
                    "OutcomeStatus": "ERROR"
                }
            }
        }
    ]
}

Mix different types of forms (Error)





{
    "errors": [
        {
            "message": "'PIC1' is not a valid value for PIC.",
            "path": [
                "createOrSaveConsignment",
                "<<Field Name>>"
            ],
            "extensions": {
                "data": {
                    "Code": "<<Field Name>>",
                    "Message": "'PIC1' is not a valid value for PIC.",
                    "Description": null,
                    "OutcomeStatus": "Error"
                }
            }
        }
    ]
}

Invalid PIC in any of the PIC-related fields (Error)





{
    "errors": [
        {
            "message": "'MIHA0548' is not associated with user.",
            "path": [
                "createOrSaveConsignment",
                "consignorPic"
            ],
            "extensions": {
                "data": {
                    "Code": "consignorPic",
                    "Message": "'MIHA0548' is not associated with user.",
                    "Description": null,
                    "OutcomeStatus": "Error"
                }
            }
        }
    ]
}

Source/Origin PIC is different from the selected LPA account (Error)





{
    "errors": [
        {
            "message": "GraphQL.ExecutionError: Required",
            "path": [
                "createOrSaveConsignment",
                "otherHealthInformation",
                "negativeHerdTestDetails",
                "lastTestDate"
            ],
            "extensions": {
                "data": {
                    "Code": "otherHealthInformation.negativeHerdTestDetails.lastTestDate",
                    "Message": "Required",
                    "Description": null,
                    "OutcomeStatus": "Error"
                }
            }
        }
    ]
}

Required answers not provided in the payload (Warning)





{
    "errors": [
        {
            "message": "GraphQL.ExecutionError: Question 113: 2024-09-06 is not valid.",
            "path": [
                "createOrSaveConsignment"
            ],
            "extensions": {
                "data": {
                    "Code": "otherHealthInformation.negativeHerdTestDetails.lastTestDate",
                    "Message": "Question 113: 2024-09-06 is not valid.",
                    "Description": "",
                    "OutcomeStatus": "Error"
                }
            }
        }
    ]
}

Invalid data provided in the answer (Warning)





6.7.2 Field-level Validation and Dependencies

To retrieve the field-level validation rules and dependencies, you can run the GraphQL query provided in section 6.6.6

6.7.3 Validators

"validators": [
  {
    "type": "minYear",
    "parameter": "1900",
    "errorMessage": "Minimum year of 1900"
  },
  {
    "type": "maxYear",
    "parameter": "now",
    "errorMessage": "Date cannot be in the future"
  }
]

The validators field contains the validation rules for a question, such as the maximum supported value, minimum value, length of a string, etc. The errorMessage field provides the corresponding error message if the validation rules are not met. Example:







6.7.4 Acceptable answers

"acceptableAnswers": [
  {
    "displayName": "Feed standard not met",
    "value": "0"
  },
  {
    "displayName": "GFF - 35 days or more",
    "value": "35"
  },
  {
    "displayName": "GFYG - 60 days or more (heifers only)",
    "value": "60"
  },
  {
    "displayName": "GFYG - 70 days or more",
    "value": "70"
  },
  {
    "displayName": "GF - 100 days or more",
    "value": "100"
  }
]

The acceptableAnswers field contains the acceptable answers for “Single Choice” and “Multiple Choice” questions. Example:





{
  "message": "Answer: abc is not valid. Acceptable answers are: 0,35,60,70,100",
  "path": ["createOrSaveConsignment"],
  "extensions": {
    "data": {
      "Code": "declaration.declarePartIV.fedNotLessThan[]",
      "Message": "Answer: abc is not valid. Acceptable answers are: 0,35,60,70,100",
      "Description": "",
      "OutcomeStatus": "Error"
    }
  }
}

Violating these rules will result in the following error:


6.7.4 Conditional Validation

{
  "id": "57",
  "text": "Give details",
  "acceptableAnswers": [],
  "type": "STRING",
  "triggers": [
    {
      "questionId": "56",
      "value": "Yes"
    }
  ]
}

Some validations are triggered by the value of another field. These conditional validations can be found in the triggers field. In the example below, the validation rules for question “57” will be applied if the answer to question “56” is “Yes”.


6.7.5 Other Validation

{
  "input": {
    "forms": ["LPAC1", "NFASDDC1", "MSAC1", "HSC2"],
    "origin": {
      "address": {
        "line1": "North Sydney",
        "postcode": "2060",
        "state": "NSW",
        "town": "North Sydney"
      },
      "name": "ISC test account",
      "pic": "QDZZ3333"
    },
    "destination": {
      "address": {
        "line1": "",
        "state": "NSW",
        "town": "EAST KURRAJONG"
      },
      "name": "MD & VM JONES",
      "pic": "NI462324"
    },
    "owner": {
      "address": {
        "line1": "North Sydney",
        "postcode": "2060",
        "state": "NSW",
        "town": "North Sydney"
      },
      "name": "ISC test account",
      "pic": "QDZZ3333"
    },
    "consignee": {
      "address": {
        "line1": "",
        "state": "NSW",
        "town": "EAST KURRAJONG"
      },
      "name": "MD & VM JONES",
      "pic": "NK992233"
    },
    "declaration": {
      "accept": false,
      "address": {
        "line1": "1/40 MOUNT ST",
        "postcode": "2060",
        "state": "NSW",
        "town": "NORTH SYDNEY"
      },
      "certificateNumber": null,
      "date": "2023-12-15T00:00:00",
      "email": null,
      "fullName": "ISC Test Account",
      "phone": null,
      "signature": null
    },
    "movementDate": "2022-12-19",
    "movementTime": null,
    "status": "DRAFT",
    "answers": []
  }
}

In addition to the field-level validation for questions, the eNVD API also performs validation on other consignment-level fields that are not exposed through the questions query. These fields are part of the input object when creating or updating a consignment.

Here’s a sample request payload:

The following table describes the validation rules for these consignment-level fields:

FieldMandatoryTypeValidation
formsYesString ArrayAccepts only the following values: EUC1, HSC2, HSG0, HSSL1, LPABC1, LPAC1, LPAG2, LPASL1, MSAC1, NFASC0, NFASDDC1, NFASEUC1
origin.address.line1, destination.address.line1, owner.address.line1, consignee.address.line1, declaration.address.line1NoStringMax Length: 300 characters
origin.address.postcode, destination.address.postcode, owner.address.postcode, consignee.address.postcode, declaration.address.postcodeNoNumeric StringLength: 4, Max: 9999, Min: 1000
origin.address.state, destination.address.state, owner.address.state, consignee.address.state, declaration.address.stateNoStringAccepts only the following values: “ACT”, “NSW”, “NT”, “QLD”, “SA”, “TAS”, “VIC”, “WA”
origin.address.town, destination.address.town, owner.address.town, consignee.address.town, declaration.address.townNoStringMax Length: 100 characters
origin.name, destination.name, owner.name, consignee.nameNoStringMax Length: 300 characters
origin.pic, destination.picYesStringAccepts only valid PIC format
owner.pic, consignee.picNoStringAccepts only valid PIC format
declaration.acceptNoBoolean-
declaration.certificateNumberNoStringMax Length: 7 characters
declaration.dateNoDateTimeValid Date format
declaration.emailNoStringValid email address
declaration.fullNameNoStringMax Length: 300 characters
declaration.phoneNoStringA valid phone number (e.g., 0299999999 or +61400000000)
declaration.signatureNoStringBase64 version of the signature image
movementDateNoDateValid date in ISO-8601 format (yyyy-MM-dd)
movementTimeNo24 hr time formatExample: “17:40”
statusNoStringAccepts only the following values: DELETED, DRAFT, SUBMITTED, LOCKED

Ensure that the input data for these consignment-level fields conforms to the specified validation rules to avoid validation errors when creating or updating a consignment using the eNVD API.

By understanding the validation rules, accepted answers, and conditional validations, you can ensure that the data sent to the eNVD API meets the required criteria and handle any validation errors appropriately in your application.

7. User Roles and Responsibilities

The eNVD API introduces a new concept of user roles, which determine the level of access and permissions a user has within the system. This section explains the different user roles and their associated privileges.

7.1 User Roles

The eNVD API defines the following user roles:

7.2 Role-based Access and Permissions

Each user role has specific access rights and permissions within the eNVD system:

Producer (LPA accounts):

Authentication:

Features and Permissions:

Receiver (LPA or NLIS PIC-based accounts):

Authentication:

Features and Permissions:

Facilitator (NLIS saleyard or agent PIC-based accounts):

Authentication:

Features and Permissions:

Transporter (email-based accounts):

Authentication:

Features and Permissions:

Buyer (email-based accounts):

Authentication:

Features and Permissions:

Authenticated Viewer (email-based accounts):

Authentication:

Features and Permissions:

7.3 authorisation Errors and Handling

The eNVD API enforces role-based access control to ensure that users can only perform actions they are authorised to do. If a user tries to access a resource or perform an action they don’t have permission for, the API will respond with a 403 Unauthorized error. Example scenarios that would result in a 403 Unauthorized error:

When handling API responses, check for the presence of a 403 Unauthorized error and handle it appropriately in your application, such as displaying an error message to the user or redirecting them to a different page.

8. API Reference

This section provides a reference of the available queries and mutations in the eNVD API, along with brief descriptions and links to more detailed documentation.

8.1 Queries

consignments: Retrieves a list of consignments based on various filter criteria.

consignment: Retrieves a specific consignment by its ID and account ID.

templates: Retrieves a list of templates based on various filter criteria.

template: Retrieves a specific template by its ID and account ID.

userDetails: Retrieves details about the authenticated user, including their account information.

consignmentUserMapping: Retrieves consignment user mappings based on account ID, consignment number, and role.

edecs: Retrieves a list eDECs created by the user via the eDEC system

questions: Retrieves a list of all questions

configurations: Retrieves a list of all dynamic configurations

comments: Retrieves a list of comments for a consignment

For a complete list of available queries and their parameters, refer to section 9 - code examples

8.2 Mutations

createOrSaveConsignment: Creates or updates a consignment.

deleteConsignment: Deletes a consignment.

createOrSaveTemplate: Creates or updates a template.

deleteTemplate: Deletes a template.

copyConsignment: Creates a copy of a consignment previously created by the producer.

createOrSaveUser: Creates or updates a user.

createComment: Creates a comment for a consignment.

For a complete list of available mutations and their parameters, refer to section 9 - code examples

9. Code Examples

This section provides code examples for common tasks in the eNVD API, such as retrieving consignments, creating a consignment, and viewing user details.

9.1 Retrieving User Details

9.2 Retrieving Consignments

9.3 Creating a Consignment

9.4 Updating a Consignment

9.5 Submitting a Consignment

9.6 Deleting a Consignment

9.7 Add a Transporter to a Consignment

9.8 Add a Viewer to a Consignment

9.9 Retrieving a viewer

9.10 Add a Comment to a Consignment

9.11 Retrieving Comments

9.12 Creating a Template

9.13 Retrieving Templates

9.14 Creating from a Template

9.15 Copying a Consignment

10. Best Practices and Tips

This section provides best practices and tips for working with the eNVD API efficiently and effectively.

10.1 Performance Optimization

Use pagination and filtering options provided by the API to retrieve only the necessary data. Avoid fetching large datasets unnecessarily. Implement caching mechanisms in your application to store and reuse frequently accessed data, reducing the number of API requests and improving performance.

10.2 Pagination and Filtering

10.3 Error Handling and Troubleshooting

10.4 Security Considerations

11. Updates and New Features

11.1 Harvested Rangeland Goat (HRG) Form

Effective Date: October 1, 2024

A new form type, the Harvested Rangeland Goat (HRG) form, will be added to the eNVD system. This section outlines the key details for integrators to incorporate this new form into their applications.

What are Harvested Rangeland Goats?

Harvested Rangeland Goats (HRGs) are feral or semi-feral goats that are not traditionally farmed but are instead harvested from wild or semi-wild populations with minimal human intervention. HRGs play a significant role in Australia’s goat meat export industry. They are subject to specific National Livestock Identification System (NLIS) regulations, which allow them to be moved without individual identification devices under certain conditions. This exemption is due to the challenges of tagging animals in extensive rangeland environments while maintaining traceability and biosecurity standards. The HRG eNVD specifically addresses whether goats in a consignment meet the NLIS Standards’ definition of HRGs and are eligible for device-free movement.

Form Code

When creating an HRG form, use the following From ID:

LPAHRG0


Accreditation Requirement

The HRG form is accreditation-driven. Only users with the appropriate HRG accreditation flag on their LPA profile will be able to create and view this form. Integrators should check for the hRG field in the user details query response to determine if a user has HRG accreditation:

query userDetailsQuery {
  userDetails {
    firstName
    lastName
    email
    accounts {
      envdAccountId
             }
        accreditations {
          lPA
          eU
          mSA
          eUGFHQB
          nFAS
          hRG
        }
      }
      roles
    }
  }
}

If hRG is true, the user has HRG accreditation.


New Question

The HRG form introduces one new question:

Important Note: If the answer is “No”, there’s a critical warning message: “IF NO - The Goats are not eligible to be moved device free on this NVD/Waybill and you are not adhering to your LPA Accreditation. You risk removal from the LPA Program and access to abattoirs and Registered Goat Depots that process Harvested Rangeland Goats.”

Note that although Question ID 185 supports both Yes and No values, only Yes will result in a consignment being created.

Sample Code for Creating an HRG Form

Here’s an example of how to create an HRG form using the eNVD API:

mutation createOrSaveConsignmentMutation(
  $input: CreateOrSaveConsignmentInput!
  $envdAccountId: String!
) {
  createOrSaveConsignment(input: $input, envdAccountId: $envdAccountId) {
    data {
      id
      number
      status
      // Include other fields as needed
    }
  }
}










Variables:

{
  "input": {
    "forms": ["LPAHRG0"],
    "origin": {
      // Origin details...
    },
    "destination": {
      // Destination details...
    },
    "owner": {
      // Owner details...
    },
    "consignee": {
      // Consignee details...
    },
    "movementDate": "2024-10-15",
    "answers": [
      {
        "questionId": "185",
        "index": null,
        "value": "Yes"
      }
      // Include other required answers...
    ],
    "declaration": {
      // Declaration details...
    }
  },
  "envdAccountId": "your_envd_account_id_here"
}



















Important Considerations

When implementing Question 185:

For any questions or issues related to the new HRG form, please contact our support team.

NLIS

About NLIS

The National Livestock Identification System (NLIS) is Australia’s system for the identification and traceability of cattle, sheep and goats. NLIS reflects Australia’s commitment to biosecurity and food safety and provides a competitive advantage in a global market.

As animals are bought, sold and moved along the supply chain, they must be tagged with an NLIS accredited tag or device from their property (PIC) of birth. In most cases this tag will remain with the animal for their entire life and it is illegal to remove this tag.

If tags are lost or become defective then a new tag can be applied, however if the animal is no longer at its place of birth then a ‘post breeder’ tag must be used. This indicates that the animal no longer has ‘lifetime’ traceability.

All animals leaving a PIC must be identified with an NLIS accredited device before moving, unless a permit is obtained from the state or territory. Each movement they make to a location with a different PIC must be recorded centrally on the NLIS database by people with NLIS accounts. NLIS accounts are free to open and operate.

Using this information, the NLIS is able to provide a life history of an animal’s movements and discern if contact with other livestock occurred. The NLIS is required to facilitate the traceability of animals in accordance with the National Traceability and Performance Standards.

About the NLIS API

The purpose of the NLIS SOAP API is to define how third-party systems can communicate with the NLIS Database:

For the majority of users, the NLIS Database website (www.nlis.mla.com.au) will provide the primary mechanism for interacting with the database: for submitting updates to data, and for requesting data from NLIS. The NLIS SOAP interface specifications details those enquiry/update processes that can be initiated/integrated from outside that website. It provides all the information required for third-party software vendors/developers to integrate their systems with the NLIS Database.

For example:

All the processes detailed in the NLIS SOAP interface specifications are provided to approved users of the NLIS Database, via direct user interaction. This document simply details alternative, programmable methods for obtaining the same results.

NLIS API Documentation

For further information about the NLIS API contact the ISC Integration Analyst at:

developersupport@integritysystems.com.au

ISC environments

ProductUATProduction
Authenticationhttps://auth-uat.integritysystems.com.auhttps://auth.integritysystems.com.au
eNVD APIhttps://api.uat.integritysystems.com.au/graphqlhttps://api.integritysystems.com.au/graphql
NLIS SOAP APIwww.uat.nlis.com.auwww.nlis.com.au
NLIS PIC Registerhttps://service.uat.nlis.com.au/api/v2/PICRegisterhttps://service.nlis.com.au/api/v2/PICRegister

Status Codes

Status CodeMeaning
200Ok – The default success code for requests that return a valid response in the response body, even if the response does not contain any rows or pagination. When POST-ing a new record a 200 indicates that while the request was correctly processed the record may not have been accepted, the body of the Response will indicate the reason for this error.
201Created – Success code for a POST request for a collection, indicating the record was successfully created. Note: While a 201 indicates the record was recorded, there may be Informational or Warning messages (in the Response body) that may require some corrective action to occur.
304Not Modified – The request content has not changed since a specified date and time (provided in an If-Modified-Since parameter in the request).
400Bad Request – The data passed in the request could not be understood, or translated to into an internal format. Typically, the passed message fails simple type validation rules (e.g. passing a string when a number is expected), or document structure rules (e.g. is a malformed XML or JSON document).
401Unauthorized – This error is returned when the OAuth token used has expired or is invalid; the user attempts to perform an action for which they are not authorized; or if a login attempt fails due to bad credentials.
403Forbidden – Authentication was provided, but the authenticated user is not permitted to perform the requested operation.
404Not Found – The requested resource could not be found. This error is generally returned when an entity with a specific ID is not found in our database. Check the URI for correct format, and that any IDs passed in the URI are valid.
500Internal Server Error – Any internal server error that was not explicitly trapped by the application. An error has occurred within the platform, or the system is not compatible with the NLIS API, so the request could not be completed. Contact the NLIS Development Team at technicalsupport@IntegritySystems.com.au for assistance with this error.
503Service Unavailable – We’re temporarially offline for maintanance. Please try again later.