I need to sync a Rails database with a WordPress db, using API calls. Each Rails record creates one wp_post, and up to 15 wp_postmeta records. I can loop over the data that becomes the postmetas, but that takes a long time. I assume most of that time comes from making so many API calls, so I'm trying to cut that number down to one.

For a single record, I've cobbled this URL together, which works:


I tried putting the following into my functions.php file to create a custom route:

function bulk_import_postmeta($request) {
    $metas = $request->get_param("meta");
  if (is_array($metas)) {
    foreach($metas as $meta){
      update_post_meta($meta[0], $meta[1], $meta[2]);

add_action( 'rest_api_init', function() {
    register_rest_route('/imports/v1', '/postmeta_bulk/',
            'methods' => 'POST',
            'callback' => 'bulk_import_postmeta',
            'args' => array('meta' => array('required' => true))));

—but I don't know how I need to encode the URL when I call it, and I don't know if it would work if I did.

My question is, then: given a post_id, what API call can I make to bulk create these wp_postmeta records?

  • Can you dump to csv and use eg wp-cli?
    – birgire
    Commented Jul 28, 2022 at 15:12
  • @birgire, the process needs to be automatic and cron-tabbable.
    – amp108
    Commented Jul 28, 2022 at 16:04

1 Answer 1


We can use the existing meta property (see docs) to add multiple meta fields (in a JSON format) when we create a post via POST method:

POST: example.com/wp-json/wp/v2/posts/

Body payload:

    "title": "My title",
    "content": "My content",
    "meta": {"myfield1":"myvalue1", "myfield2":"myvalue2"}

or when we want to update a post with ID 123:

POST: example.com/wp-json/wp/v2/posts/123

Body payload:

    "title": "My title 2",
    "content": "My content 2",
    "meta": {"myfield1":"myvalue11", "myfield2":"myvalue22"}

Note that we will have to register the meta fields with corresponding schema properties (see docs and docs), for example registering meta field myfield1 as a string with:

add_action( 'rest_api_init', function() {
         'post', // post type
         'myfield1', // meta key
             'single'       => true,
             'type'         => 'string',
             'show_in_rest' => array(
                 'schema' => array(
                     'type'    => 'string',
                     'default' => '',
} );

We can see how the meta scheme property is checked in the rest posts controller:

if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) {
    $meta_update = $this->meta->update_value( $request['meta'], $post_id );

    if ( is_wp_error( $meta_update ) ) {
        return $meta_update;


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.