REST API

The REST API is a fully functional HTTP client that allows you to interact with your Documents in a RESTful manner. It supports all CRUD operations and is equipped with automatic pagination, depth, and sorting. All Payload API routes are mounted and prefixed to your config's routes.api URL segment (default: /api).

REST query parameters:

  • depth - automatically populates relationships and uploads
  • locale - retrieves document(s) in a specific locale
  • fallback-locale - specifies a fallback locale if no locale value exists

Collections

Each collection is mounted using its slug value. For example, if a collection's slug is users, all corresponding routes will be mounted on /api/users.

Note: Collection slugs must be formatted in kebab-case

All CRUD operations are exposed as follows:

OperationMethodPathView
FindGET/api/{collection-slug}
Find By IDGET/api/{collection-slug}/{id}
CountGET/api/{collection-slug}/count
CreatePOST/api/{collection-slug}
UpdatePATCH/api/{collection-slug}
Update By IDPATCH/api/{collection-slug}/{id}
DeleteDELETE/api/{collection-slug}
Delete by IDDELETE/api/{collection-slug}/{id}

Auth Operations

Auth enabled collections are also given the following endpoints:

OperationMethodPathView
LoginPOST/api/{user-collection}/login
LogoutPOST/api/{user-collection}/logout
UnlockPOST/api/{user-collection}/unlock
RefreshPOST/api/{user-collection}/refresh-token
Verify UserPOST/api/{user-collection}/verify/{token}
Current UserGET/api/{user-collection}/me
Forgot PasswordPOST/api/{user-collection}/forgot-password
Reset PasswordPOST/api/{user-collection}/reset-password

Globals

Globals cannot be created or deleted, so there are only two REST endpoints opened:

OperationMethodPathView
Get GlobalGET/api/globals/{global-slug}
Update GlobalPOST/api/globals/{global-slug}

Preferences

In addition to the dynamically generated endpoints above Payload also has REST endpoints to manage the admin user preferences for data specific to the authenticated user.

OperationMethodPathView
Get PreferenceGET/api/payload-preferences/{key}
Create PreferencePOST/api/payload-preferences/{key}
Delete PreferenceDELETE/api/payload-preferences/{key}

Custom Endpoints

Additional REST API endpoints can be added to your application by providing an array of endpoints in various places within a Payload Config. Custom endpoints are useful for adding additional middleware on existing routes or for building custom functionality into Payload apps and plugins. Endpoints can be added at the top of the Payload Config, collections, and globals and accessed respective of the api and slugs you have configured.

Each endpoint object needs to have:

PropertyDescription
pathA string for the endpoint route after the collection or globals slug
methodThe lowercase HTTP verb to use: 'get', 'head', 'post', 'put', 'delete', 'connect' or 'options'
handlerA function or array of functions to be called with req, res and next arguments. Next.js
rootWhen true, defines the endpoint on the root Next.js app, bypassing Payload handlers and the routes.api subpath. Note: this only applies to top-level endpoints of your Payload Config, endpoints defined on collections or globals cannot be root.
customExtension point for adding custom data (e.g. for plugins)

Example:

1
import { CollectionConfig } from 'payload'
2
3
// a collection of 'orders' with an additional route for tracking details, reachable at /api/orders/:id/tracking
4
export const Orders: CollectionConfig = {
5
slug: 'orders',
6
fields: [
7
/* ... */
8
],
9
endpoints: [
10
{
11
path: '/:id/tracking',
12
method: 'get',
13
handler: async (req) => {
14
const tracking = await getTrackingInfo(req.params.id)
15
16
if (!tracking) {
17
return Response.json({ error: 'not found' }, { status: 404})
18
}
19
20
return Response.json({
21
message: `Hello ${req.routeParams.name as string} @ ${req.routeParams.group as string}`,
22
})
23
},
24
},
25
{
26
path: '/:id/tracking',
27
method: 'post',
28
handler: async (req) => {
29
// `data` is not automatically appended to the request
30
// if you would like to read the body of the request
31
// you can use `data = await req.json()`
32
const data = await req.json()
33
await req.payload.update({
34
collection: 'tracking',
35
data: {
36
// data to update the document with
37
}
38
})
39
return Response.json({
40
message: 'successfully updated tracking info'
41
})
42
}
43
}
44
],
45
}

Helpful tips

req.data

Data is not automatically appended to the request. You can read the body data by calling await req.json().

Or you could use our helper function that mutates the request and appends data and file if found.

1
import { addDataAndFileToRequest } from '@payloadcms/next/utilities'
2
3
// custom endpoint example
4
{
5
path: '/:id/tracking',
6
method: 'post',
7
handler: async (req) => {
8
await addDataAndFileToRequest(req)
9
await req.payload.update({
10
collection: 'tracking',
11
data: {
12
// data to update the document with
13
}
14
})
15
return Response.json({
16
message: 'successfully updated tracking info'
17
})
18
}
19
}

req.locale & req.fallbackLocale

The locale and the fallback locale are not automatically appended to custom endpoint requests. If you would like to add them you can use this helper function.

1
import { addLocalesToRequestFromData } from '@payloadcms/next/utilities'
2
3
// custom endpoint example
4
{
5
path: '/:id/tracking',
6
method: 'post',
7
handler: async (req) => {
8
await addLocalesToRequestFromData(req)
9
// you now can access req.locale & req.fallbackLocale
10
return Response.json({ message: 'success' })
11
}
12
}

Method Override for GET Requests

Payload supports a method override feature that allows you to send GET requests using the HTTP POST method. This can be particularly useful in scenarios when the query string in a regular GET request is too long.

How to Use

To use this feature, include the X-HTTP-Method-Override header set to GET in your POST request. The parameters should be sent in the body of the request with the Content-Type set to application/x-www-form-urlencoded.

Example

Here is an example of how to use the method override to perform a GET request:

Using Method Override (POST)

1
const res = await fetch(`${api}/${collectionSlug}`, {
2
method: 'POST',
3
credentials: 'include',
4
headers: {
5
'Accept-Language': i18n.language,
6
'Content-Type': 'application/x-www-form-urlencoded',
7
'X-HTTP-Method-Override': 'GET',
8
},
9
body: qs.stringify({
10
depth: 1,
11
locale: 'en',
12
}),
13
})

Equivalent Regular GET Request

1
const res = await fetch(`${api}/${collectionSlug}?depth=1&locale=en`, {
2
method: 'GET',
3
credentials: 'include',
4
headers: {
5
'Accept-Language': i18n.language,
6
},
7
})
Next

GraphQL Overview