Getting Started with GraphQL

The GraphQL Endpoint

Unlike the Commerce7 REST API which has a variety of endpoints, the GraphQL API has a single endpoint:

POST https://api.commerce7.com/graphql

Authentication & Headers

The GraphQL API requires and supports the same authentication & headers as the REST API.

Every request must contain an Authorization header using Basic Auth, as well as a tenant header for the data you're interacting with. Details on getting your Authorization credentials & tenant values can be found at the following links:

Exploring the GraphQL Schema

We recommend starting to explore the schema by using our GraphiQL playground, which can be found by hitting the same GraphQL endpoint that you'll send requests to from your applications later on.

Go ahead and try visiting: https://api.commerce7.com/graphql

You can click on the DOCS tab on the right side to view the various queries, types & scalars. For more information on how to use the playground (and download an app-based version of it), you can check out this blog post: https://blog.logrocket.com/complete-guide-to-graphql-playground/

Making your first call to the GraphQL API

To start, let's run a query to get some basic information about a customer. You'll notice we have a variable of $customerId: GUID! being passed to our query, which is a way to allow a query from within your application to be dynamic and reused for multiple customers (rather than having to compose the query with the customerId written directly into the query each time).

In the GraphQL playground, you can pass these query variables in underneath where you've written your query in the QUERY VARIABLES tab. This accepts a JSON structure with key/value pairs as shown in the "Query Variables" tab below.

Remember to also include your HTTP Headers, example format shown in the "HTTP Headers" tab below.

query getCustomer($customerId: GUID!) {
  customer(id: $customerId) {
    firstName
    lastName
    city
    stateCode
    countryCode
  }
}
{
  "customerId":"dde4f315-67ec-4e24-9410-5e64b05cabc9"
}
{
  "tenant":"spectrawinery",
  "Authorization":"Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
curl -X POST \
  "https://api.commerce7.com/graphql" \
  -H "Content-Type: application/json" \
  -H "tenant: spectrawinery" \
  -H "Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -d '{ 
    "query": "query getCustomer($customerId: GUID!) { customer(id: $customerId) { firstName lastName city stateCode countryCode } }",
    "variables": { "customerId": "dde4f315-67ec-4e24-9410-5e64b05cabc9" }
  }'
const axios = require('axios');

const url = 'https://api.commerce7.com/graphql';
const headers = {
  Authorization: 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  tenant: 'spectrawinery'
};

const query = `
  query getCustomer($customerId: GUID!) {
    customer(id: $customerId) {
      firstName
      lastName
      city
      stateCode
      countryCode
    }
  } 
`;
const variables = {
  customerId: 'dde4f315-67ec-4e24-9410-5e64b05cabc9'
};
const payload = { query, variables };

const response = await axios.post(url, payload, { headers });
{
  "data": {
    "customer": {
      "firstName": "Andrew",
      "lastName": "Kamphuis",
      "city": "Vancouver",
      "stateCode": "BC",
      "countryCode": "CA"
    }
  }
}

Congrats, you've made your first GraphQL request with Commerce7!

Example Queries

In GraphQL, queries are the equivalent of REST’s GET action verb. They generally begin with one of the objects listed under Query and can get data from any connections that object has. Even though a POST is being sent to the GraphQL endpoint, if the body only contains queries, data will only be retrieved and not modified.

Query the first customer who's name contains Andrew and return their addresses

query getCustomerWithAddress(
  $customersLimit: PositiveInt
  $customersFilters: CustomerFilterInput
) {
  customersConnection(limit: $customersLimit, filters: $customersFilters) {
    edges {
      cursor
      node {
        firstName
        lastName
        addresses {
          address
          city
          stateCode
          isDefault
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
{
  "customersLimit": 1,
  "customersFilters": {
    "search": "Andrew"
  }
}
{
  "data": {
    "customersConnection": {
      "edges": [
        {
          "cursor": "00000000-0000-0000-0000-000000000000",
          "node": {
            "firstName": "Andrew",
            "lastName": "Kamphuis",
            "addresses": [
              {
                "address": "#624 - 289 Alexander Street",
                "city": "Vancouver",
                "stateCode": "BC",
                "isDefault": true
              }
            ]
          }
        }
      ],
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "00000000-0000-0000-0000-000000000000"
      }
    }
  }
}

Schema Design Patterns

Our schema contains the following patterns to help you navigate and implement easier:

  • For queries & fields returning filterable lists of a specific type, we use the Connection spec
    • The naming convention for these end with Connection
    • Each Connection object contains an array of edges and either totalCount or a pageInfo object for pagination purposes
      • totalCount is only returned when using offset for offset pagination (see below)
      • pageInfo is only returned when using after for cursor pagination (see below)
    • The edges each contain a node and cursor field, with node always returning the type of data you were requesting (so in the example below, the node for the customersConnection will be of type Customer
    • All Connection queries & fields allow the following 3 optional arguments:
      • limit: PositiveInt (defaults to 50)
      • after: GUID for cursor pagination (default pagination method)
      • offset: Int for offset pagination (use offset = 0 to trigger offset pagination for page 1)
    • Some Connection queries & fields have optional filters as well
  • We use enums for types that have a finite number of allowed values. In our V1 REST API, these enums are human-readable (i.e. Not Checked for a compliance status). In our GraphQL schema, these are uppercased to be proper constants, so Not Checked becomes NOT_CHECKED. With our future V2 REST API, enums will match GraphQL, but if you're writing data using the V1 REST APIs, you'll need to map those values if reading from GraphQL.

Additional Resources