The Bifrost Music plugin extends the WordPress REST API with custom fields and endpoints for the music content types.
Overview
All custom post types and taxonomies are REST API-enabled through the show_in_rest parameter:
Artists : /wp-json/wp/v2/music_artist
Albums : /wp-json/wp/v2/music_album
Genres : /wp-json/wp/v2/music_genre
Album Parent Field
Since the music_album post type is non-hierarchical but needs to maintain parent-child relationships with artists, a custom parent field is registered with the REST API.
Registration
Registered in inc/Content/Album.php:152
private function restRegister () : void
{
register_rest_field ( Definitions :: POST_TYPE_ALBUM , 'parent' , [
'get_callback' => fn ( $post ) => ( int ) $post [ 'parent' ],
'update_callback' => fn ( $value , $post ) => wp_update_post ([
'ID' => $post -> ID ,
'post_parent' => ( int ) $value
]),
'schema' => [
'description' => __ ( 'Parent Artist ID' , 'bifrost-music' ),
'type' => 'integer' ,
'context' => [ 'view' , 'edit' ]
]
]);
}
Field Schema
The ID of the parent artist for this album
description
string
default: "Parent Artist ID"
Human-readable description of the field
Data type validation (must be an integer)
context
array
default: "['view', 'edit']"
Available in both view and edit contexts
Get Callback
Retrieves the parent artist ID from the post object:
'get_callback' => fn ( $post ) => ( int ) $post [ 'parent' ]
Returns : Integer ID of the parent artist, or 0 if no parent is set.
Update Callback
Updates the parent artist relationship:
'update_callback' => fn ( $value , $post ) => wp_update_post ([
'ID' => $post -> ID ,
'post_parent' => ( int ) $value
])
Parameters :
$value (int): The new parent artist ID
$post (WP_Post): The album post object
Returns : The result of wp_update_post()
REST API Endpoints
Artists Endpoint
GET /wp-json/wp/v2/music_artist
Retrieve a list of all artists. Query Parameters :Scope under which the request is made. Options: view, embed, edit
Current page of the collection
Maximum number of items per page
Limit to artists with specific status
Example Request :curl https://example.com/wp-json/wp/v2/music_artist?per_page= 5
Example Response :[
{
"id" : 123 ,
"date" : "2026-03-09T10:00:00" ,
"slug" : "the-beatles" ,
"status" : "publish" ,
"type" : "music_artist" ,
"link" : "https://example.com/artists/the-beatles" ,
"title" : {
"rendered" : "The Beatles"
},
"content" : {
"rendered" : "<p>Artist biography...</p>"
},
"featured_media" : 456 ,
"_links" : { ... }
}
]
GET /wp-json/wp/v2/music_artist/{id}
Retrieve a specific artist by ID. Path Parameters :Unique identifier for the artist
Example Request :curl https://example.com/wp-json/wp/v2/music_artist/123
POST /wp-json/wp/v2/music_artist
Create a new artist. Required Capabilities : create_music_artistsBody Parameters :The artist biography (HTML content)
The artist status. Options: publish, draft, pending
The ID of the featured image (artist photo)
Example Request :curl -X POST https://example.com/wp-json/wp/v2/music_artist \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Pink Floyd",
"content": "Progressive rock band...",
"status": "publish"
}'
Albums Endpoint
GET /wp-json/wp/v2/music_album
Retrieve a list of all albums. Query Parameters : Same as Artists endpoint, plus:Filter albums by parent artist ID
Filter albums by genre term ID(s)
Example Request :# Get all albums by artist ID 123
curl https://example.com/wp-json/wp/v2/music_album?parent= 123
# Get all rock albums
curl https://example.com/wp-json/wp/v2/music_album?music_genre= 5
Example Response :[
{
"id" : 456 ,
"date" : "2026-03-09T11:00:00" ,
"slug" : "abbey-road" ,
"status" : "publish" ,
"type" : "music_album" ,
"link" : "https://example.com/albums/abbey-road" ,
"title" : {
"rendered" : "Abbey Road"
},
"parent" : 123 ,
"featured_media" : 789 ,
"music_genre" : [ 5 , 12 ],
"_links" : { ... }
}
]
POST /wp-json/wp/v2/music_album
Create a new album. Required Capabilities : create_music_albumsBody Parameters : Same as Artists, plus:Array of genre term IDs to assign
Example Request :curl -X POST https://example.com/wp-json/wp/v2/music_album \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "The Dark Side of the Moon",
"parent": 124,
"music_genre": [5, 12],
"status": "publish"
}'
PUT/PATCH /wp-json/wp/v2/music_album/{id}
Update an existing album, including its parent artist relationship. Required Capabilities : edit_music_albumExample Request :# Change the parent artist for an album
curl -X PATCH https://example.com/wp-json/wp/v2/music_album/456 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"parent": 125}'
Genres Endpoint
GET /wp-json/wp/v2/music_genre
Retrieve a list of all genres. Query Parameters :Whether to hide genres with no assigned albums
Maximum number of items per page
Example Request :curl https://example.com/wp-json/wp/v2/music_genre
Example Response :[
{
"id" : 5 ,
"count" : 42 ,
"description" : "" ,
"link" : "https://example.com/genres/rock" ,
"name" : "Rock" ,
"slug" : "rock" ,
"taxonomy" : "music_genre" ,
"_links" : { ... }
}
]
Authentication
All write operations (POST, PUT, PATCH, DELETE) require authentication. WordPress supports several authentication methods:
Application Passwords Built-in WordPress authentication method (WP 5.6+)
OAuth OAuth 1.0a or 2.0 via plugins
JWT JSON Web Tokens via third-party plugins
Cookie WordPress cookie authentication (same-site only)
CORS Considerations
If accessing the API from a different domain, you may need to enable CORS. Add this to your theme’s functions.php or a custom plugin:
add_action ( 'rest_api_init' , function () {
remove_filter ( 'rest_pre_serve_request' , 'rest_send_cors_headers' );
add_filter ( 'rest_pre_serve_request' , function ( $value ) {
header ( 'Access-Control-Allow-Origin: https://your-frontend-domain.com' );
header ( 'Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS' );
header ( 'Access-Control-Allow-Credentials: true' );
return $value ;
});
}, 15 );
Error Responses
The API returns standard WordPress REST API error responses:
{
"code" : "rest_forbidden" ,
"message" : "Sorry, you are not allowed to create music artists." ,
"data" : {
"status" : 403
}
}
Common error codes:
rest_forbidden (403): Insufficient permissions
rest_invalid_param (400): Invalid parameter value
rest_post_invalid_id (404): Post not found
rest_cannot_edit (401): Authentication required