O valor está gravado, o wp post meta get 123 rt_tempo_leitura devolve o número, e mesmo assim /wp-json/wp/v2/posts/123 volta com meta vazio. Não é bug do WordPress 6.9: a REST API só entrega chave que passou por register_post_meta() com show_in_rest. O que não foi registrado ela nem enxerga.
O registro completo
add_action( 'init', function () {
register_post_meta( 'post', 'rt_tempo_leitura', [
'type' => 'integer',
'single' => true,
'default' => 0,
'show_in_rest' => true,
'sanitize_callback' => 'absint',
'auth_callback' => function () {
return current_user_can( 'edit_posts' );
},
] );
} );Três detalhes que eu já vi derrubarem isso. O registro roda no init sem nenhum if ( is_admin() ) em volta, porque requisição REST não é tela de admin. O single em true faz o campo sair como valor escalar em vez de array. E o type tem que bater com o que você grava: declarou integer e salvou string, o schema converte ou descarta na saída.
Array trava; object sai vazio
register_post_meta( 'post', 'rt_autores_extras', [
'type' => 'array',
'single' => true,
'show_in_rest' => [
'schema' => [
'type' => 'array',
'items' => [ 'type' => 'string' ],
],
],
] );O núcleo é literal aqui: com type array e sem show_in_rest['schema']['items'], o register_post_meta() dispara _doing_it_wrong e retorna false — a chave nem chega a existir para a REST. Com type object não existe essa trava, mas sem properties no schema a resposta sai com o objeto vazio.
O auth_callback manda na escrita e tem um default que pega gente desprevenida: quando você omite, o WordPress consulta is_protected_meta() e toda chave começada com underline cai em __return_false. Aí o PUT volta com rest_cannot_update enquanto a leitura continua funcionando, e o bug parece de permissão do usuário.
Para conferir sem abrir o editor, chame curl -s 'https://seusite.com.br/wp-json/wp/v2/posts/123?_fields=meta'. Se o objeto vier com a chave e o valor default, o registro está de pé e o resto é problema de quem grava.