Overview
ThemePlus exposes a full REST API under the themeplus/v1namespace that allows you to get, save, and reset theme option values programmatically — useful for headless WordPress setups, static site generators, external dashboards, or any application that needs to read or write theme configuration. The API is available as soon as ThemePlus is active.
The endpoint is registered under the themeplus/v1 namespace and is available as soon as ThemePlus is active.
Endpoint
GET /wp-json/themeplus/v1/options
Returns all saved theme options as a JSON object.
Authentication
All ThemePlus REST endpoints require authentication. Requests without valid credentials receive a 403 Forbidden response.
For browser-based requests (the ThemePlus admin panel itself), WordPress handles authentication automatically via cookie auth and the X-WP-Nonce header.
For external requests, use WordPress Application Passwords (WordPress 5.6+):
const credentials = btoa( 'username:application_password' );
const response = await fetch( '/wp-json/themeplus/v1/options', {
headers: {
'Authorization': `Basic ${credentials}`,
},
});
The required capability is edit_theme_options by default. This can be changed via themeplus_framework_config(['capability' => 'manage_options']).
| Method | Endpoint | Description | Auth required |
|---|---|---|---|
GET | /wp-json/themeplus/v1/options | Get all saved options | ✅ |
POST | /wp-json/themeplus/v1/options | Save all options | ✅ |
POST | /wp-json/themeplus/v1/options/reset | Reset all options to defaults | ✅ |
POST | /wp-json/themeplus/v1/options/reset-section | Reset a single section to defaults | ✅ |
GET | /wp-json/themeplus/v1/config | Get full sections and fields config | ✅ |
GET | /wp-json/themeplus/v1/dev-panel | Field metadata and statistics | ✅ dev mode only |
Response Format
A successful request returns a JSON object where each key is an option ID and each value is the saved option value — matching the same structure returned by themeplus_get_option() in PHP.
Example response
{
"primary_color": "#2271b1",
"enable_preloader": true,
"header_layout": "standard",
"body_typography": {
"font-family": "Inter",
"font-weight": "400",
"font-size": "16",
"line-height": "1.6",
"letter-spacing": "0",
"text-transform": "none",
"font-style": "normal",
"subsets": ["latin"]
},
"logo_image": {
"id": 42,
"url": "https://example.com/wp-content/uploads/logo.png",
"width": 300,
"height": 100,
"alt": "My Logo",
"title": "Logo"
},
"social_links": [
{ "platform": "github", "url": "https://github.com/yourhandle" },
{ "platform": "instagram", "url": "https://instagram.com/yourhandle" }
],
"hero_gallery": [
{ "id": 42, "url": "https://example.com/wp-content/uploads/image-1.jpg", "alt": "" },
{ "id": 43, "url": "https://example.com/wp-content/uploads/image-2.jpg", "alt": "Second image" }
]
}Usage Examples
Fetch all options with the browser Fetch API
const response = await fetch( '/wp-json/themeplus/v1/options' );
const options = await response.json();
console.log( options.primary_color ); // '#2271b1'
console.log( options.header_layout ); // 'standard'Fetch a single option value
ThemePlus does not expose individual option endpoints by default. Filter the full response in JavaScript:
async function getThemeOption( key, fallback = null ) {
const response = await fetch( '/wp-json/themeplus/v1/options' );
const options = await response.json();
return options[ key ] ?? fallback;
}
const color = await getThemeOption( 'primary_color', '#000000' );
document.documentElement.style.setProperty( '--color-primary', color );Applying options to a headless frontend
// Fetch theme options and inject as CSS custom properties
async function applyThemeOptions() {
const res = await fetch('https://your-wp-site.com/wp-json/themeplus/v1/options');
const options = await res.json();
const root = document.documentElement;
if (options.primary_color) root.style.setProperty('--color-primary', options.primary_color);
if (options.secondary_color) root.style.setProperty('--color-secondary', options.secondary_color);
if (options.body_typography) {
const t = options.body_typography;
if (t['font-family']) root.style.setProperty('--body-font-family', `"${t['font-family']}", sans-serif`);
if (t['font-size']) root.style.setProperty('--body-font-size', t['font-size'] + 'px');
if (t['line-height']) root.style.setProperty('--body-line-height', t['line-height']);
if (t['font-weight']) root.style.setProperty('--body-font-weight', t['font-weight']);
if (t['letter-spacing']) root.style.setProperty('--body-letter-spacing', t['letter-spacing'] + 'px');
if (t['text-transform']) root.style.setProperty('--body-text-transform', t['text-transform']);
}
}
applyThemeOptions();Using with Next.js getStaticProps
// pages/index.js
export async function getStaticProps() {
const res = await fetch( `${process.env.WP_API_URL}/wp-json/themeplus/v1/options` );
const options = await res.json();
return {
props: { themeOptions: options },
revalidate: 60, // ISR — revalidate every 60 seconds
};
}
export default function Home({ themeOptions }) {
return (
<main style={{ '--color-primary': themeOptions.primary_color }}>
{/* page content */}
</main>
);
}Using with WP REST API authentication for private options
// Authenticated request using Application Passwords (WordPress 5.6+)
const credentials = btoa( 'username:application_password' );
const response = await fetch( '/wp-json/themeplus/v1/options', {
headers: {
'Authorization': `Basic ${credentials}`,
},
});
const options = await response.json();Changing the Required Capability
By default all endpoints require edit_theme_options. To require a stricter capability, set it in your framework config:
themeplus_framework_config([
'capability' => 'manage_options',
]);
This affects both the admin panel visibility and all REST API endpoints — they always use the same configured capability.
Registering a Custom Endpoint
If you need a custom endpoint that returns only a subset of options — for example to expose only public-safe values — register your own REST route in functions.php:
add_action( 'rest_api_init', function() {
register_rest_route( 'mytheme/v1', '/public-options', [
'methods' => 'GET',
'callback' => function() {
$options = themeplus_get_option();
// Return only safe, public-facing values
return rest_ensure_response([
'primary_color' => $options['primary_color'] ?? '',
'secondary_color' => $options['secondary_color'] ?? '',
'social_links' => $options['social_links'] ?? [],
'header_layout' => $options['header_layout'] ?? 'standard',
]);
},
'permission_callback' => '__return_true',
]);
});GET /wp-json/mytheme/v1/public-options