Printavo API v2.0

These GraphQL API docs are used to access information in your Printavo account. Printavo is the simplest way for screen-printing, embroidering and promotional product shops to manage their business.

Rate Limiting

For API requests, we allow a maximum of 10 requests for every 5 seconds per user email or IP address.

Get Started

Requests to Printavo API v2.0 are made to the following endpoint and you will need the authentication headers below:

API v2.0 Endpoint:

www.printavo.com/api/v2

Authentication Headers

const headers = {
  'Content-Type': 'application/json',
  'email': '{{youremail@email.com}}',
  'token': '{{API token from My Account page}}'
};

New to GraphQL?

GraphQL is a departure from traditional API paradigms designed around the idea of limiting excess in requests and responses, and providing users and developers the tools to tailor their actions to exactly what they need. The core concept of GraphQL can be described as "ask for what you want and that's exactly what you'll get".

The Basics

Data models in GraphQL are called types and information about them is stored in their fields. A request to a GraphQL server will define exactly the fields that it wants to query or mutate about an object or set of objects, and will specify what the response should include. More on that can be found in the query and mutation documentation.

Collections and Pagination

The GraphQL way of grouping data is by using a connection. By default, the Printavo API paginates connections into pages of twenty-five. These connections describe a subset graph, with data objects referred to as nodes connected by edges. Because this pagination happens internally, it means the connection object that's returned in the response can contain helpful information about how its current results exist within the full dataset represented by the connection. The pageInfo fields contain this information and can be used to inform subsequent queries. In addition, each connection reports its totalNodes value to notify the requester of how many nodes are in the connection overall.

query{
  tasks {
    pageInfo {
      hasPreviousPage
      startCursor
      endCursor
      hasNextPage
    }
    edges { ... }
    nodes { ... }
    totalNodes
  }
}

Now, to dive into the actual data objects themselves and their representations, you can think of nodes as the individual records, with edges describing relationships. Edges are a powerful tool that form the underlying pagination mechanisms in GraphQL, and can be manipulated to surgically specify which nodes a request will return information on. Each edge is uniquely identified with a cursor. For example, the following query will return the IDs of the first 25 tasks, as well as the cursor values associated with the edges that connect them to the TaskConnection.

query{
  tasks {
    edges {
      cursor
      node{
        id
      }
    }
    nodes { ... }
  }
}

As you can see in the example above, using edges allows you to examine individual data records within a connection, and their cursors allow you uniquely identify the record of interest. This is where you can begin to develop more fine-tuned queries. GraphQL supports slicing, so we can limit the number of records requested, using the built-in arguments first, last, after, and before.

query{
  tasks(first: 10) {
    edges {
      cursor
      node{
        id
      }
    }
    nodes { ... }
  }
}

For the purposes of the example below, let us assume that cursor of the last edge of the previous query was the string MTA. That would be 10th entry in our dataset. The example below would then return the next page of 25 results, querying for records number 11-36 over the total dataset.

query{
  tasks(after:"MTA") {
    edges {
      cursor
      node{
        id
      }
    }
    nodes { ... }
  }
}

Combining the concepts of slicing and cursors, GraphQL allows for powerful and selective pagination. Depending on the task at hand, combining the first, last, before, and after parameters and cursors allows you to get very specific about what data you'd like to see.

For more on pagination, refer to GraphQL - Pagination and Edges.

Aliasing

GraphQL also supports aliasing for queries, mutations, and individual fields, allowing a user to customize the labels in the returned data. For one such example, take a look at the following query:

query {
  taskAlias: tasks {
    edges { ... } 
    nodes {
      nameAlias: name
    }
  }
}

The query defines an alias, taskAlias, for the tasks query and requests that each node in the returned connection contains the name field aliased as nameAlias. The response would correspondingly look like this:

{
  "data": {
    "taskAlias": {
      "edges": { ... },
      "nodes": [
        {
          "nameAlias": "Prepare the screens"
        }
      ]
    }
  }
}

Conventions: the use of !

In GraphQL, the use of the exclamation point carries two meanings, depending on context. In the context of an argument, it represents a required argument, such as in the query provided below:

query {
  task(id: ID!) {
	...
  }
}

In the task query, the use of ! indicates that an ID value is required, otherwise the query can't resolve.

In the context of a returned field, it represents a non-nullable value. For fields that return connections, the ! signifies that GraphQL will always return a connection even if that connection is empty. Several examples of this can be found on the InvoiceType, but let's look at its fees field and break it down:

fees (FeeConnection!)

If you were to query for an Invoice which had no fees attached to it, what that ! is signifying is that you'd still receive a connection when you queried the fees field, but that connection would contain no nodes. In effect, this ! denotes a promise from the GraphQL server to the user, that they can depend on something being returned and that the server won't unexpectedly return a null value when that field is requested.

Conventions: Querying Edges vs Nodes

In the examples above, we've shown you that when querying a connection, GraphQL allows you to refer to both edges and nodes, and request data from either. Generally, it's better practice to develop your data requests on the edges, as the added information managed by the edge (in particular the cursor), is what allows a query to be made more direct and specific. For simpler requests, it can be easier to query against the nodes of a connection, but you lose out on pagination specificity.

Complexity

GraphQL allows for very powerful queries, which can allow a user to deeply and surgically probe massive datasets. However, it does not eliminate the underlying problem facing any data-serving API model: querying and reporting a lot of data at once is a time-costly operation! In order to protect the efficacy of the Printavo API, we're forced to enforce limits on the depth and complexity acceptable for a query. Currently, the complexity limit is 25000, and the maximum depth permitted is 13. For an explanation of how complexity is calculated, refer to GraphQL-Ruby's - Complexity and Depth.

Continued Reading

The above are just a few select conventions and principles that form the core of what GraphQL is all about. In order to learn more, check out GraphQL's official documentation!