Independent Editorial DeskWordPress Releases, Builds, and Operations
Back to Archive
Hardening NotesImplementation Notes

WordPress register_post_meta Example: Expose Custom Fields to REST Safely

Register custom post meta safely for REST API and block editor workflows with schema, sanitization, auth callbacks, and testing steps.

Published

April 19, 2026

Reading Time

4 min read

Updated

April 19, 2026

Abstract metadata fields connected to a REST response panel for WordPress custom fields.
Control LedgerHardening Notes

Hardening Notes

Baselines, access reduction, and default settings that stand up in production.

Best For

Teams preparing, launching, or maintaining WordPress as a backend service in a production stack.

Primary Topics

Hardening NotesImplementation Notes

Editorial Focus

Control Ledger: Baselines, access reduction, and default settings that stand up in production. Updated on April 19, 2026.

Full Report

Last reviewed: April 19, 2026

Custom fields are one of the most useful parts of WordPress, but they become messy when they are not registered properly. In headless projects and block editor workflows, unregistered meta often leads to missing REST fields, unsafe values, inconsistent schemas, and frontend code that depends on private implementation details.

This guide shows a practical register_post_meta() example for exposing a custom field to the WordPress REST API safely. The same pattern works for normal posts and custom post types when the field is part of the public content model.

Who this guide is for

This article is for WordPress developers building custom fields for headless frontends, block editor components, custom post types, editorial metadata, or API-driven publishing workflows.

Why registered meta matters

Registering post meta gives WordPress a schema for the field. That schema tells WordPress the field type, whether it is single or multi-value, how to sanitize input, whether it appears in REST responses, and who can read or edit it. Without that contract, custom fields are easy to misuse.

Example: expose reading time to REST

This plugin registers a vulnwp_reading_time integer field for posts. It is visible in the REST API, sanitized as a positive integer, and protected by an authorization callback.

<?php
/**
 * Plugin Name: VulnWP Reading Time Meta
 * Description: Registers a REST-visible reading time field for posts.
 * Version: 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

add_action( 'init', 'vulnwp_register_reading_time_meta' );

function vulnwp_register_reading_time_meta() {
	register_post_meta(
		'post',
		'vulnwp_reading_time',
		array(
			'type'              => 'integer',
			'description'       => __( 'Estimated reading time in minutes.', 'vulnwp-meta' ),
			'single'            => true,
			'default'           => 0,
			'show_in_rest'      => true,
			'sanitize_callback' => 'absint',
			'auth_callback'     => 'vulnwp_can_access_reading_time_meta',
		)
	);
}

function vulnwp_can_access_reading_time_meta( $allowed, $meta_key, $post_id, $user_id, $cap, $caps ) {
	if ( 'edit_post_meta' === $cap || 'delete_post_meta' === $cap ) {
		return current_user_can( 'edit_post', $post_id );
	}

	return true;
}

The field appears inside the meta object of REST post responses when requested. For custom post types, make sure the post type supports custom fields and is visible in REST if it needs editor or API integration.

Test the REST response

curl -s 'https://example.com/wp-json/wp/v2/posts/123?_fields=id,slug,meta' | jq

A successful response should include a structure like this:

{
	"id": 123,
	"slug": "example-post",
	"meta": {
		"vulnwp_reading_time": 7
	}
}

Save meta from PHP

When updating registered meta from PHP, still validate the source of the value. Registration is not a replacement for request-level checks.

function vulnwp_update_reading_time( $post_id, $minutes ) {
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return false;
	}

	return update_post_meta(
		$post_id,
		'vulnwp_reading_time',
		absint( $minutes )
	);
}

Public fields vs private fields

Do not expose everything to REST just because a frontend can read it. Public editorial metadata like reading time, difficulty level, canonical source, product SKU, or documentation version may be fine. Secrets, internal notes, API keys, cost data, private user decisions, and moderation signals should not be exposed publicly.

If a field is needed only by authenticated editors, keep it protected and enforce permissions through auth_callback and the surrounding REST route or editor flow.

Field naming rules

Choose a meta key that is stable and specific. A generic key like reading_time may collide with another plugin or theme. A prefixed key such as vulnwp_reading_time is easier to audit and safer to expose to REST. Once a frontend depends on the key, changing it becomes a migration.

Private meta keys often start with an underscore. That can be useful for hiding fields from the classic Custom Fields UI, but do not assume the underscore alone is a security boundary. Visibility, editing, and REST behavior should be controlled by registration arguments and permissions.

Array and object fields

Scalar fields are easiest to register. If the meta value is an array or object and should appear in REST, define the schema explicitly. Otherwise WordPress cannot reliably validate the shape of the field.

register_post_meta(
	'post',
	'vulnwp_source_links',
	array(
		'type'         => 'array',
		'single'       => true,
		'show_in_rest' => array(
			'schema' => array(
				'type'  => 'array',
				'items' => array(
					'type' => 'string',
				),
			),
		),
	)
);

Production checklist

  • Register meta on init.
  • Use a stable, namespaced meta key.
  • Set type, single, default, and description.
  • Use a sanitization callback that matches the field type.
  • Expose only fields that should be available to the intended REST audience.
  • For custom post types, confirm REST and custom field support.
  • Document whether the field is editorial, operational, private, or public.

Testing workflow

  1. Register the field in a plugin and activate it on staging.
  2. Update a post with a test value from PHP, the editor, or a REST request.
  3. Request the post with _fields=id,slug,meta and confirm the value shape.
  4. Test invalid values and confirm sanitization behaves as expected.
  5. Test with a low-privilege user and confirm edit attempts are blocked.

Do not test only the happy path. Meta fields often break when values are empty, missing, typed incorrectly, or edited by users with fewer capabilities than administrators.

Common mistakes

  • Using generic meta keys. Prefix custom keys to avoid collisions.
  • Skipping auth_callback. Access rules should be explicit.
  • Exposing protected data. REST responses can become public content surfaces.
  • Changing field type later. Frontends and block editor code may depend on the schema.
  • Forgetting custom post type support. Meta may not behave as expected without the right post type configuration.

Related reading

This builds on the custom post type example and pairs well with the block.json custom block example when a block needs to read or write post metadata.

References and further reading

Popular Guides

Popular WordPress guides to read next.

These articles connect recurring production concerns: implementation details, updates, troubleshooting, recovery paths, and operational cleanup.

Continue Reading

More from the archive.

Diagnostic dashboard scene representing a WordPress Site Health review before major updates.
01Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Site Health Check Before Major Updates: What to Review First

A pre-update WordPress Site Health checklist covering loopbacks, connectivity, debug settings, and environment readiness.

Structured data and route review scene representing permalink validation after a WordPress migration.
02Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Permalink Checklist After Migration: Catch URL Problems Early

A post-migration WordPress permalink checklist for checking rewrite rules, post URLs, archives, and redirect noise.

Technical media workspace representing image preparation and optimization before upload to WordPress.
03Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Image Optimization Checklist: What to Fix Before Upload

A practical WordPress image optimization checklist covering dimensions, compression, formats, and Media settings before upload.