4.1 KiB
4.1 KiB
| title | aliases | tags | sources | created | updated | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| GraphQL — Custom Queries and Mutations |
|
|
|
2026-05-15 | 2026-05-15 |
Overview
Payload exposes two config keys for adding custom GraphQL operations, both receiving (GraphQL, payload) as arguments:
| Config Path | Description |
|---|---|
graphQL.queries |
Function returning object of custom query definitions |
graphQL.mutations |
Function returning object of custom mutation definitions |
Critical: use the GraphQL and payload instances provided via arguments — never install your own graphql package alongside Payload.
Defining Custom Operations
import { buildConfig } from 'payload'
import myCustomQueryResolver from './graphql/queries/myCustomQuery/resolver'
export default buildConfig({
graphQL: {
queries: (GraphQL, payload) => ({
MyCustomQuery: {
type: new GraphQL.GraphQLObjectType({
name: 'MyCustomQuery',
fields: {
text: { type: GraphQL.GraphQLString },
someNumberField: { type: GraphQL.GraphQLFloat },
},
}),
args: {
argNameHere: {
type: new GraphQL.GraphQLNonNull(GraphQL.GraphQLString),
},
},
resolve: myCustomQueryResolver,
},
}),
},
})
Resolver Function
Resolvers receive four arguments:
async (obj, args, context, info) => {}
| Arg | Description |
|---|---|
obj |
Previous object — rarely used, usually discarded |
args |
Query/mutation arguments (must be declared in the operation first) |
context |
{ req, res } — gives access to payload, user, and other request state |
info |
Schema info + contextual data about the running operation |
Gotcha: set depth: 0 when returning data directly from the Local API so GraphQL can correctly resolve nested relationship values.
Useful Types & Utilities
import { GraphQLJSON, GraphQLJSONObject } from '@payloadcms/graphql/types'
import { GraphQL } from '@payloadcms/graphql/types'
import { buildPaginatedListType } from '@payloadcms/graphql/types'
buildPaginatedListType
Creates a paginated result type matching Payload's generated schema:
type: buildPaginatedListType(
'AuthorPosts', // must be unique
payload.collections['posts'].graphQL?.type, // GraphQL type for items
)
payload.collections[slug].graphQL
Access auto-generated types per collection:
graphQL?: {
type: GraphQLObjectType
paginatedType: GraphQLObjectType
JWT: GraphQLObjectType
versionType: GraphQLObjectType
whereInputType: GraphQLInputObjectType
mutationInputType: GraphQLNonNull<any>
updateMutationInputType: GraphQLNonNull<any>
}
Recommended File Structure
src/graphql/
queries/
index.ts
myCustomQuery/
index.ts
resolver.ts
mutations/
Key Takeaways
- Add custom ops via
graphQL.queries/graphQL.mutationsinbuildConfig— both are functions receiving(GraphQL, payload). - Never install
graphqlindependently — use the providedGraphQLargument to avoid version conflicts. - Resolver signature:
(obj, args, context, info)—context.reqcarriespayloadanduser. - Use
depth: 0in Local API calls inside resolvers to avoid double-population. - Re-use Payload's auto-generated types via
payload.collections[slug].graphQL— avoids type duplication. buildPaginatedListTypeproduces a Payload-compatible paginated response type.- Group all custom GraphQL logic under
src/graphql/— queries and mutations in separate sub-folders.
Related
- wiki/payloadcms/rest-api — custom endpoints via
endpointsarray - wiki/payloadcms/local-api —
payload.*calls usable inside resolvers - wiki/payloadcms/hooks — alternative extension point for business logic
- wiki/payloadcms/configuration — full
buildConfigreference
Source: raw/graphql__extending.md — https://payloadcms.com/docs/graphql/extending