Skip to main content

Schema

The Codex GraphQL API generates the schema definition based on the models created in the respective organization.

Types

The GraphQL schema is generated from the models defined in the specific organization in Codex. For each model in your organization, the Codex GraphQL API created a corresponding GraphQL type.

Names

Type name is the alias of the model created in Codex with title case. For example: 'Signature', 'Recipe', 'Publication' etc.

Reserved type names

Below is a list of reserved type names, which means you cannot use them as alias of a model.

Query type Query

Scalar types String, Float, Int, Boolean, DateTime, Json,

All internal Codex types start with the keyword Codex. That means you cannot create models by using an alias that starts with the keyword Codex.

Fields

GraphQL type fields are generated from the corresponding content type fields. Each type contains a list of common fields explained below.

Names

Fields name is the alias of the model field as configured in Codex. For example: 'title', 'description', 'thumbnail', 'price' etc.

Types

Field type is determibed based on the following mappings:

Codex TypeGraphQL Type
TextString
List of texts[String]
Number (int)Int
List of numbers (int)[Int]
Number (decimal)Decimal
List of number (decimal)[Decimal]
DateTimeDateTime
BooleanBoolean
LocationCodexLocation
RefereceCodexEntry
List of ReferecesCodexEntryCollection
MediaCodexMedia
Media[CodexMedia]
RichTextString
RichContent[CodexContentBlock]
RichContent (v2)CodexRichContent
AuthorCodexAuthor
List of authors[CodexAuthor]
TagString
List of tags[String]
SectionCodexSection
List of sections[CodexSection]
UrlString

Entry interface

All object types generated from Codex for the models inherit the Entry interface. The entry interface contains a list of fields which are common for all models and their object types respectively.

enum CodexEntryStatus {
PUBLISHED
DELETED
DRAFT
UNPUBLISHED
ARCHIVED
SCHEDULED
EDITED
}

type CodexSystem {
title: String,
slug: String,
clonedFrom: String
modelAlias: String,
modelId: String,
externalId: String
versionId: String!
siteId: String!
metrics: CodexMetrics
labels: [CodexLabel]
status: CodexEntryStatus
publishedAt: DateTime
firstPublishedAt: DateTime
createdAt: DateTime
updatedAt: DateTime
unpublishedAt: DateTime
}

interface CodexEntry {
"""
The id of the entry.
"""
id: String!

"""
System information about the entry.
"""
system: CodexSystem

"""
Additional dynamic metadata about the entry.
"""
attrs: Json
}

The common fields are:

id - String value representing the id of the entry. This value is generated by Codex. The ids are auto generated by Codex and are unique globaly, meaning no two entries will have the same Id even if they are of different models.

system Object value representing system fields about the entry, handled by Codex.

attrs Object value representing dynamic metadata for the entry. This field is for API purposes only.

System

Entry system is a common object for all entries that contains common metadata about the entry. The fields of System are:

title - String value representing the title of the entry. This title has the same value as the field configured to represent the title of the entry.

modelAlias - String value representing the alias of the model that the entry belongs to.

modelId - String value representing the id of the model that the entry belongs to.

externalId - String value representing the an external id of the entry. This value is not generated by Codex.

versionId - String value representing the version id of the entry. This value is generated by Codex.

siteId - String value representing the site id of the entry.

metrics - Object representing metrics about to the entry.

labels - Array of objects representing labels assigned to the entry.

status - Enum value representing the status of the entry.

publishedAt - DateTime representing the publish date time of the entry in UTC.

firstPublishedAt DateTime representing the first publish date time of the entry in UTC.

createdAt DateTime representing the create date time of the entry in UTC

updatedAt DateTime representing the latest update date time of the entry in UTC

unpublishedAt DateTime representing the first publish date time of the entry in UTC.

Codex types

The Codex GraphQL API contains a list of pre defined object types for some of the more advanced fields types provided in model builder. Below you can find more information about each object type:

Location

Location object type represents the location field in Codex model builder. It contains information about the address, latitude and longitude of a speicifc location.

type CodexLocation {
address: String
latitude: String
longitude: String
}

Media

Media object type represents the media field in Codex model builder. A media in Codex is an asset which can be an image, file, video, playlist, audio or podcast (powered by GjirafaTech Video Player and Platform)

enum CodexAssetType {
IMAGE
FILE
VIDEO
VIDEO_PLAYLIST
AUDIO
PODCAST
}

type CodexMedia {
id: String
type: CodexAssetType!
media: Media
url(transformation: CodexAssetTransformation, focalPointRatio: String): String
focalPoints: [CodexRatioFocalPoint]
}

Each media field can have multiple ratios for focal points. Since these focal point coordinates are on media field leve, Codex GraphQL API provides a new asset URL resolver for media values where you can also specify the ratio focal point that you want to use in that image. If a specific image has the ratio square of '1:1' you can retrieve the image with the URL specific for that ratio based on adjustments set in Codex Admin.

The CodexRatioFocalPoint has the following properties:

type CodexRatioFocalPoint {
ratio: String!
focalPoint: CodexFocalPoint
}

Rich Content

Rich Content object type represents the value of RichContent field in Codex model builder. It contains an array of blocks (RichContentBlock), all entries references inside the rich content editor and all the media used in the same field.

type CodexRichContent {
blocks: [CodexRichContentBlock]
entries(offset: Int, limit: Int): CodexEntryCollection
media(offset: Int, limit: Int): CodexAssetCollection
@deprecated(
reason: "This type of media field will be deprecated. Use _v2 field instead."
)
media_v2(offset: Int, limit: Int): CodexMediaCollection
}

type CodexRichContentBlock {
type: String
text: String
content: Json
marks: [CodexRichContentBlockMark]
attrs: Json
contentHTML: String
}

type CodexRichContentBlockMark {
type: String
attrs: Json
}

Rich Content as V2

RichContent object type is a new change in Codex GraphQL API which is expected to replace the old version of Rich Content output type as an array of blocks. For backward compatibility reasons, right now each rich content field will created two fields in the generated model object type

  alias: [CodexContentBlock!]
alias_v2: CodexRichContent

The first field will be left as it is for a period of time untill all the GraphQL users will migrate to the new field and then will be removed from the generated schema.

We recommend users to start using the new generated field with the "_v2" prefix which contains the automatic resolving of referenced entries and media used inside the Rich Content field.

Content Block

danger

DEPRECATED: This type will be replaced with the new version of RichContentBlock (see above) in the future

Content block object type represents a block inside the Rich Content field in Codex model builder. It contains metadata about the blocks used in the editor. If you want to learn more about Content Block type, please read the Editor documentation.

type CodexContentBlockMark {
type: String
attrs: Json
}

type CodexContentBlock {
type: String
text: String
content: Json
marks: [CodexContentBlockMark!]
attrs: Json
contentHTML: String
entries(offset: Int, limit: Int): CodexEntryCollection
media(offset: Int, limit: Int): CodexMediaCollection
}
info

The entries list is automatically filled when a block references entries any model or any media. For example, when the users adds the reference block, they can choose multiple entries to reference (embed) inside the Rich Content field. These references are automatically added to the entries field of ContentBlock. The same applies for the media block.

Metrics

Metrics object type represents content metrics about the entry based on the fields used in the model. It contains numbers about nr. of words, characters, sentences images and the estimated reading time for the entry.

type CodexMetrics {
wordCount: Int
characterCount: Int
sentenceCount: Int
imageCount: Int
readingTime: Int
}

Section

Section object type represents the Codex sections that you can assign to entries. It contains the fields presented below.

type CodexSection {
id: String!
title: String
parentId: String
slug: String
url: String
siteId: String
externalId: String
path: [CodexSection]
parent: CodexSection
description: String
children(offset: Int, limit: Int): CodexSectionCollection
media(offset: Int, limit: Int): CodexAssetCollection
references(offset: Int, limit: Int): CodexEntryCollection
}

Label

Label object type represents the Codex labels that you can assign to entries. It contains the fields presented below.

type CodexLabel {
id: String!
name: String
description: String
color: String
siteId: String
externalId: String
}

Author

Author object type represents the Codex authors that you can assign to entries as a special field. It contains the fields presented below.

type CodexAuthor {
id: String!
userId: String
byline: String
externalId: String
firstName: String
lastName: String
url: String
imageId: String
biography: String
profession: [String!]
email: String
website: String
facebook: String
instagram: String
twitter: String
linkedin: String
tiktok: String
telegram: String
image: CodexAsset
}

Assets

Codex provides native asset management through the GraphQL API. The asset object types provides a set of fields and methods for delivering content to end users. The GraphQL API offers a predefined schema for retrieving assets from Codex. Below you can find the representation of an asset:

type CodexAsset {
id: String!
title: String
contentType: String
fileName: String
path: String
caption: String
alt: String
author: String
source: String
size: Long
tags: [String!]
externalId: String
versionId: String
width: Int
height: Int
duration: Float
type: CodexAssetType!
focalPoint: CodexFocalPoint
url(transformation: CodexAssetTransformation, useFocalPoint: Boolean): String
}

Assets in Codex can be of of multiple types: Images, Files, Videos, VideoPlaylists, Audios or Podcasts. Codex provides out of the box features for images uploaded through Assets API, such as on the fly image transformation or automatic compression.

enum CodexAssetType {
IMAGE
FILE
VIDEO
VIDEO_PLAYLIST
AUDIO
PODCAST
}

Focal point is the X/Y represantation of the main content of the image, which can be adjusted by users in Codex Admin. The values are from 0-1 and represent the percentage of the focal point position starting from top-left corner of the image. For example the center focal point has the valuex x: 0.5 and y: 0,5.

type CodexFocalPoint {
x: Float
y: Float
}

Asset transformation

Codex provides on the fly image transformation powered by GjirafaTech Captain CDN. By default the original image is returned. If you want to change the size of the image or the quality, you can use the image transformation argument in the URL field for the CodexImage. The transformation argument provides these options:

input CodexAssetTransformation {
width: Int
height: Int
resize: CodexImageTransformationResize
quality: Int
gravity: CodexImageTransformationGravity
format: CodexVideoTransformationFormat
preset: String
orientation: CodexVideoTransformationOrientation
}

enum CodexImageTransformationResize {
FIT
FILL
AUTO
}

enum CodexImageTransformationGravity {
NORTH
SOUTH
EAST
WEST
NORTH_EAST
NORTH_WEST
SOUTH_EAST
SOUTH_WEST
CENTER
}

enum CodexVideoTransformationFormat {
THUMBNAIL
HTML
JS
JSON
}

enum CodexVideoTransformationOrientation {
HORIZONTAL
VERTICAL
}

If you specify the useFocalPoint to true, the GraphQL API will include adjust the gravity query parameters based on the focal point specified for that asset in Codex admin.

By default, you will get horizontal video player, unless you specify it differently with the CodexVideoTransformationOrientation.

Video Format

Codex provides out of the box URL building for delivering videos from GjirafaTech VP. The supported formats are:

  1. Thumbnail: renders the URL of the thumbnail of the video as an image
  2. HTML: renders the HTML embed URL for the video
  3. JS: renders the Javascript file URL for embeding the video
  4. JSON: renders the JSON config URL for embeding the video

Lists

Codex provides native listing management through the GraphQL API. Below you can find the representation of an asset:

type CodexList {
id: String!
name: String
description: String
siteId: String
externalId: String
entries(
offset: Int
limit: Int
where: CodexListEntryFilter
order: CodexListEntryOrder
): CodexListEntryCollection
}

type CodexListEntry {
startAt: DateTime
endAt: DateTime
entry: CodexEntry
}

You can filter the list entries based on their startAt and endAt date time fields to retrieve entries that are going to be displayed at a specific time in a web page.

Example

Let's take an example of a model created in Codex for recipes.

Model: 'recipe'
{
"alias": "recipe",
"fields": [
{
"alias": "title",
"type": "text",
"valueType": "single"
},
{
"alias": "timeToCook",
"type": "number",
"valueType": "single"
},
{
"alias": "tags",
"type": "text",
"valueType": "list"
},
{
"alias": "image",
"type": "media",
"valueType": "single"
},
{
"alias": "parameters",
"type": "json",
"valueType": "single"
}
]
}

The generated GraphQL object type would be

type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
tags: [String]
image: CodexMedia
parameters: Json

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

Single entry retrieval

All retrieval of data from Codex GraphQL APi is done through the root query object type. The query object contains the fields for retrieving entries for all models created in Codex.

When you want to retrieve a single entry of a model, you can use the single entry field of the root query. The name of the field is the same as the name of the type generated based on the alias of the model in camelCase. If we take the example of the recipe model from the previous section, to query a single recipe you would need to write the following GraphQL query. You need to pass the id of the entry as an argument for retrieving the respective entry.

type Query {
recipe(id: String): Recipe
}

An example for retrieving a single recipe with a specific Id would be:

query {
recipe(
id: "meTrC06uRK"
){
id
timeToCook
tags
image
parameters
}
}

Multi entry retrieval

When you want to retrieve multiple entries from a specific model, you can use the entry collection field of the root query. The name of the field is the alias of the model plus the keyword collection: {alias}Collection. For each collection the following object types are created in the Codex GraphQL API

type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
tags: [String]
image: CodexMedia
parameters: Json

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

type RecipeCollection {
items: [Recipe]
offset: Int
limit: Int
total: Int
}

type RecipeFilter {
id: CodexIdFilter
title: CodexStringFilter
timeToCook: CodexIntFilter
tags: CodexStringListFilter
system: CodexSystemFilter

and: [RecipeFilter]
or: [RecipeFilter]
}

type RecipeOrder {
id: CodexOrderDirection
title: CodexOrderDirection
timeToCook: CodexOrderDirection
system: CodexSystemOrder

thenBy: [RecipeOrder]
}

type RecipeRelations implements EntryRelations {
entryCollection(
offset: Int
limit: Int
): EntryCollection
}

type Query {
recipeCollection(
offset: Int
limit: Int
where: RecipeFilter
order: RecipeOrder
): RecipeCollection
}

Each collection field of query returns a collection object type. The collection contains four fields

items

Array of object where each item of of the object type the collection belongs too. For example for recipe model items returns an array of recipe object types: [recipe].

offset

Integer representing the number of items to be skipped in the result.

limit

Integer representing the number of items to be returned in the result.

total

Integer representing the total number of entries that are part of the collection.

To query multiple recipes you would need to write the following GraphQL query:

query {
recipeCollection {
items {
id
timeToCook
tags
image
parameters
}
}
}

Pagination

By using collection query arguments and collection result fields, you can perform custom pagination for all collections. An example query for getting paginated entries from recipe model would be:

query {
recipeCollection(
offset: 20
limit: 20
){
items {
id
timeToCook
tags
image
parameters
}
offset
limit
total
}
}

Filtering

You can filter all entries belonging to a specific model on any of their fields or the common Entry interface fields. For each model, a model filter input is generated which contains filtering options for the fields belonging to that model.

Below you can find the filter input generated for our recipe model from the previous examples:

type RecipeFilter {
id: CodexIdFilter
title: CodexStringFilter
timeToCook: CodexIntFilter
tags: CodexStringListFilter
system: CodexSystemFilter

and: [RecipeFilter]
or: [RecipeFilter]
}

Each generated filter input contains a a set of inputs for field data type supported by Codex. Below you can find the native filter input from Codex.

Boolean filter

You can filter with equals (eq) or not equals (ne) operator for each boolean field in your models.

input CodexBooleanFilter {
eq: Boolean
ne: Boolean
}

DateTime filters

You can filter with equals (eq), not equals (ne), less than (lt), less than or equals (lte), greather than (gt), greater than or equals (gte), exists (exists) operators for each date and time field in your models. You can also perform more complet filtering using and & or logical operators for combining multiple fitlers in the same request.

input CodexDateTimeFilter {
eq: DateTime
ne: DateTime
lt: DateTime
lte: DateTime
gt: DateTime
gte: DateTime
exists: Boolean
and: [CodexDateTimeFilter!]
or: [CodexDateTimeFilter!]
}

Float filters

You can filter with equals (eq), not equals (ne), less than (lt), less than or equals (lte), greather than (gt), greater than or equals (gte), exists (exists) operators for each number field with decimal values in your models. You can also perform more complet filtering using and & or logical operators for combining multiple fitlers in the same request.

input CodexFloatFilter {
eq: Float
ne: Float
lt: Float
lte: Float
gt: Float
gte: Float
in: [Float!]
notIn: [Float!]
exists: Boolean
and: [CodexFloatFilter!]
or: [CodexFloatFilter!]
}

You can filter with contains all (all), contains some (some) or contains none (none) operators for each float field with list value type in your models.

input CodexFloatListFilter {
all: [Float!]
some: [Float!]
none: [Float!]
}

Id filters

For id fields (such as entry id field) you can use the CodexIdFilter input. It offers equals (eq), not equals (ne), in (in), not in (notIn), exists (exists) operators for foltering. All Codex object types contain string unique identifiers. You can also perform more complet filtering using and & or logical operators for combining multiple fitlers in the same request.

input CodexIdFilter {
eq: String
ne: String
in: [String!]
notIn: [String!]
exists: Boolean
and: [CodexIdFilter!]
or: [CodexIdFilter!]
}

Int filters

You can filter with equals (eq), not equals (ne), less than (lt), less than or equals (lte), greather than (gt), greater than or equals (gte), exists (exists) operators for each number field with integer values in your models. You can also perform more complet filtering using and & or logical operators for combining multiple fitlers in the same request.

input CodexIntFilter {
eq: Int
ne: Int
lt: Int
lte: Int
gt: Int
gte: Int
in: [Int!]
notIn: [Int!]
exists: Boolean
and: [CodexIntFilter!]
or: [CodexIntFilter!]
}

You can filter with contains all (all), contains some (some) or contains none (none) operators for each integer field with list value type in your models.

input CodexIntListFilter {
all: [Int!]
some: [Int!]
none: [Int!]
}

String filters

You can filter with equals (eq), not equals (ne), in (in), not in (notIn), contains (contains), not contains (notContains), exists (exists), starts with (startsWith), ends with (endsWith), starts with any (startsWithAny) or ends with any (endsWithAny) operators for each text field in your models. All string operators are case insensitive. You can also perform more complet filtering using and & or logical operators for combining multiple fitlers in the same request.

input CodexStringFilter {
eq: String
ne: String
in: [String!]
notIn: [String!]
contains: String
notContains: String
exists: Boolean
startsWith: String
endsWith: String
startsWithAny: [String!]
endsWithAny: [String!]
and: [CodexStringFilter!]
or: [CodexStringFilter!]
}

You can filter with contains all (all), contains some (some) or contains none (none) operators for each text field with list value type in your models.

```graphql
input CodexStringListFilter {
all: [String!]
some: [String!]
none: [String!]
}

Reference filters

You can filter with exists (exists), entry id (entryId) or model alias (model) for each reference field in your models. The entry id and model operations are built on top of String filter.

input CodexReferenceFieldFilter {
exists: Boolean
entryId: CodexStringFilter
model: CodexStringFilter
}

input CodexReferenceListFieldFilter {
entryId: CodexStringListFilter
model: CodexStringListFilter
}

Media filters

You can filter with exists (exists), asset id (id) or asset type (type) for each media field in your models. The asset id is built on top of stirng filter.

input CodexMediaFieldFilter {
exists: Boolean
id: CodexStringFilter
type: CodexAssetTypeFilter
}

input CodexMediaListFieldFilter {
id: CodexStringListFilter
type: CodexAssetTypeListFilter
}

input CodexAssetTypeFilter {
in: [CodexAssetType!]
notIn: [CodexAssetType!]
exists: Boolean
}

input CodexAssetTypeListFilter {
all: [CodexAssetType!]
none: [CodexAssetType!]
some: [CodexAssetType!]
}

Section field filters

You can filter with equals (eq), not equals (ne), in (in), not in (notIn) and inlcude children (includeChildren) operations for each section field in your models. All these operations are performed with section ids.

If you set includeChildren to true, the filter will automatically include all child sections nested under the specified parent sections in both CodexSectionFieldFilter and CodexSectionListFieldFilter.

input CodexSectionFieldFilter {
eq: String
ne: String
in: [String!]
notIn: [String!]
includeChildren: Boolean
}

input CodexSectionListFieldFilter {
all: [String!]
some: [String!]
none: [String!]
includeChildren: Boolean
}

Author field filters

You can filter with equals (eq), not equals (ne), in (in) and not in (notIn) operations for each author field in your models. All these operations are performed with author ids

input CodexAuthorFieldFilter {
eq: String
ne: String
in: [String!]
notIn: [String!]
}

input CodexAuthorListFieldFilter {
all: [String!]
some: [String!]
none: [String!]
}

Status filter

input CodexEntryStatusFilter {
in: [CodexEntryStatus!]
notIn: [CodexEntryStatus!]
exists: Boolean
}

System filters

If you need to perform filtering on system fields you can use the system filter input objects. It offers filtering on the below fields.

input CodexSystemFilter {
title: CodexStringFilter
slug: CodexStringFilter
siteId: CodexIdFilter
externalId: CodexStringFilter
createdAt: CodexDateTimeFilter
updatedAt: CodexDateTimeFilter
publishedAt: CodexDateTimeFilter
firstPublishedAt: CodexDateTimeFilter
unpublishedAt: CodexDateTimeFilter
status: CodexEntryStatusFilter
labels: CodexStringListFilter
and: [CodexSystemFilter!]
or: [CodexSystemFilter!]
}

For example if you want to retrieve all recipes that have timeToCook higher than 5 and contain the tag 'healthy' than you would write the followig query:

query {
recipeCollection (
where: {
timeToCook: { gt: 5 }
tags: { some: { eq: "healthy" } }
}
){
items {
id
timeToCook
tags
image
parameters
}
offset
limit
total
}
}

Combining multiple fields in the where filter input is performed using the "and" logic operator. The example above is equivalent to the query below:

query {
recipeCollection (
where: {
and: [
{ timeToCook: { gt: 5 } }
{ tags: { some: { eq: "healthy" } } }
]
}
){
items {
id
timeToCook
tags
image
parameters
}
offset
limit
total
}
}

You can also perform the "or" logical operator if you want to retrieve entries that fit any of the specified criterias. For example if you want to retrieve all recipes that have time to cook equal to 5 OR contain the tag healthy, execture the following query:

query {
recipeCollection (
where: {
or: [
{ timeToCook: { eq: 5 } }
{ tags: { some: { eq: "healthy" } } }
]
}
){
items {
id
timeToCook
tags
image
parameters
}
offset
limit
total
}
}

Ordering

By default all entries belonging to a sepcific collection are ordered based on their published date & time in descending mode.

If you want to order entries based on another field, you can use the order argument of the collection fields. For each collection a order input is generated which contains sorting options for all orderable fields belonging to that model.

enum CodexOrderDirection {
ASC
DESC
}

type RecipeOrder {
id: CodexOrderDirection
title: CodexOrderDirection
timeToCook: CodexOrderDirection
system: CodexSystemOrder

thenBy: [RecipeOrder]
}

For example if you want to sort recipes based on the title asceding, than you would write the following query:

query {
recipeCollection (
order: {
title: ASC
}
){
items {
id
timeToCook
tags
image
parameters
}
offset
limit
total
}
}

You can also apply ordering on multiple fields by using the thenBy field of the order input. Ordering on multiple fields can be used only if you have multiple entries with the same value for a specific field.

query {
recipeCollection (
order: {
timeToCook: ASC
thenBy:
[
{
title: DESC
}
]
}
){
items {
id
timeToCook
tags
image
parameters
}
offset
limit
total
}
}

References

Codex model builder offers the possibility to reference entries from different models into the reference field. Depending on the reference field configuration the Codex GraphQL API generates the necessary schema to enable developers to retrieve the referenced content in an intuitive manner. Let's take the previous example of our recipe model. We are going to create a new model restaurant which represents content for specific restaurants in a city. Let's define the restaurant model as follows:

type Restaurant implements CodexEntry {
id: String!
name: String
address: CodexLocation
image: CodexMedia
startHour: Int
endHour: Int
hasDelivery: Boolean

system: CodexSystem
attrs: Json
relations: RestaurantRelations
}

Single strict reference

We are also going to add a new field to our existing recipe model with the alias restaurant which references to the Restaurant model as a single value. Now the updated schema of our recipe model is:

type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
tags: [String]
restaurant: Restaurant
image: CodexMedia
parameters: Json

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

You can retrieve all fields of the referenced restaurant same as you will retrieve other fields of recipe.

query {
recipe(
id: "RECIPE_ID"
){
id
timeToCook
tags
image
parameters
restaurant: {
id
name
address {
address
latitude
longitude
}
startHour
endHour
hasdelivery
}
}
}

Single dynamic reference

By default reference fields can include entries from all existing models. If you don't restrict allowed models in the created reference field (or allow more than one model to be referenced) then the Codex GraphQL API will generate the field with the generic Entry interface for the field.

Let's add a new field in our recipe model with the alias related which can by any entry from any model as a related content which will be displayed to end-users. The updated schema for our recipe model is:

type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
tags: [String]
restaurant: Reference
image: Media
parameters: Json
restaurant: Restaurant
related: Entry

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

To retrieve the fields of the referenced entry you can use Inline Fragments from GraphQL. Let's say our related entry can be another recipe or a restaurant, to retrieve fields from each one of them we can use the following query:

query {
recipe(
id: "RECIPE_ID"
){
id
timeToCook
tags
image
parameters
related {
id
... on Recipe {
title
timeToCook
}
... on Restaurant {
name
hasDelivery
}
}
}
}

Multi strict reference

We are also going to add a new field to our existing recipe model with the alias restaurants which references to the Restaurant model as a list value. Now the updated schema of our recipe model is:

type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
tags: [String]
restaurant: Reference
image: Media
parameters: Json
restaurant(
offset: Int
limit: Int
): RestaurantCollection

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

You can retrieve all fields of the referenced restaurants same as you will retrieve other fields of recipe. You can also limit the number of referenced restaurants you want to retrieve, or see the total number of restaurants referenced.

query {
recipe(
id: "RECIPE_ID"
){
id
timeToCook
tags
image
parameters
restaurants (limit: 3) {
items: {
id
name
address {
address
latitude
longitude
}
startHour
endHour
hasdelivery
}
total
}
}
}

Multi dynamic reference

By default reference fields can include entries from all existing models. If you don't restrict allowed models in the created reference field (or allow more than one model to be referenced) then the Codex GraphQL API will generate the field with the generic Entry interface for the field.

Let's add a new field in our recipe model with the alias related which can by any entry from any model as a related content which will be displayed to end-users. The updated schema for our recipe model is:

type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
tags: [String]
restaurant: Reference
image: Media
parameters: Json
restaurant: Restaurant
related(
offset: Int
limit: Int
): EntryCollection

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

To retrieve the fields of the referenced entries you can use Inline Fragments from GraphQL. Let's say our related entry can be another recipe or a restaurant, to retrieve fields from each one of them we can use the following query:

query {
recipe(
id: "RECIPE_ID"
){
id
timeToCook
tags
image
parameters
related (limit: 3) {
items {
id
... on Recipe {
title
timeToCook
}
... on Restaurant {
name
hasDelivery
}
}
total
}
}
}

Relations

By using references you can create advanced relations between different models in Codex. Apart from automatic field generation based on reference field configurations, Codex GraphQL also generates reverse relation retrieval for querying all entities that have references an entry. You can query all of these entries by using the relations field, which is a common field for each entry.

In our recipe model we have a single reference to the restaurant model. The generated relations field for restaurants are:

type RecipeRelations implements EntryRelations {
recipeCollection(
offset: Int
limit: Int
where: RecipeFilter
order: RecipeOrder
): RecipeCollection
entryCollection(
offset: Int
limit: Int
where: CodexEntryFilter
order: CodexEntryOrder
): CodexEntryCollection
}

Since our reference field in recipe model allows only restaurant models, then our restaurant model contains a field for all recipes that are referencing a restaurant entry. By default all relation object contain the entryCollection field which returns all entries referencing the restaurant regardless of the model or field configuration.

If we would like to retrieve 10 recipes that you can find in a particular restaurant, you can perform the following query:

query {
restaurant(
id: "RESTAURANT_ID"
) {
id
name
address
image
startHour
endHour
hasDelivery

relations {
recipeCollection(limit: 10) {
items {
id
title
timeToCook
tags
}
}
}
}
}

You can perform additional filtering and ordering on top of relations results by using the where and order arguments. These arguments are generated based on collection type.

query {
restaurant(
id: "RESTAURANT_ID"
) {
id
name
address
image
startHour
endHour
hasDelivery

relations {
recipeCollection(
limit: 10
where: {
and: [
{ timeToCook: { gt: 5 } }
{ tags: { some: { eq: "healthy" } } }
]
}
) {
items {
id
title
timeToCook
tags
}
}
}
}
}

Next entries

In the relations type for each specific model you will be able to find a field named next{Alias}EntryCollection which returns a collection of entries for that model, relative to that specific entry based on filtering and sorting specified in arguments. This allows you to retrieve "next" or "previous" entries. For example, you can retrieve the recipes published after a specific recipe (next) by using the asceding order in the publishedAt system field, or retrieve the recipes published before a specific recipe (previous) by using the descending order in the publishedAt system field. The query would look like this:

query {
recipe(
id: "RECIPE_ID"
){
id
timeToCook
tags
image
parameters
relations {
nextRecipes: nextRecipeCollection (
limit: 5
order: {
system: {
publishedAt: ASC
}
}
) {
items {
id
timeToCook
//other fields
}
}
previousRecipes: nextRecipeCollection (
limit: 5
order: {
system: {
publishedAt: DESC
}
}
) {
items {
id
timeToCook
//other fields
}
}
}
}
}

You can sort by model specific number or date time fields. This feature works only with number and date time fields. If you use any other field type in sorting it will return a null result.

You can also filter out entries using the model specific filter input, allowing you to filter by any filterable fields of the model same way as you can do in the main model collection queries.

Please keep in mind performance when using this feature, since it will introduce multiple round trips to the database to retrieve the relative next entries. It is recommended to be used on single entry queries. Using it in large lists of entries might cause latencies on responses.

Generic queries

In addition to collections for entries of a specific model, Codex GraphQL allows you to query for the generic Entry interface in the root query object. Same as with other models, it offers two methods entry for single entry retrievak and entryCollection for multi entry retrieval.

type Query {
entry(id: String): CodexEntry
entryCollection(
offset: Int
limit: Int
where: CodexEntryFilter
order: CodexEntryOrder
): CodexEntryCollection
}

Let's say we have two models in our schema so far, recipe and restaurant.

type Restaurant implements CodexEntry {
id: String!
name: String
address: CodexLocation
image: CodexMedia
startHour: Int
endHour: Int
hasDelivery: Boolean

system: CodexSystem
attrs: Json
relations: RestaurantRelations
}
type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
tags: [String]
restaurant: Reference
image: Media
parameters: Json
restaurant: Restaurant

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

If we have the entry ID but don't know the model of the id, then we can use the generic entry retrieval method and then use inline fragments to select specific fields from each model respectively. By default you can use the common fields of all entries without needing to use the inline fragments.

query {
entry(
id: "meTrC06uRK"
){
id
system {
title
publishedAt
}
... on Recipe {
title
timeToCook
}
... on Restaurant {
name
hasDelivery
}
}
}

We can also retrieve multiple entries from all the models in the generic entry collection query method. Same as in the previous example, by using the inline fragmenting we can select specific fields from different models. For example if we want to retrieve top 5 most recently published entries from all the models, we can perform the following query:

query {
entryCollection(
limit: 5
){
items {
id
system {
title
publishedAt
}
... on Recipe {
title
timeToCook
}
... on Restaurant {
name
hasDelivery
}
}
limit
total
}
}

Generic filtering

Codex GraphQL API provides advanced filtering in the generic entry collection method. It generates the generic entry filter based on all existing models in your Codex organization. For each model created in Codex one filter input is generated for all the filterable fields of the model and also that filter input is added to the generic entry filtering input as a sub-field. It allows developers to perform complex filtering on multiple models in one request. This kind of filtering is useful when you want to filter all entries in common fields (such as id or system fields) or perform more advanced filtering in common fields defined in the models. Let's take an example when we have two models that have some common fields and see the generated schema:


type Recipe implements CodexEntry {
id: String!
title: String
timeToCook: Int
premium: Boolean

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

input RecipeFilter {
id: CodexIdFilter
title: CodexStringFilter
timeToCook: CodexIntFilter
premium: CodexBooleanFilter

system: CodexSystemFilter
}

type Article implements CodexEntry {
id: String!
title: String
timeToRead: Int
premium: Boolean

system: CodexSystem
attrs: Json
relations: RecipeRelations
}

input RecipeFilter {
id: CodexIdFilter
title: CodexStringFilter
timeToRead: CodexIntFilter
premium: CodexBooleanFilter

system: CodexSystemFilter
}

"""
The generic entry filter
"""
input CodexEntryFilter {
id: CodexIdFilter
restaurant: RestaurantFilter
article: ArticleFilter
system: CodexSystemFilter
and: [CodexEntryFilter]
or: [CodexEntryFilter]
}

Let's say you want to have all entries that contain the keyword Codex in the title. You can perform this kind of filtering without know the exact fields of the entries by using the generic entry collection method:

query {
entryCollection(
where: {
system: {
title: {
contains: "codex"
}
}
}
limit: 10
) {
items {
id
system {
title
publishedAt
}
... on Recipe {
title
timeToCook
}
... on Article {
title
timeToRead
}
}
}
}

If you need more advanced filtering based on model fields, than you can use the generated filters from each model respectively. Let's say we want to display all premium recipes or articles in our homepage.

query {
entryCollection(
where: {
or: [
{
recipe: {
premium: {
eq: true
}
}
},
{
article: {
premium: {
eq: true
}
}
}
]
}
limit: 10
) {
items {
id
system {
title
publishedAt
}
... on Recipe {
title
timeToCook
premium
}
... on Article {
title
timeToRead
premium
}
}
}
}

If you use any of the model filter inputs as a sub filter in the generic entry collection query, then Codex GraphQL API first checks if the entry belongs to that specific model before applying the filtering on the sub fields. That's why this kind of filtering are most useful by using the OR logical operator when you have to combine field filters from multiple models. Performing the above example with the AND logical operator will return no result, because one entry cannot belong to Recipe and Article filter at the same time.