GraphQL Documentation

Fast-Weigh GraphQL

To add the API module to your Fast-Weigh subscription, contact us at 865-219-2980 or support@tacinsight.com.

Fast-Weigh is a modern cloud-based truck ticketing, ordering, and dispatching platform.

The Fast-Weigh REST & GraphQL APIs allow system integrators to interface with the Fast-Weigh data model to extend functionality and/or extract data for third-party use.

Authentication

The Fast-Weigh REST & GraphQL API services use token-based authentication with a custom x-api-key HTTP header record. The token should be included with every call.

Basic Authentication has been deprecated.

We have transitioned from using Basic Authentication with username/password credentials to token-based authentication. Existing integrations will continue to work, but please note that Basic Auth has been deprecated and will be removed in the future.

Graph QL

Your endpoint:

You can find your endpoint listed on the API Info page under the settings gear of the Fast-Weigh Web Portal.

Don't see API Info on your web portal?

  1. You may not be an admin of your Fast-Weigh account. Check with a known admin to see if they can set up this key.

  2. Your company's account may not have this enabled. If this is the case you will need to contact your sales or onboarding rep to get it enabled.

The endpoint should look something like this: https://server-name.fast-weigh.dev/v1/graphql

API schema explorer:

Your credentials will allow you to use the Insomnia tool to build queries. There, you can dive into the data model docs as well as test queries with the live editor.

Info for devs

GraphQL queries are handled via standard HTTP.

All GraphQL queries are POST requests

The first thing to understand is the GraphQL query itself is sent along in the body of the request. Since HTTP GET calls cannot include a request body, every call sent to the GraphQL server must be a POST request.

The request body is JSON-encoded

The request body itself should be JSON encoded. So the query you write will be transformed into something like this:

{
    "query": "query get_customers {Customer {CustomerID CustomerName}}"
}

Use libraries

Unless you are programming in a very obscure language, there are probably client libraries that can abstract away a lot of this for you.

These clients typically let you write your query in standard GraphQL syntax, and they handle the rest.

Also, thanks to GraphQL's build-in introspection, many libraries can generate a fully-typed API client for you to use!

Using Parameters

Parameters allow you to pass data into your GraphQL statement.

Common parameter types

  • Int

  • String

  • Boolean

  • date (yes, this one is lowercase)

Date formatting

It's important to note that dates must be formatted as YYYY-MM-DD when being passed as parameters.

Parameter arrays

Parameter arrays can be used for filters like the "_in" filter and are defined with []'s.

  • [String!]

  • [Int!]

GraphQL Crash Course

If you are not familiar with GraphQL, no worries. It's easy to learn. If you have experience working with SQL you'll feel right at home. The syntax also looks similar to a JSON document if you are used to working with responses from REST endpoints. In fact, the structure of the query is simply the format of the JSON response you'd like to receive back.

Another nice feature of GraphQL is schema introspection. That's a fancy way of saying that the fields are self-documenting. This allows us to build things like the Insomnia GraphQL Schema that provides autocompletion and field documentation that is always up to date with the latest API changes. (🍻cheers to no documentation lag!)

GraphQL basics

With GraphQL, you're still issuing a request to an HTTP endpoint just like you would for a REST API. The big difference is there is a single endpoint that services all requests.

For Fast-Weigh, the endpoint looks like this:

https://<your-servername-here>.fast-weigh.dev/v1/graphql

Calling the endpoint directly

If you calling the GraphQL endpoint directly, all requests must be POST requests with a JSON encoded query as the body of the request (Content-Type: application/json)

Writing a simple query

Here's a simple query that requests a few fields from the Customer GraphQL type:

query customers {
  Customer {
    CustomerID
    CustomerName
    ContactName
    ContactPhone
  }
}

Let's break that syntax into its parts:

<ActionType> <QueryName> {
  <Type> {
    <TypeField1>
    <TypeField2>
  }
}
  • ActionType: GraphQL endpoints support the following "ActionTypes". Note that Fast-Weigh only supports the "query" type at this time.

    • query: ✅ Similar to a SQL SELECT statement

    • subscription: ❌ A WebSocket based live data stream

    • mutation: ❌ Similar to a SQL UPDATE or INSERT statement

  • QueryName: This is the identifier for the query. You can give it any name you'd like. In the GET CUSTOMERS example the QueryName could have been "getAllCustomers", "get-customers-list", or anything else you could dream up. I went with "customers" for brevity.

  • Type: If you are familiar with SQL, you can think of this as the corresponding SQL table.

  • TypeField: Again, if you are familiar with SQL, you can think of this as the columns within the corresponding SQL table.

The response back from this query will be a JSON response matching the format requested.

If a requested field has no value, it will be omitted from the response. This compresses the payload size and increases performance.

Finding the available fields

GraphQL introspection powers autocomplete within our recommended tooling.

This tool also allows you to browse the schema, as explained here.

Joining via relationships

Relationships in GraphQL can be of 2 types:

  • Object: 1 to 1

  • Array: 1 to many

Object relationships

Object relationships will embed a single subtype in the response.

For example, the Customer type has an Object Relationship with a TaxCode.

So a query like this:

query customers_with_taxcode {
  Customer {
    CustomerID
    CustomerName
    TaxCode {
      Code
    }
  }
}

Will result in a response that looks like this:

{
  "data": {
    "Customer": [
      {
        "CustomerID": "",
        "CustomerName": "",
        "TaxCode": {
          "Code": ""
        }
      }
    ]
  }
}

Array relationships

Array relationships will nest an list of objects in the response.

As an example, a Customer may have many Orders.

So the Customer type has an array relationship with orders. And querying for the Orders would look some like this:

query customers_and_orders {
  Customer {
    CustomerID
    CustomerName
    Orders {
      OrderNumber
      Description
    }
  }
}

And result in:

{
  "data": {
    "Customer": [
      {
        "CustomerID": "",
        "CustomerName": "",
        "Orders": [
          {
            "OrderNumber": 1,
            "Description": "",
          },
          {
            "OrderNumber": 2,
            "Description": "",
          }
        ]
      }
    ]
  }
}

Filtering data

Until now, the queries we've written would have returned all results from the Customer table.

To filter the results, GraphQL supplies us with a few syntax options.

Limit & offset

This one is pretty easy. Within the Type your are querying, supply the limit argument with an integer specifying the number of results you'd like returned.

query customers_and_orders {
  Customer(limit: 10) {
    CustomerID
    CustomerName
    Orders {
      OrderNumber
      Description
      PONumber
    }
  }
}

Note that this only limits the Customer type to 10 results. So the nested Orders array may contain many more. You can limit on the nested Orders type in the same way.

query customers_and_orders {
  Customer(limit: 10) {
    CustomerID
    CustomerName
    Orders(limit: 10) {
      OrderNumber
      Description
      PONumber
    }
  }
}

If you want to limit each response but still cycle through to retrieve all of the filtered data, you can use an offset loop to go through the next set of 10 records.

In practice, you'd want to increment this number on each call by whatever your limit is. So the first call would be offset of 0, second call an offset of 10, then 20, 30, and so on. Once you get a payload with fewer records than your limit, you'll know there are no more records to retrieve and can stop issuing queries.

query customers_and_orders {
  Customer(limit: 10, offset: 10) {
    CustomerID
    CustomerName
    Orders {
      OrderNumber
      Description
      PONumber
    }
  }
}

Order by

Building on the query above, you can order the results by adding an "order_by" field to your arguments.

query customers_and_orders {
  Customer(
    limit: 10,
    order_by: {CustomerID: asc}
  ) {
    CustomerID
    CustomerName
    Orders {
      OrderNumber
      Description
      PONumber
    }
  }
}

Notice you must pass an object to the "order_by" argument with the field you'd like to order, as well as the sort direction.

The following sort directions are permitted:

  • asc

  • asc_nulls_first

  • asc_nulls_last

  • desc

  • desc_nulls_first

  • desc_nulls_last

Where clauses

Let's modify the query once again and supply a "where" argument.

The "where" argument can apply a number of different filters to a given field.

  • _eq: equal to

  • _neq: not equal to

  • _gt: greater than

  • _gte: great than or equal to

  • _lt: less than

  • _lte: less than or equal to

  • _in: exists in an array of values

  • _nin: does not exist in an array of values

  • _like: matches some part of the given string

  • _nlike: does not match some part of the - given string

  • _is_null: ...is null 😆

Here's an example of querying for just Customers in the State of Tennessee:

query customers_with_taxcode {
  Customer(
    where: {State: {_eq: "TN"}}
  ) {
    CustomerID
    CustomerName
    Orders {
      OrderNumber
      Description
      PONumber
    }
  }
}

And here's an example of passing an array of States to the filter using the "_in" clause:

query customers_with_taxcode {
  Customer(
    where: {State: {_in: ["TN","KY","GA"]}}
  ) {
    CustomerID
    CustomerName
    Orders {
      OrderNumber
      Description
      PONumber
    }
  }
}

Using multiple filters with _and / _or

You can use the _and / _or operators along with the other "where" filters to create more complex queries.

  • _and: Data must satisfy all of the included filters

  • _or: Data must satisfy at least one of the included filters

These operators open up an array using "[]" brackets that contain all the filters you wish to apply.

_and:

This query will return a Customer only if it is within the provided States, and also has a Country set to "US".

query customers_with_taxcode {
  Customer(
    where: {_and: [
      {State: {_in: ["TN","KY","GA"]}},
      {Country: {_eq: {_eq: "US"}}}
    ]}
  ) {
    CustomerID
    CustomerName
    TaxCode {
      Code
    }
  }
}

_or:

This query will return a Customer if it's within the given States, OR if its CustomerID field contains "100".

query customers_with_taxcode {
  Customer(
    where: {_or: [
      {State: {_in: ["TN","KY","GA"]}},
      {CustomerID: {_like: "100"}}
    ]}
  ) {
    CustomerID
    CustomerName
    TaxCode {
      Code
    }
  }
}

Filtering on nested Types

Remember that filters can also be used on nested Types as well. But there is a difference for "where" filters in Object vs Array relations.

Object relationship "where" filter

For Object relationships, you'll apply the filter on the parent. For example, a Customer can only have a single TaxCode. So to filter the Customers TaxCode you could write:

query customers_with_taxcode {
  Customer(
    where: {TaxCode: {Code: {_eq: "EXEMPT"}}}
  ) {
    CustomerID
    CustomerName
    TaxCode {
      Code
    }
  }
}

Array relationship "where" filter

For Array relationships, you'll typically apply the filter on the nested array itself. For example, a Customer can have many Orders. So to filter the Orders returned you would write:

query customers_and_orders {
  Customer(
    where: {State: {_in: ["TN","KY","GA"]}}
  ) {
    CustomerID
    CustomerName
    Orders(
      where: {Status: {_eq: "A"}}
    ) {
      OrderNumber
      Description
      PONumber
    }
  }
}

Compound queries

Completely separate requests can also be merged within a single query. This is useful if you need to bring in data from multiple tables and only want to make a single HTTP call to do so.

Typically compound queries would only be used to stitch together the responses of smaller queries. You would not want to combine multiple large payload queries in the same request/response as this can be quite taxing to fetch and parse due to query complexity and payload size.

Here's an example request for some base resources within Fast-Weigh. These lists are generally quite short and are good candidates for compound queries if applicable to your use case.

query sample_compound_query {
  Region {
    RegionName
    RegionDescription
  }
  Salesperson {
    Name
    Email
  }
  TaxCode {
    Code
    MaterialPercent
    FreightPercent
    SurchargePercent
  }
  Product {
    ProductID
    ProductDescription
  }
}

Results in:

{
  "data": {
    "Region": [
      {
        "RegionName": "",
        "RegionDescription": ""
      },
    ],
    "Salesperson": [
      {
        "Name": "",
        "Email": ""
      },
    ],
    "TaxCode": [
      {
        "Code": "",
        "MaterialPercent": 0.0000000,
        "FreightPercent": 0.0000000,
        "SurchargePercent": 0.0000000
      },
    ],
    "Product": [
      {
        "ProductID": "",
        "ProductDescription": ""
      },
    ]
  }
}

Putting queries into practice

Once you've got the query basics down, it's time to start experimenting and using them for your own use case in Insomnia or start quering via HTTP and code in your programming language of choice.

GraphQL and Reporting Quickstart

Note: If this link is not working, please email support@tacinsight.com

GraphQL Query Examples

query GetTrucks($fromDate: smalldatetime!) {
  Truck(where: { LastLoadDate: { _gte: $fromDate } }) {
    TruckID
    LastLoadDate
    TareWeight
    Hauler {
      HaulerID
      HaulerName
    }
  }
}

Query Variables

{
    "fromDate": "2022-02-01"
}

query GetCustomers($state: String) {
  Customer(where: { State: { _eq: $state } }) {
    CustomerID
    CustomerName
    Address1
    Address2
    City
    State
    Zip
    TaxCode {
      Code
    }
  }
}

Query Variables

{
    "state": "TN"
}

query GetOrders {
  Order(where: {Status: {_eq: "A"}}) {
    OrderNumber
    Description
    PONumber
    DefaultJob
    Customer {
      CustomerID
      CustomerName
    }
    OrderProducts {
      Product {
        ProductID
        ProductDescription
      }
      UnitPrice
      FreightRate
    }
  }
}

query GetTickets($FromDate: date!, $ToDate: date!) {
  LoadTicket(
    where: {
      _and: [
        { TicketDate: { _gte: $FromDate } }
        { TicketDate: { _lte: $ToDate } }
      ]
    }
  ) {
    TicketKey
    TicketNumber
    Void
    NetWeight
    TicketDate
    OrderProduct {
      Product {
        ProductKey
        ProductID
        ProductDescription
        UnitOfMeasure
      }
    }
    Order {
      OrderKey
      OrderNumber
      Description
      Customer {
        CustomerKey
        CustomerID
        CustomerName
      }
    }
    Truck {
      TruckKey
      TruckID
      Hauler {
        HaulerKey
        HaulerID
        HaulerName
      }
    }
    RatesAndAmounts {
      MaterialAmountCalculated
      FreightAmountCalculated
      SurchargeAmountCalculated
    }
  }
}

Query Variables

{
    "FromDate": "2022-02-13",
    "ToDate": "2022-02-23"
}

GraphQL Schema

GraphQL provides a live schema via introspection of the API endpoint. That's a nerdy way of saying the available fields are always up to date and you don't have to worry about the documentation being stale!

How to View the Schema

Head to the Tooling page and follow the instructions listed there to view the schema docs via the Insomnia Client.

Check out the Graph behind the GraphQL here: https://graph.fast-weigh.dev/

Making Sense of the Schema

GraphQL queries are based on "Types". These types are similar to a SQL Table.

A "Customer" database table, for example, becomes a "Customer" type in GraphQL.

Root type:

First, you'll need to drill into a "root" type, two of which are available:

  • query_root

  • subscription_root

In the vast majority of cases, query_root is what you're after. It's equivalent to a SELECT query in SQL.

The subscription_root is useful for programmers wanting a live websocket connection to the data.

If you're following along, click into the query_root to continue.

Exploring a GraphQL type:

Inside the query_root you'll see a list of available Types to explore.

Let's click into the Customer type.

Here, you'll see a link to view the fields available on the Customer type at the top.

You'll also see a list of arguments that can be passed into the type to filter or order the results returned.

For example, the limit argument tells you that you can pass an integer to limit the number of results.

query GetOneHundredCustomers {
  Customer(limit: 100) {
    CustomerID
  }
}

Arguments/filters are covered further in our GraphQL Crash Course.

Clicking inside the actual Customer type at the top reveals the fields available to you within that type.

Object relationships:

Object relationships on a type are 1:1 relationships with another type.

On the Customer type, if you scroll to the bottom, you'll see the TaxCode field. This is listed as an object type, meaning that if you query for the Customer's TaxCode the result will be a single TaxCode object.

Array relationships:

Array relationships on a type are 1:N relationships with another type.

On the Customer type, you can find the Orders field. This is listed as an array type, meaning that querying for Orders will return a nested array of Orders for the Customer(s) you are filtering for.

Last updated

Logo