GraphQL Extensions

GraphQL schema for data model extensions.
Warning

This feature is currently in preview. Although the implementation is complete and the schema extensions are available for everyone, the access to data model extensions is restricted to selected customers. If you are not one of these customers, you cannot create data model extensions. You can still use all the API extensions available in the schema for generically querying the model, but only for the code data model.

The GraphQL schema is dynamically built from the core data model. It exposes tables, columns, relations, processings, reports the way they are defined in the core model.

BNXT supports extending the model with new tables, columns, relations, and others. These data model extensions (DMEs for short) are accessible through GraphQL just like the core model. However, these extensions are not available the same way the core model is. GraphQL features a single schema, and that cannot expose all customer-specific extensions in a strongly-type named. For this reason, generic extensions are available everywhere DMEs are possible.

Tip

Although these generic extensions to the schema are designed for DMEs, it is possible to also query the core model using them. However, we advice that you only use them for DMEs.

Getting started with extensions

Extensions are referenced using their name identifiers, and not model numbers:

  • columns and tables by their name
  • relations by their name and where necessary to avoid ambiguity, also by their source and target table name

A few examples are provided here to get you started.

query read_order($cid:Int!)
{
  useCompany(no:$cid)
  {   
    order(first:5)
    {
      items
      {
        orderNo
        orderDate        
       
        extensions
        {
          customerNo : integerValue
          createdAt : dateValue(name: "createdDate")
        }
      }
    }
  }
}

The extensions field is available on all tables, and it exposes all extension columns defined for that table. You can query the extension columns by their name using the appropriate typed field. There are two ways to query a field:

  • using an alias, which is interpreted as the name of the extension column, such as in customerNo : integerValue
  • using the name argument to specify the name of the extension column, such as in createdAt : dateValue(name: "createdDate")

When both an alias and the name argument are used, the name argument takes precedence and the alias is not considered for identifying the company.

The possible field names for extension columns are:

  • integerValue
  • decimalValue
  • stringValue
  • booleanValue
  • dateValue
  • timeValue
  • timestampValue

Each column has a domain with a specific data type. Data types can be integer, decimal, boolean, string, date, timestamp. If the requested data type (such as integer for integerValue) does not match the domain data type of the extension column, the value null is returned.

The following example utilizes a relation extension to query related data from an extension table:

query read_order($cid:Int!)
{
  useCompany(no:$cid)
  {
    order(first:5)
    {
      items
      {
        orderNo
        orderDate
       
        extensions
        {
          customerNo : integerValue
          createdAt : dateValue(name: "createdDate")
        }
        
        joinup_Associate_via_Customer
        {
          name
          
          extensions
          {
            joinup(relation: "Country")
            {
              name : stringValue
            }
          }
        }
      }
    }
  }
}

The last example here shows how to query a table, use filters and sorting, and also do joins using the generic extensions schema:

query read_table($cid:Int!)
{
  useCompany(no:$cid)
  {
    table(
      name : "order",
      first: 5, 
      filter : {
        joindown : {
            relation : {
              name : "Order",
              from : "OrderLine"
            }
            _some : {
              joinup :{
                relation : {
                  name : "Product"
                },
               
                column : "Description",
                stringValue : {
                  _eq : "Product 103"
                }
              }
            }
          }
      }
      orderBy : [
        {column : "customerNo", order : DESC},
        {column : "orderDate", order : ASC},
        {column : "orderNo"}
      ])
    {
      items
      {
        orderNo : integerValue
        customerNo : integerValue
        address : stringValue (name : "addressLine1")
        orderDate : dateValue
        createdDate : dateValue
        createdTime : timeValue
        createdTimestamp : timestampValue
        
        totalDiscountPercent : decimalValue
        editStatus : integerValue
        
        joindown(relation : "Order", from : "OrderLine")
        {
          items
          {
            orderNo : integerValue
            lineNo : integerValue
              
            joinup(relation : "Product")
            {
              description : stringValue
            }
          }
        }
        
        joinup(relation : "Customer")
        {
          name : stringValue
          
          joinup(relation : "Country")
          {
            name : stringValue
            
            joinup(relation : "Language")
            {
              name : stringValue
            }
          }
        }
      }
    }
  }
}

This query uses the core model entirely and is the equivalent of the following:

query read_order($cid:Int!)
{
  useCompany(no:$cid)
  {    
    order(
      first: 5, 
      filter : {
        joindown_OrderLine_via_Order : {
          _some : {
            joinup_Product : {
              description : {
                _eq : "Product 103"
              }
            }
          }
        }
      }
      orderBy : [
        {customerNo : DESC},
        {orderDate : ASC},
        {orderNo : ASC}
      ])
    {
      items
      {
        orderNo
        customerNo
        
        joindown_OrderLine_via_Order
        {
          items
          {
            orderNo
            lineNo
            
            joinup_Product
            {
              description
            }
          }
        }
        
        joinup_Associate_via_Customer
        {
          name
          
          joinup_Country
          {
            name

            joinup_Language
            {
              name
            }
          }
        }
      }
    }
  }
}
Last modified February 11, 2026