Smooth API Accelerator generates JSON outputs from a source system and publishes them to Smooth CDN for faster delivery and lower origin load.
The source system remains the content and API source of truth. API Accelerator is responsible for scanning routes, deciding which ones should be synced, generating JSON files, and serving them through CDN URLs.
The current production integration is WordPress. The same model can be extended to other source systems later, but this documentation page describes the current WordPress plugin behavior.
Core model
- Discover routes that can be synced.
- Keep synced routes in a dedicated group separate from the rest of detected endpoints.
- Generate one or more JSON files per synced route.
- Serve those files from
https://cdn.smoothcdn.com/<user-slug>/<project-slug>/.... - Optionally upload synced JSONs as protected assets.
The WordPress plugin Smooth API Accelerator turns selected WP REST API endpoints into JSON files hosted on Smooth CDN.
Installation
- Download the plugin from Smooth API Accelerator.
- Install and activate it in WordPress.
- Open
Smooth API Accelerator -> Settingsin wp-admin.
Login and connection
The plugin supports two connection modes: an existing Smooth CDN account or guest mode.
- Choose the connection mode in
Settings. - Use
Log in to Smooth CDNfor account mode, or switch to guest mode and accept the policy. - After connection, the plugin stores the API key and creates or attaches a Smooth CDN project of type
api_accelerator.
If the status payload does not return another value, guest mode falls back to a default limit of50 JSON files.
Endpoint discovery and route selection
The endpoint screen keeps two tables:
Synced endpointsOther endpoints
The current flow is:
Run scan nowdiscovers GET endpoints and refreshes the local endpoint registry.- Newly detected endpoints appear in
Other endpoints. Sync selectedmoves selected entries into the synced group and queues an immediate background sync for those routes.- After that selection, the routes appear in
Synced endpoints. Sync endpoints nowruns a full sync for all currently synced endpoints.Unsync selectedremoves selected entries from the synced group and removes their remote JSON files from Smooth CDN.
Sync selected does not wait for the normal hourly schedule. The plugin queues a fast single WP-Cron event for the selected routes, usually with a short delay. Execution still depends on WP-Cron and the next request that triggers it, but it does not wait for the regular hourly cron.
Automatic refresh after content changes
The plugin automatically scans and syncs related routes after content changes affecting:
- posts
- terms and taxonomies
When a post changes, the plugin can refresh:
- the endpoint for that specific post
- the collection endpoint for that post type
- related taxonomy collection endpoints
- related term item endpoints
When a term changes, the plugin can refresh:
- the taxonomy collection endpoint
- the specific term endpoint
- related post collection endpoints
- related single post endpoints
These refreshes are also scheduled through WP-Cron with short-delay single events instead of waiting for the standard automatic scan interval.
Settings
The current WordPress plugin exposes these settings:
Add blocks field— adds a normalizedblocksfield when block parsing is possible.Remove content field— appears only whenAdd blocks fieldis enabled and removescontentonly ifblockswas actually added.Protected assets— uploads synced JSON files as protected assets instead of public assets.Collection sync page size— available values:10,25,50,100; default:50.Auto scan and sync— schedules the automatic full scan and sync recurrence: hourly, daily, or weekly.
Changing any of these settings forces sync invalidation and a faster full refresh:
Protected assetsAdd blocks fieldRemove content fieldCollection sync page size
After such a change, the plugin clears sync markers for previously synced routes and queues a faster full scan + sync through an immediate single WP-Cron event instead of waiting for the regular schedule.
Blocking original WordPress REST API
In Settings you can configure whether original WordPress REST GET endpoints should remain available:
No— do not block originalwp-jsonGET routes.Yes— block all eligible REST GET routes for non-logged-in users.Only synced ones— block only routes that are already synced to Smooth CDN.
Blocks output
When Add blocks field is enabled, the plugin adds a normalized blocks field to supported post-like payloads. The current block shape uses:
block_nameattrsinnerContentinner_blocks
The synced JSON does not use the old output shape with blockName, innerBlocks, orinnerHTML.
{
"id": 42,
"title": { "rendered": "Example page" },
"blocks": [
{
"block_name": "core/paragraph",
"attrs": {},
"innerContent": [
"<p>Hello world</p>"
],
"inner_blocks": []
}
]
}Practical note for core/navigation: if the block contains ref or legacynavigationMenuId, the plugin expands inner_blocks from the referenced wp_navigation post to avoid syncing an empty core/navigation wrapper.
Protected JSONs and file limits
Enable Protected assets when synced JSONs should not be exposed as public files. In that mode use a token-aware consumer to read them.
File limits are counted as physical JSON files. Paginated collections count as multiple files: one metadata file plus every page file.
Filtering requested JSONs
Synced JSON files can be filtered at request time with the _fields query parameter. Array payloads can also be filtered with normal query params such as id, slug, or other top-level keys.
https://cdn.smoothcdn.com/<user-slug>/<project-slug>/wp/v2/posts/page-1.json?_fields=id,slug,titleGET https://cdn.smoothcdn.com/<user-slug>/<project-slug>/wp/v2/posts/page-1.json?slug=hello-world&_fields=id,slug,titleField filtering works on top-level keys. Dot notation is normalized to the root field.
Pre-send hook
Use scdn_api_accelerator_pre_send_json to adjust payloads right before JSON encoding and upload. Returning WP_Error stops sync for the current output file.
The hook runs for regular endpoint JSONs and also for collection-specific outputs:
- collection metadata files
- individual collection page files
The context array can contain:
triggerhttp_statusroute_templatehandler_argsrepository_itemsync_file_kindfor collection outputspage_nofor collection page filestotal_pagesfor collection metadata and collection page filesper_pagefor collection metadata and collection page files
add_filter( 'scdn_api_accelerator_pre_send_json', function( $data, $route, $context ) {
if ( '/wp/v2/posts' === $route && ( $context['sync_file_kind'] ?? '' ) === 'collection_page' && is_array( $data ) ) {
foreach ( $data as $index => $item ) {
if ( ! is_array( $item ) ) {
continue;
}
unset( $data[ $index ]['class_list'], $data[ $index ]['meta'] );
}
}
if ( '/wp/v2/posts' === $route && ( $context['sync_file_kind'] ?? '' ) === 'collection_manifest' ) {
$data['generated_for'] = 'posts';
}
return $data;
}, 10, 3 );Unsync selected
Unsync selected does more than removing a local flag.
- It deletes synced JSON files from Smooth CDN.
- For collections, this includes the metadata file and all paginated collection pages.
- The local repository entry is reset to a detected state.
After unsync, the route goes back to Other endpoints instead of staying in the synced group.
Purge endpoints
Purge endpoints is a destructive maintenance action available in Settings.
- It deletes synced JSON files from Smooth CDN.
- Then it clears local endpoint data stored by the plugin.
- It also clears plugin scheduling and stored plugin state.
Use this action only when you want to wipe synced endpoint data and start from a clean state.
The JavaScript SDK is the recommended way to consume synced API Accelerator JSONs in apps that need route-aware resolution, field filtering, query filters, pagination, or protected asset access.
Installation
npm install @smoothcdn/api-accelerator-sdkBasic usage
Create a client with your Smooth CDN slugs and fetch data by route:
import { createApiClient } from "@smoothcdn/api-accelerator-sdk";
const client = createApiClient({
userSlug: "example-user",
projectSlug: "my-project"
});
const posts = await client.fetch("/wp/v2/posts");Fields, filtering, and pagination
Use fields to map to _fields, where to append top-level query filters, andpage when you want a specific collection page.
const postsPage2 = await client.fetch("/wp/v2/posts", {
fields: ["id", "title", "slug"],
where: {
slug: "hello-world"
},
page: 2
});Use page for paginated collection files.
Joins
Use join to concatenate JSON files into more dynamical collection.
const postsWithAuthors = await client.fetch("/wp/v2/posts", {
join: {
author: "/wp/v2/users/[author]"
},
});Query with token
For protected JSONs, pass a token when creating the client.
import { createApiClient } from "@smoothcdn/api-accelerator-sdk";
const client = createApiClient({
userSlug: "example-user",
projectSlug: "my-project",
token: process.env.SMOOTHCDN_TOKEN
});
const privatePosts = await client.fetch("/wp/v2/posts", {
page: 1,
});Framework adapters
The SDK also provides framework-specific adapters for the most common frontend runtimes.
Next.js
import { createApiClient } from "@smoothcdn/api-accelerator-sdk/next";
const next = createApiClient({
userSlug: "example-user",
projectSlug: "my-project",
token: process.env.SMOOTHCDN_TOKEN
});
export async function getStaticProps() {
return next.createStaticProps("/wp/v2/pages", { revalidate: 60 });
}
export async function getFeaturedPost() {
return next.getRouteData("/wp/v2/posts", {
fields: ["id", "title"],
where: { id: 123 },
cache: "force-cache",
next: {
revalidate: 300,
tags: ["posts", "featured-post"]
}
});
}Nuxt
import { createApiClient } from "@smoothcdn/api-accelerator-sdk/nuxt";
const nuxt = createApiClient({
userSlug: "example-user",
projectSlug: "my-project",
token: process.env.SMOOTHCDN_TOKEN
});
export default defineComponent({
setup() {
const requestFetch = useRequestFetch();
return nuxt.useRouteDataWithAutoKey(useAsyncData, "/wp/v2/posts", {
fetch: requestFetch,
asyncData: {
dedupe: "defer",
lazy: true
}
});
}
});Astro
import { createApiClient } from "@smoothcdn/api-accelerator-sdk/astro";
const astro = createApiClient({
userSlug: "example-user",
projectSlug: "my-project"
});
const loadPosts = astro.createLoader("/wp/v2/posts", {
fields: ["id", "title"]
});
const posts = await loadPosts({ fetch });SvelteKit
import { createApiClient } from "@smoothcdn/api-accelerator-sdk/sveltekit";
const sveltekit = createApiClient({
userSlug: "example-user",
projectSlug: "my-project"
});
export const load = sveltekit.createLoad("/wp/v2/posts", {
fields: ["id", "title"],
depends: ["smooth:posts"],
cacheControl: "public, max-age=60"
});Remix
import { json } from "@remix-run/node";
import { createApiClient } from "@smoothcdn/api-accelerator-sdk/remix";
const remix = createApiClient({
userSlug: "example-user",
projectSlug: "my-project",
token: process.env.SMOOTHCDN_TOKEN
});
export const loader = remix.createJsonLoader(json, "/wp/v2/posts", {
fields: ["id", "title"],
where: { id: 123 },
useRequestSignal: true
});