GraphQL Queries
Learn how to query your content using GraphQL with the Contensa.ai SDK
What is GraphQL?
GraphQL is a query language that lets you request exactly the data you need. Unlike REST, you specify which fields you want in the response, making it more efficient.
const sdk = new MybeSDK({
apiKey: 'your-api-key',
baseUrl: 'https://api.yoursite.com/v1/api/v1'
});
const result = await sdk.graphql(
PROJECT_ID,
`query {
blog-postCollection {
items {
id
slug
data {
title
content
}
}
}
}`
);How to Get Field Names
- Go to Dashboard → Content Model → Select your content type
- Hover over any field name and click the copy icon to copy individual field names
- Or click the menu (⋮) → "Copy GraphQL Fields" to copy all fields at once
- Paste the field names into your GraphQL query
Understanding Field Types
Different field types require different query syntax. Here's how to query each type:
1. Regular Fields (Text, Number, Boolean, Date)
Different field types require different query syntax. Here's how to query each type:
query {
blog-postCollection {
items {
data {
title # Text field
content # Rich text field
publishedDate # Date field
viewCount # Number field
isPublished # Boolean field
}
}
}
}2. Reference Fields (Single Reference)
Reference fields point to another content entry. They return a ContentEntry type where data is a JSON scalar.
query {
blog-postCollection {
items {
data {
title
author {
id
slug
data { # ❌ Error!
name
email
}
}
}
}
}
}Error: Field "data" must not have a selection since type "JSON" has no subfields
query {
blog-postCollection {
items {
data {
title
author { # ✅ Query data as scalar
id
slug
data # Returns full JSON object
}
}
}
}
}The data field returns the entire JSON object with all author fields
3. References-Many Fields (Array of References)
These fields return an array of ContentEntry objects. Query data as a scalar to get the full JSON.
query {
blog-postCollection {
items {
data {
title
categories { # Array of references
id
slug
data # Returns full JSON for each category
}
tags { # Another array
id
slug
data # Returns full JSON for each tag
}
}
}
}
}Each data field will contain the complete JSON object with all fields for that entry.
4. Media Fields
Media fields return file information and need subfield selection.
query {
blog-postCollection {
items {
data {
title
featuredImage { # Media field
id
filename
url
mimeType
size
}
}
}
}
}Complete Example
Here's a real-world example combining all field types:
const sdk = new MybeSDK({
apiKey: 'your-api-key',
baseUrl: 'https://api.yoursite.com/v1/api/v1'
});
const PROJECT_ID = 'your-project-id';
const result = await sdk.graphql(
PROJECT_ID,
`query {
blog-postCollection(limit: 10) {
items {
id
slug
status
contentType {
id
name
slug
}
data {
# Regular fields
title
content
publishedDate
viewCount
# Reference field (single)
# Returns ContentEntry where data is a JSON scalar
author {
id
slug
data # Gets full author JSON: { name, email, bio, ... }
}
# References-many field (array)
# Each item is a ContentEntry with data as JSON scalar
categories {
id
slug
data # Gets full category JSON: { categoryName, ... }
}
# Media field
featuredImage {
id
url
filename
}
}
created_at
updated_at
}
total
}
}`
);
console.log(result);Using Variables
Variables make your queries dynamic and reusable:
const result = await sdk.graphql(
PROJECT_ID,
`query GetPosts($status: String!, $limit: Int!) {
blog-postCollection(
where: { status: $status }
limit: $limit
) {
items {
id
slug
data {
title
}
}
total
}
}`,
{
status: "published",
limit: 10
}
);Filtering Content
Use the where clause to filter results:
// Filter by slug
query {
blog-postCollection(where: { slug: "my-first-post" }) {
items {
id
data { title }
}
}
}
// Filter by status
query {
blog-postCollection(where: { status: "published" }) {
items {
id
data { title }
}
}
}
// Filter by locale
query {
blog-postCollection(where: { locale: "en-US" }) {
items {
id
locale
data { title }
}
}
}
// Filter by custom field (with variables)
query GetByCategory($categoryName: String!) {
blog-postCollection(where: { category: $categoryName }) {
items {
data { title }
}
}
}Filtering by Locale
Filter content by locale to retrieve entries in specific languages. This is useful for building multilingual applications where you need to fetch content in a particular language.
// Get all Bangla (Bengali) content
query {
blog-postCollection(where: { locale: "bn-BD" }) {
items {
id
locale
slug
data {
title
content
}
}
total
}
}
// Get all English content
query {
blog-postCollection(where: { locale: "en-US" }) {
items {
id
locale
data { title }
}
}
}
// Combine locale with status filter
// Get only published content in a specific locale
query {
blog-postCollection(
where: {
locale: "bn-BD"
status: "published"
}
) {
items {
id
locale
status
data {
title
}
published_at
}
}
}
// Using variables for dynamic locale filtering
query GetByLocale($locale: String!, $status: String!) {
blog-postCollection(
where: {
locale: $locale
status: $status
}
limit: 10
) {
items {
id
locale
status
data {
title
content
}
}
total
}
}
// Example usage with the SDK:
const result = await sdk.graphql(
PROJECT_ID,
`query GetByLocale($locale: String!, $status: String!) {
blog-postCollection(
where: {
locale: $locale
status: $status
}
) {
items {
id
locale
data { title }
}
}
}`,
{
locale: "bn-BD",
status: "published"
}
);Locale Codes
Common locale codes follow the format language-REGION:
en-US- English (United States)bn-BD- Bangla (Bangladesh)es-ES- Spanish (Spain)fr-FR- French (France)de-DE- German (Germany)
Pagination
Control how many items are returned and skip items:
// Get first 10 items
query {
blog-postCollection(limit: 10) {
items { id }
total
}
}
// Skip first 10, get next 10 (page 2)
query {
blog-postCollection(limit: 10, skip: 10) {
items { id }
total
limit
skip
}
}Common Errors & Solutions
Error: "must not have a selection since type JSON has no subfields"
Cause: You're trying to query subfields of data on a reference field, but reference fields return ContentEntry where data is a JSON scalar.
Solution: Query data without curly braces:
# Wrong
author {
id
data {
name # ❌ Can't query subfields
}
}
# Correct
author {
id
slug
data # ✅ Returns full JSON: { name, email, ... }
}Error: "must have a selection of subfields"
Cause: You're trying to query a reference or media field without specifying any subfields.
Solution: Add subfields inside curly braces:
# Wrong
author # ❌ No subfields
# Correct
author {
id
slug
data
}Error: "Cannot query field 'fieldName'"
Cause: The field name doesn't exist in your content type.
Solution: Check your field names in the dashboard and copy them using the copy button.
💡 Pro Tips
- Always include
contentType.slugto know which content type each entry belongs to - Use the dashboard's "Copy GraphQL Fields" button to avoid typos
- Reference fields return
ContentEntryobjects - querydataas a scalar (no curly braces) to get the full JSON - Regular fields on your main content type have structured
data- you can query specific subfields - Start with simple queries and add fields incrementally
- Use variables for dynamic values instead of hardcoding them