GraphQL API
DynapiCMS generates a GraphQL API from your schema: every content type gets queries (read), mutations (create, update, delete), filtering, and sorting. No CRUD to write.
Endpoint: POST /cms/graphql. Playground: GET /cms/playground.
Authentication
Every API request requires a token or API key:
| Method | Header |
|---|---|
| JWT | Authorization: Bearer <jwt> |
| JWT (alias) | Authorization: Token <jwt> |
| API key | X-API-Key: <key> |
| Cookie | auth_token (from admin login) |
The API key is also accepted as a query parameter: ?api_key=<key>.
GraphQL naming
The type’s slug sets the API names. Slug blog-post produces:
| Name | Purpose |
|---|---|
blogPost(id, slug) |
Single record |
blogPosts(where, orderBy, limit, offset) |
List |
blogPostsCount(where) |
Count |
createBlogPost(input) |
Create |
updateBlogPost(id, input) |
Update |
deleteBlogPost(id) |
Delete |
Reading a single record
query {
blogPost(slug: "hello-world") {
id title status
author { id name }
}
}
The slug argument is only available when the type has a slug field
marked Unique. Otherwise, use id:
query {
blogPost(id: "550e8400-e29b-41d4-a716-446655440000") {
title
}
}
Localized fields return the value for the locale argument or the
X-Locale header:
query {
blogPost(slug: "hello", locale: "ru") {
title
}
}
Reading a list
query {
blogPosts(limit: 10, offset: 0) {
id title status
}
}
limit defaults to 10, max 100. offset is for pagination.
The list accepts where (filter), orderBy (sort), search (text search),
and a separate blogPostsCount(where) for the total count. The full
operator reference, combinators, and sorting details are on the
Filtering & sorting page.
Example with filter and sort:
query {
blogPosts(
where: { status: { eq: "published" } }
orderBy: [{ field: PUBLISHED_AT, direction: DESC }]
) { id title }
}
Creating a record
mutation {
createBlogPost(input: {
title: "New post"
slug: "new-post"
status: "draft"
}) {
id title slug
}
}
Required fields must be filled. References are passed by ID:
mutation {
createBlogPost(input: {
title: "With author"
author: "550e8400-e29b-41d4-a716-446655440000"
}) { id }
}
Localized fields are passed as a locale map:
mutation {
createBlogPost(input: {
title: { ru: "Привет", en: "Hello" }
}) { id }
}
Updating a record
Partial update — only the supplied fields change:
mutation {
updateBlogPost(
id: "550e8400-e29b-41d4-a716-446655440000"
input: { status: "published" }
) { id status }
}
Deleting a record
mutation {
deleteBlogPost(id: "550e8400-e29b-41d4-a716-446655440000")
}
Returns true on success.
Uploading media
A dedicated mutation for files (multipart upload):
mutation($file: Upload!) {
uploadMedia(file: $file) { id name url mimeType fileSize type }
}
The file is sent as multipart form data. Returns a ready media record
with ID and URL.
What’s next
- Filtering & sorting — detailed operator reference.
- Webhooks — entity lifecycle events.
- First content type — how to create the type that generates this API.