Overview
ThemePlus exposes a read-only REST API endpoint that allows you to retrieve saved theme option values from outside WordPress — useful for headless WordPress setups, static site generators, external dashboards, or any JavaScript application that needs to read theme configuration at runtime.
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
By default the endpoint is public — no authentication is required to read options. If your theme options contain sensitive data you should restrict access. See Restricting Access below.
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
json
{
"primary_color": "#2271b1",
"secondary_color": "#646970",
"enable_preloader": true,
"header_layout": "standard",
"body_typography": {
"font-family": "Inter",
"font-weight": "400",
"font-size": "16px",
"line-height": "1.6",
"color": "#1e1e1e"
},
"social_links": {
"facebook": "https://facebook.com/yourpage",
"twitter": "",
"instagram": "https://instagram.com/yourhandle"
},
"hero_gallery": [42, 43, 44]
}
Usage Examples
Fetch all options with the browser Fetch API
javascript
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:
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
javascript
// 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'] );
if ( t['line-height'] ) root.style.setProperty( '--body-line-height', t['line-height'] );
if ( t['color'] ) root.style.setProperty( '--body-color', t['color'] );
}
}
applyThemeOptions();
Using with Next.js getStaticProps
javascript
// 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
javascript
// 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();
Restricting Access
To make the endpoint private — requiring authentication — add a permission callback in your theme’s functions.php:
php
add_filter( 'themeplus_rest_permission_callback', function( $callback ) {
return function() {
return current_user_can( 'manage_options' );
};
});
After adding this filter, unauthenticated requests will receive a 401 Unauthorized response.
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:
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
Notes
- The REST API endpoint returns values exactly as stored — Image fields return attachment IDs, not URLs. Resolve attachment URLs server-side before exposing them, or handle the ID-to-URL conversion in your frontend using the WordPress media REST API (
/wp-json/wp/v2/media/{id}). - For headless setups, consider caching the options response at the CDN or using ISR (Incremental Static Regeneration) to avoid hitting the WordPress REST API on every request.
- The endpoint returns all options including any that may contain user-generated content — always audit what your options contain before making the endpoint publicly accessible.
- REST API access requires WordPress permalinks to be set to anything other than Plain — go to Settings → Permalinks and save if
/wp-json/routes return 404.