Skip to content

Custom endpoints – fluent-wp-client

Content typeAPI
Custom post type in wp/v2content('resource')
Custom taxonomy in wp/v2terms('resource')
Plugin/custom namespacerequest({ endpoint: '/wp-json/...' })
Full transport controlrequest(...)

Assume a CPT with rest_base: 'books'.

Reads
const books = wp.content('books');
const list = await books.list({ perPage: 20 });
const allBooks = await books.listAll();
const paged = await books.listPaginated({ page: 2, perPage: 25 });
const book = await books.item('my-book');
const embedded = await books.item('my-book', { embed: true });
CPT CRUD
const created = await books.create({ title: 'Book title', status: 'draft' });
await books.update(created.id, { status: 'publish' });
await books.delete(created.id, { force: true });

Validate custom endpoint payloads in application code after the request resolves:

Validate a CPT response in app code
import { z } from 'zod';
const bookSchema = z.object({
id: z.number(),
slug: z.string(),
status: z.string(),
type: z.literal('book'),
});
const rawBook = await wp.content('books').item('my-book');
const book = bookSchema.parse(rawBook);

Use WordPressCustomPost<T> or postLikeWordPressSchema when a CPT may omit title, content, or excerpt.

import type { WordPressCustomPost } from 'fluent-wp-client';
import { postLikeWordPressSchema } from 'fluent-wp-client/zod';
const rawArtifact = await wp.content('artifacts').item('test-artifact-001');
const artifact = postLikeWordPressSchema.parse(rawArtifact);
Extract custom taxonomy terms from an embedded CPT
import { getEmbeddedTerms, getEmbeddedAuthor } from 'fluent-wp-client';
const book = await books.item('test-book-001', { embed: ['author', 'wp:term'] });
const author = getEmbeddedAuthor(book);
const genres = getEmbeddedTerms(book, 'genre');

Use fluent-wp-client/blocks when the CPT exposes content.raw:

import { withBlocks } from 'fluent-wp-client/blocks';
const wpBlocks = withBlocks(wp);
const blocks = await wpBlocks.content('books').item('test-book-001').blocks().get();

Assume rest_base: 'genre'.

Reads and CRUD
const genres = wp.terms('genre');
const list = await genres.list({ perPage: 100 });
const allGenres = await genres.listAll();
const created = await genres.create({ name: 'Science Fiction' });
await genres.update(created.id, { name: 'Sci-Fi' });
await genres.delete(created.id, { force: true });
Direct transport
const { data, response } = await wp.request({
endpoint: '/wp-json/my-plugin/v1/sync',
method: 'POST',
body: { mode: 'delta' },
});

Use the same auth approach as core endpoints. See the auth guide.

  • WordPressClientError — base class for all runtime failures with kind, operation, endpoint, retryable
  • WordPressHttpError — HTTP failures with status, wpCode, wpMessage, responseBody
  • Use instanceof to narrow, or error.kind for serialization
  • Prefer schema validation for writes so regressions fail fast
  • TypeScript92%
  • PHP6%
  • JavaScript2%