Alright, not the answer I was expecting, especially since REST is part of the WP core now. Luckily I figured it out myself. People who understand REST a little bit should understand the below functions:
My post type is 'exchange', so change that to yours, and fields are 'wpcf_languages_spoken' and 'wpcf_languages_learning', which are multi-select checkboxes. Please note that I am only allowing the user to select one box per field in the app, so not sure if this code works for more.
Also please note that if you are updating the field, check your Types post field settings to see what you should be saving the field value as in your database. For me, it was just the value name as a string, but I believe the default option is a number.
//Fields for Language Exchanges
add_action( 'rest_api_init', 'slug_register_exchange' );
function slug_register_exchange() {
foreach (array('wpcf_languages_spoken', 'wpcf_languages_learning') as $field) {
register_rest_field( 'exchange',
$field,
array(
'get_callback' => 'slug_get_exchange',
'update_callback' => 'slug_update_exchange',
'schema' => null,
)
);
}
}
//Get custom exchange fields
function slug_get_exchange( $object, $field_name, $request ) {
//note that the fields were added with underscores rather than dashes. This is because in JS, dashes cause problems, so here we need to convert them back.
$field_name = str_replace('_', '-', $field_name);
$values = get_post_meta( $object[ 'id' ], $field_name, true );
$return = array();
//This is going to output an array for each field with the value of each selected checkbox
foreach ($values as $key => $value) {
$return[] = ['name' => $value[0]];
}
return $return;
}
//For posting a language exchange with custom field checkboxes. not sure if it works for multiple values
function slug_update_exchange( $value, $object, $field_name ) {
if ( ! $value || ! is_string( $value ) ) {
return;
}
//again, we have to replace the underscores with dashes
$field_name = str_replace('_', '-', $field_name);
$prefix = 'wpcf_';
//here we strip the prefix so we can use it to get field options in the Types function below
$field_name_nopre = substr($field_name, strlen($prefix));
$field_data = types_get_field($field_name_nopre);
$options = $field_data['data']['options'];
$return = array();
$value = strip_tags( $value );
foreach ($options as $key => $val) {
if ($val['title'] === $value) {
$return[$key] = array(0 => $value);
}
}
return update_post_meta( $object->ID, $field_name, $return );
}