Skip to content

REST API

Access theme options programmatically via the WordPress REST API.

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.

On This Page