GraphQL Mutations
Mutations allow you to create, update, and delete content in your StormyCMS site. All mutations require authentication with your site API key and client ID.
Authentication
Don't forget to include your authentication headers in every request:
headers: { 'Content-Type': 'application/json', 'x-site-api-key': 'YOUR_SITE_API_KEY', 'x-client-id': 'YOUR_CLIENT_ID'}Page Mutations
Create a New Page
Create a new page with metadata and components.
mutation CreatePage( $meta: MetadataInput! $components: [ComponentInput!]! $layoutId: ID! $componentIds: [ID!]!) { create_page( meta: $meta components: $components layout_id: $layoutId component_ids: $componentIds ) { id meta { title description keywords } layout_id components { id name text } }}Example:
const response = await fetch('https://api.stormycms.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-site-api-key': 'YOUR_SITE_API_KEY', 'x-client-id': 'YOUR_CLIENT_ID' }, body: JSON.stringify({ query: ` mutation CreatePage($meta: MetadataInput!, $layoutId: ID!) { create_page( meta: $meta components: [] layout_id: $layoutId component_ids: [] ) { id meta { title description } } } `, variables: { meta: { title: "My New Page", description: "A page created with the StormyCMS API", keywords: ["cms", "api", "content"] }, layoutId: "layout_123" } })});Update an Existing Page
Update a page's metadata, components, or layout.
mutation UpdatePage( $id: ID! $meta: MetadataInput! $components: [ComponentInput!]! $layoutId: ID! $componentIds: [ID!]!) { update_page( id: $id meta: $meta components: $components layout_id: $layoutId component_ids: $componentIds ) { id meta { title description keywords } layout_id updated_at }}Example:
const response = await fetch('https://api.stormycms.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-site-api-key': 'YOUR_SITE_API_KEY', 'x-client-id': 'YOUR_CLIENT_ID' }, body: JSON.stringify({ query: ` mutation UpdatePage($id: ID!, $meta: MetadataInput!) { update_page( id: $id meta: $meta components: [] layout_id: "layout_123" component_ids: [] ) { id meta { title description } } } `, variables: { id: "page_456", meta: { title: "Updated Page Title", description: "This page has been updated", keywords: ["updated", "content"] } } })});Delete a Page
Permanently remove a page from your site.
mutation DeletePage($id: ID!) { delete_page(id: $id) { id meta { title } }}Example:
const response = await fetch('https://api.stormycms.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-site-api-key': 'YOUR_SITE_API_KEY', 'x-client-id': 'YOUR_CLIENT_ID' }, body: JSON.stringify({ query: ` mutation DeletePage($id: ID!) { delete_page(id: $id) { id meta { title } } } `, variables: { id: "page_456" } })});Layout Mutations
Create a New Layout
Create a reusable layout for your pages.
mutation CreateLayout( $name: String! $components: [ComponentInput!]! $componentIds: [ID!]!) { create_layout( name: $name components: $components component_ids: $componentIds ) { id name components { id name } created_at }}Example:
const response = await fetch('https://api.stormycms.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-site-api-key': 'YOUR_SITE_API_KEY', 'x-client-id': 'YOUR_CLIENT_ID' }, body: JSON.stringify({ query: ` mutation CreateLayout($name: String!) { create_layout( name: $name components: [] component_ids: [] ) { id name } } `, variables: { name: "Blog Post Layout" } })});Update an Existing Layout
Modify a layout's structure or components.
mutation UpdateLayout( $id: ID! $name: String! $components: [ComponentInput!]! $componentIds: [ID!]!) { update_layout( id: $id name: $name components: $components component_ids: $componentIds ) { id name updated_at }}Delete a Layout
Remove a layout from your system.
mutation DeleteLayout($id: ID!) { delete_layout(id: $id) { id name }}Working with Components
Adding Components to a Page
When creating or updating a page, you can include components:
const components = [ { name: "Header", text: [ { locale: "en", value: "Welcome to My Page" } ], props: [ { key: "className", translations: [ { locale: "en", value: "page-header" } ] } ] }, { name: "TextBlock", text: [ { locale: "en", value: "This is the main content of the page." } ] }];Nested Components
Components can have child relationships:
const containerComponent = { name: "Container", child_ids: ["child_1", "child_2"], components: [ { id: "child_1", name: "Sidebar", text: [{ locale: "en", value: "Sidebar content" }] }, { id: "child_2", name: "MainContent", text: [{ locale: "en", value: "Main content" }] } ]};Error Handling
Always handle potential errors in your mutations:
async function executeMutation(query, variables) { const response = await fetch('https://api.stormycms.com/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-site-api-key': 'YOUR_SITE_API_KEY', 'x-client-id': 'YOUR_CLIENT_ID' }, body: JSON.stringify({ query, variables }) });
if (!response.ok) { if (response.status === 401) { throw new Error('Authentication failed: Check your API key and client ID'); } else if (response.status === 403) { throw new Error('Permission denied: You may not have the required permissions'); } else if (response.status === 429) { throw new Error('Rate limit exceeded: Try again later'); } throw new Error(`HTTP error! status: ${response.status}`); }
const result = await response.json();
if (result.errors) { const errorMessages = result.errors.map(err => err.message).join(', '); throw new Error(`GraphQL errors: ${errorMessages}`); }
return result.data;}Best Practices
- Validate input - Always validate data before sending mutations
- Handle errors gracefully - Provide clear error messages to users
- Use transactions - Group related mutations when possible
- Track changes - Keep a record of who made changes and when
- Backup data - Especially before bulk operations
Permissions
- Site Admin - Can create, update, and delete pages
- Site Editor - Can update existing pages (but not delete)
- Site Contributor - Read-only access
Next Steps
- Learn about GraphQL Queries to fetch data
- Check the API Reference for complete type definitions
- View Examples for practical implementations
Last updated: 2/27/26, 3:48 AM