How to Update Post Meta with WordPress REST API

This tutorial is an addition to my another tutorial about creating posts using REST API in WordPress, because in that post I didn’t mention how to work with meta fields. So now we’re going to add (or update) meta fields of a specific post with the help of REST API requests.

By the way, the whole process is similar when you work for example with term meta, not only with post meta.

If you don’t want to code, you could have a look at my Simple WP Crossposting plugin, it allows to publish and update posts with custom fields via REST API easily.

Registering Meta Fields in REST API

First of all let me remind you that we are working with two websites:

  • Site 1 – is the website where the post meta should be updated.
  • Site 2 – is the website which will interact with the first one with the REST API.

And our goal now is to register every custom field we are going to create or update with REST API. In order to do so we’re about to use register_meta() function, you can check its description in the official WordPress documentation.

The code below is for Site 1.

add_action( 'rest_api_init', function(){

	register_meta( 
		'post', 
		'event_location', 
		array(
			'type' => 'string',
			'single' => false,
			'show_in_rest' => true,
		)
	);
	
	register_meta( 
		'post', 
		'event_date', 
		array(
			'type' => 'string',
			'single' => true,
			'show_in_rest' => true,
		)
	);
	
} );

When working with register_meta() function you have to keep in mind a couple moments:

  • The first parameter of the function is post here, which means that our custom meta fields are for posts only (posts, pages or custom post types). If you need to use them for categories or post tags, this parameter value should be term.
  • If you know that your post may have multiple meta values (rows in the database) of a specific meta key, don’t forget to provide 'single' => false or just skip this parameter. In our case we’re going to provide multiple locations for event_location. Example:
Multiple post meta values for the same meta key
  • The last but not the least, type and show_in_rest parameters. These ones are dependent on each other. If you’re using array or object as type, you have to specify the whole array or object structure in show_in_rest parameter, check this example.

Meta fields in custom post types

It doesn’t relate to regular posts or pages, but when you’re registering a custom post type you should pay a special attention to supports argument. It should contain custom-fields value in it.

Example:

register_post_type(
	'rudr_post_type',
	array(
		
		/* some parameters will be here */
		
		'supports' => array( 'title', 'editor', 'custom-fields' ),
	)
);

Add or Update Post Meta with a REST API Request

Finally we’re going to use WordPress REST API to update post meta of a specific post. Don’t forget to provive $post_id, $login and $password variable, more about them here.

wp_remote_post(
		"https://WEBSITE-DOMAIN/wp-json/wp/v2/posts/{$post_id}",
		array(
			'headers' => array(
				'Authorization' => 'Basic ' . base64_encode( "$login:$password" )
			),
			'body' => array(
				// we're only updating two meta fields, nothing else
				'meta' => array(
					'event_location' => array( 'Athens', 'Lisbon' ),
					'event_date' => 'Tomorrow',
				),
			),
		)
);

And finally we have this:

WordPress REST API update post meta example

Difference between arrays in meta fields and multiple meta key values

The thing is that when we pass a meta field value as an array like this…

'body' => array(
	'meta' => array(
		'event_location' => array( 'Athens', 'Lisbon' ),
	),
),

…it can be used for completely different things:

  • multiple values (rows) in the database for the same meta key (like in our example)
  • or a single database rows which stores an array of values.

And how are we supposed to differentiate these two?

With the register_meta() function configuration of course! So with the same configuration we used above, this is our result in the database:

Multiple post meta values for the same meta key

But if we just slightly change the register_meta() arguments to this:

register_meta( 
	'post', 
	'event_location', 
	array(
		'type' => 'array',
		'single' => true,
		'show_in_rest' => array( 'schema' => array( 'type' => 'array', 'items' => array() ) ),
	)
);

Then we are going to have a completely different situation in the wp_postmeta table:

Single post meta value as an array
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X