How to build a request

Plant Jammer Studio API accepts POST requests containing authorization token in header and a GraphQL body.

Authorization

In order to obtain an auth token a use tokenAuth mutation with valid email and password. tokenAuth is the only request that does not require auth tokens. What about verifyToken and refreshToken?

Each request except the abovementioned require header with a valid token.

Authorization: jwt <auth_token>

More on tokens in the JWT documentation.

Meta request context

Some of the settings can influence more than just one object, therefore we decided to include an optional meta param accepting QueryMeta object. It controls general response properties, like language or diet-based filtering. If the request does not contain meta object or some of it’s fields are missing, the default values will be set from Client object.

field

type

accepted values

default

language

enum

ClientLanguage

Client.language or English

diets

[enum]

Diet

None

unitsSystem

enum

UnitsSystemEnum

None

masks

[ID]

IngredientMask

None

Deprecated field:

diets

[enum]

Diet

None

diets field is deprecated, therefore, we strongly advice to pass diets by using IngredientMask. Default dietary masks can be found in the API using a tag (id 748).

query {
  tags(id:748) {
    masks {
      id
      nameInternal
    }
  }
}

Dietary mask ids can be added to meta payload together with any other relevant masks.

query {
  ingredients(
    meta: {
      language: DANISH,
      masks: [4, 34]
    })
    {
      name
    }
  }

Queries and Mutations

There is no distinction between list and detail views, like it is a common practice with RestAPIs. All queries will always return a list of objects. However, if you pass a specific id as a lookup, you are always guaranteed a single object in the list.

Balancer is the single exception to this rule and it returns an object, since it is a function query with no attachment to a database model. Some functional queries do not return objects with ids, rather only computed values. These are:

Currently, we support only authorization-related mutations that are necessary to obtain and refresh an auth token.

To learn more about queries and mutations, see GraphQl documentation.

Using fragments

GraphQL accepts reusable sets of fields called fragments. They can be used to simplify a large request that contains multiple queries. You can find an example in Fragments.

Multilinguality

We support multiple languages, list of currently supported ones can be found in ClientLanguage. Any object containing name or description field will have these fields’ values translated into a target language. Choosing a target language can be achieved on several levels. The API’s default language is English, which is overwritten if an active client has language field set. To change a language for a specific request, use Meta request context.

If you wish to override this functionality, any multilingual field accepts a forceField parameter that allows you to get back any language or ID of the multilingual object.

M2M fields

Recursive queries: Some relationships between types are 2-way, such as Ingredient.tags which can also be accessed from the other side - Tag.ingredients. Be carful about querying in a recursive fashion, because the response size can quickly grow. Pagination of nested fields: Django will not allow pagination on nested fields in most cases. However, filtering the nested field will work.

Response Info

For request debugging, optimisation and cost management, you can read metrics in the response’s info field. Do not rely on these fields with your functionality, the info fields can be deprecated.

Timeout

GraphQL queries can easily become too heavy to fulfill. Recursive queries for i.e. ingredients-tags-ingredients would have to return 10 mil results.

In case your query takes longer than 15 seconds, you will see a following response.

{
  "data": null,
  "errors": [
    {
      "message": "The request timed out (>15000ms)."
    }
  ]
}

Multitenancy

Most objects in the database are owned by a `core database tenant. These objects are created by Plant Jammer and should be fully supported. To add your own object to the database, arrange with us to have a tenancy created for you. Every ownable object has an `ownerName field add_node an owner filter.

Tags

Tags are a way to enrich the database object with your own data. There are some core tags that you can access and to add your own please you need your own tenancy (refer to Multitenancy above). Tags can be used for simple filtering, but also to attach multilingual data, plain strings, float values, icons and images. Tags can also be used to group together data of different types.

The API makes it simple for you to use a tag on an object as if it were a regular field using tagsAsBoolean and tagAsValue fields on any taggable type.

query tags {
  dishes(owner: "core") {
    id
    tagsAsBoolean(tags: [1,2,3,4,5,6,7,8], mode: ANY)
  }
}

The field tagsAsBoolean can return true/false based on a set of tags. The modes ANY, ALL and NONE define whether to return true if all tags are present, any of the tags are present or none of them are present on each returned object.