REST API Reference
BuddyPress Member Blog overviewFree + ProGet BuddyPress Member Blog →
Every route WB Member Blog and WB Member Blog Pro register, who may call it, what it takes and what it returns. Written against version 4.3.0.
Sources: src/Rest/*Controller.php and the two image routes in
public/class-buddypress-member-blog-public.php (Free), and
includes/class-buddypress-member-blog-pro-rest.php (Pro).
Namespace and base URL
Section titled “Namespace and base URL”There is one namespace: wbcom-member-blog/v1. Pro registers its routes in the same namespace by
extending Free’s RestController, so both plugins share one error shape, one set of permission
callbacks and one pagination contract.
https://example.com/wp-json/wbcom-member-blog/v1The constant is Wbcom\MemberBlog\Rest\RestController::NAMESPACE_V1.
The old bpmb/v1 alias was removed in 4.0.1. Requests to /wp-json/bpmb/v1/* return 404.
Authentication
Section titled “Authentication”Every write route and every private read route uses the WordPress cookie plus a REST nonce, sent in
the X-WP-Nonce header.
fetch( wpApiSettings.root + 'wbcom-member-blog/v1/bookmarks', { method: 'POST', credentials: 'same-origin', headers: { 'X-WP-Nonce': wpApiSettings.nonce, 'Content-Type': 'application/json' }, body: JSON.stringify( { post_id: 123 } )} );Any script that declares bpmb-ui-helpers as a dependency gets window.bpmbRestConfig
({ root, nonce }) and the window.bpmbRest( method, path, data ) helper. It attaches the nonce,
returns the payload on success, and rejects with an Error carrying .code, .status and .data
on failure. Pro’s own scripts use it for every call.
Application Passwords cannot write by default
Section titled “Application Passwords cannot write by default”The shared write check, RestController::can_mutate(), refuses a request authenticated with an
Application Password with 403 bpmb_app_password_write_denied. Every member-facing write here is
something a member does on a page they are looking at, so a long-lived token is refused unless the
site opts in:
add_filter( 'bpmb_rest_allow_app_passwords', '__return_true' );This applies to every route that uses can_mutate() or a check built on it, in Free and in Pro.
Error shape
Section titled “Error shape”Every route returns core’s error envelope. Codes are prefixed bpmb_.
{ "code": "bpmb_cannot_edit", "message": "You cannot edit this post.", "data": { "status": 403 }}Common codes from the shared checks:
| Code | Status | Meaning |
|---|---|---|
bpmb_not_logged_in |
401 | The route needs a signed-in user. |
bpmb_app_password_write_denied |
403 | A write was attempted with an Application Password. |
bpmb_feature_disabled |
403 | The site owner switched the feature off on the Features screen. |
bpmb_forbidden |
403 | Signed in, but not allowed to act on this object. |
bpmb_not_found |
404 | The object does not exist, or is not published where it must be. |
Pagination
Section titled “Pagination”Collection routes that use the shared parameters accept page (default 1) and per_page
(default 10, maximum 50) and send X-WP-Total and X-WP-TotalPages. Values outside the bounds
are rejected with a 400, not silently clamped.
Switching a feature off closes its route
Section titled “Switching a feature off closes its route”The Features screen (Member Blog settings, Features tab) is enforced on the server, not only in the
page. With a feature off, its routes answer 403 bpmb_feature_disabled:
| Feature | Routes it closes |
|---|---|
| Claps | POST /reactions |
| Reading list | POST /bookmarks, GET /bookmarks, DELETE /bookmarks/{post_id} |
| Follow writers | POST /follows, GET /follows, DELETE /follows/{object_type}/{object_id}, and GET /feed?source=following (501) |
In Pro, each module registers its routes only while the module is on (see Pro routes). A route for a module that is off does not exist and returns 404.
Route index
Section titled “Route index”| Route | Method | Access |
|---|---|---|
/dashboard |
GET | Signed in. Own dashboard, or any with edit_others_posts. |
/dashboard/counts |
GET | Same as /dashboard. |
/posts/render |
GET | Public for published posts. Drafts and pending: owner or edit_others_posts. |
/posts/{id}/related |
GET | Public. |
/feed |
GET | Public, except following and reading-list, which need a signed-in user. |
/popular |
GET | Public. |
/authors |
GET | Public. |
/featured |
GET | Public. |
/posts/{id}/featured |
POST, DELETE | Capability from bpmb_feature_capability (default edit_others_posts). |
/bookmarks |
GET, POST | Signed in. Reading list feature on. |
/bookmarks/{post_id} |
DELETE | Signed in. Reading list feature on. |
/follows |
GET, POST | Signed in. Follow writers feature on. |
/follows/{object_type}/{object_id} |
DELETE | Signed in. Follow writers feature on. |
/reactions |
POST | Signed in. Claps feature on. |
/autosave |
POST | Signed in. Edit rights on the post, or the create gate for a new one. |
/draft |
GET, DELETE | Signed in. Edit rights on the post. |
/posts/{id}/featured-image |
DELETE | Signed in. Edit rights on the post. |
/categories |
POST | Signed in. The Allow custom categories rule (bpmb_access()->can_manage_categories()). |
/upload-image |
POST | Signed in, with upload_files or the create gate. |
/attach-image |
POST | Signed in, with upload_files or the create gate, plus edit rights on the post and the attachment. |
| Route | Method | Module |
|---|---|---|
/posts/{id} |
DELETE | Always registered. |
/posts/{id}/status |
POST | Always registered. |
/series |
POST | Series |
/series/{id} |
PATCH, DELETE | Series |
/series/{id}/order |
PATCH | Series |
/series/{id}/progress |
POST | Series |
/series/{id}/guest-progress |
POST | Series |
/coauthors/search |
GET | Co-Authors |
/posts/{id}/coauthors |
POST, PATCH | Co-Authors |
/posts/{id}/coauthors/{user_id} |
DELETE | Co-Authors |
/posts/{id}/coauthors/invitation/accept |
POST | Co-Authors |
/posts/{id}/coauthors/invitation/decline |
POST | Co-Authors |
/posts/{id}/lock |
POST, DELETE | Co-Authors |
/posts/{id}/review |
POST | Co-Authors, with the editorial workflow setting on |
/posts/{id}/schedule |
POST, DELETE | Scheduling |
/analytics |
GET | Analytics |
/analytics/export |
GET | Analytics |
/groups/{group_id}/posts/{id}/featured |
POST | Group Blogs |
/me/notifications |
PATCH | Author Dashboard |
Dashboard
Section titled “Dashboard”src/Rest/DashboardController.php
A member’s dashboard lists the posts they can edit, which includes posts they co-author. Core’s
author parameter cannot express that. Both routes go through DashboardService, which applies the
bp_member_blog_dashboard_query_args filter Pro uses to fold in co-authored posts.
GET /dashboard
Section titled “GET /dashboard”Permission: signed in (401 otherwise). Passing another member’s user_id needs
edit_others_posts (403 bpmb_forbidden otherwise).
| Param | Type | Default | Notes |
|---|---|---|---|
user_id |
integer | 0 | 0 is the current user. |
tab |
string | published |
drafts or pending; anything else lists published posts. |
search |
string | '' |
|
page |
integer | 1 | |
per_page |
integer | 10 | Maximum 50. |
[ { "id": 412, "title": "Draft about indexes", "status": "draft", "date": "2026-07-02T09:14:00", "link": "https://example.com/?p=412", "edit_link": "https://example.com/write/?post_id=412", "views": 0, "is_owner": true }]Headers: X-WP-Total, X-WP-TotalPages.
GET /dashboard/counts
Section titled “GET /dashboard/counts”Same permission. Accepts user_id.
{ "published": 12, "drafts": 3, "pending": 1, "total": 16, "views": 4821 }Each count comes from the same service call as the list, so a tab badge cannot disagree with the list under it.
Listing and discovery
Section titled “Listing and discovery”GET /posts/render
Section titled “GET /posts/render”src/Rest/FrontendController.php. Returns one page of a member’s post list as rendered HTML,
the same cards and empty state the first page was drawn with. The member home uses it for paging.
Permission: public. The drafts and pending tabs return 403 bpmb_forbidden unless the caller is
the owner or has edit_others_posts.
| Param | Type | Default |
|---|---|---|
user_id |
integer | 0 (the current user; 400 bpmb_invalid_user when signed out) |
tab |
string | published |
page |
integer | 1 |
search |
string | '' |
{ "html": "<div class=\"bpmb-blog-post\">...</div>", "page": 2, "max_pages": 4, "total": 31, "pagination": "<nav class=\"bpmb-pagination\">...</nav>"}GET /posts/{id}/related
Section titled “GET /posts/{id}/related”Permission: public. Wraps PostQuery::related(), the same method the related-posts shortcode and
block use.
| Param | Type | Default | Notes |
|---|---|---|---|
id |
integer | required | Must be published, otherwise 404 bpmb_not_found. |
per_page |
integer | 4 | 1 to 12. |
[ { "id": 77, "title": "Indexing follows", "link": "https://example.com/indexing-follows/", "date": "2026-06-21T10:00:00", "thumbnail": "", "author": { "id": 4, "name": "Jane Doe" } }]GET /feed
Section titled “GET /feed”src/Rest/FeedController.php. The route behind Load more on every listing shortcode. One route
with a source parameter, where each source calls the same service method its shortcode used for
page 1, so page 2 always continues page 1. It returns rendered card HTML.
Permission: public. following and reading-list need a signed-in user (401) and always read the
current user from the session; a user_id in the request is ignored for them. Only published posts
are returned; post_status is not a parameter.
Public sources are cached for 60 seconds, for signed-out visitors only (the cards carry each member’s own saved, clapped and following state, so a signed-in response is never cached). The cache key uses the registered parameters below; any other query parameter is ignored.
| Param | Type | Default | Notes |
|---|---|---|---|
source |
string | required | recent, author, popular, topic, following, reading-list, authors. |
page |
integer | 2 | |
per_page |
integer | 10 | 1 to 50. |
user_id |
integer | 0 | Required for source=author (400 bpmb_missing_author). |
category, tag, search |
string | '' |
|
timeframe |
string | all |
all, week, month, year (for popular). |
orderby |
string | date |
date, title, comment_count, rand; for authors also post_count, total_views, name, recent. |
order |
string | DESC |
ASC or DESC. |
exclude_users |
string | '' |
Comma-separated user IDs. |
start_rank, variant |
0, recent |
Card layout options passed through from the shortcode. | |
show_image, show_excerpt, show_date, show_author, show_avatar, show_views |
boolean | true | Card options. |
role, columns (1-6, default 4), avatar_size (32-200, default 80), show_count, show_bio |
Author directory options (source=authors). |
{ "html": "<article ...>", "page": 2, "max_pages": 5, "count": 10, "has_more": true }source=authors also returns announce, a sentence for the screen-reader status region.
Responses for public sources are cached for 60 seconds per parameter set; personal sources are never
cached.
GET /popular
Section titled “GET /popular”src/Rest/DiscoveryController.php. Permission: public. Collection parameters plus:
| Param | Type | Default | Notes |
|---|---|---|---|
category |
integer | 0 | Term ID. |
timeframe |
string | all |
all, week, month, year. |
Each item: id, title, permalink, date (UTC), thumbnail, views, and author (id,
name, url). Headers: X-WP-Total, X-WP-TotalPages.
GET /authors
Section titled “GET /authors”Permission: public. Collection parameters plus orderby (post_count or total_views, default
post_count) and order (asc or desc, default desc).
Each item: id, name, slug, post_count, total_views, description, avatar, url.
Featured posts
Section titled “Featured posts”src/Rest/FeaturedController.php. Every route wraps FeaturedService, which the Featured row
action in wp-admin also calls.
/posts/{id}/featured is the editor’s-pick flag. /posts/{id}/featured-image is the post
thumbnail. They are different things.
GET /featured
Section titled “GET /featured”Permission: public. Collection parameters. Returns a plain array (not an envelope) and the paging headers.
[ { "id": 101, "title": "The member blog rebuild", "permalink": "https://example.com/the-member-blog-rebuild/", "author": { "id": 4, "name": "Jane Doe", "url": "https://example.com/author/jane/" }, "date": "2026-07-01T08:00:00" }]POST /posts/{id}/featured
Section titled “POST /posts/{id}/featured”Permission: FeaturedService::user_can_feature(), which checks the capability returned by
bpmb_feature_capability (default edit_others_posts). 401 when signed out, 403
bpmb_cannot_feature when signed in without it.
| Param | Type | Default | Notes |
|---|---|---|---|
order |
integer | 0 | 0 to 9999. Lower sorts first. |
Only a published post can be featured (400 bpmb_not_published). A missing post is
404 bpmb_post_not_found.
{ "post_id": 101, "featured": true, "total": 7 }DELETE /posts/{id}/featured
Section titled “DELETE /posts/{id}/featured”Same permission. Returns { "post_id": 101, "featured": false, "total": 6 }.
Engagement
Section titled “Engagement”src/Rest/EngagementController.php. Bookmarks (the reading list), follows and claps. Each route is
closed when its feature is switched off (see above).
POST /bookmarks
Section titled “POST /bookmarks”| Param | Type | Required |
|---|---|---|
post_id |
integer | yes |
The post must be published, otherwise 404. Returns { "bookmarked": true, "count": 38 }.
DELETE /bookmarks/{post_id}
Section titled “DELETE /bookmarks/{post_id}”No existence check, so a member can remove a saved post that has since been deleted. Returns
{ "bookmarked": false, "count": 37 }.
GET /bookmarks
Section titled “GET /bookmarks”A reading list is private. Collection parameters plus user_id (default the current user); another
member’s list needs edit_others_posts. Each item: id, title, link, date, thumbnail,
author (id, name). Paging headers.
POST /follows
Section titled “POST /follows”| Param | Type | Required | Notes |
|---|---|---|---|
object_type |
string | yes | user, series or term. |
object_id |
integer | yes | A user ID, a series term ID, or (for term) a term taxonomy ID. |
The target must exist (404). A term must belong to a followable taxonomy, category by default
(bpmb_followable_taxonomies), otherwise 400 bpmb_not_followable.
Returns { "following": true, "followers": 129 }.
DELETE /follows/{object_type}/{object_id}
Section titled “DELETE /follows/{object_type}/{object_id}”No existence check. Returns { "following": false, "followers": 128 }.
GET /follows
Section titled “GET /follows”Returns the current member’s own list only.
| Param | Type | Default |
|---|---|---|
object_type |
string | user |
{ "object_type": "user", "ids": [ 4, 19, 22 ] }POST /reactions
Section titled “POST /reactions”Claps.
| Param | Type | Default | Notes |
|---|---|---|---|
post_id |
integer | required | Must be published. |
claps |
integer | 1 | 1 to 50 per request. |
The client sends one request per burst of taps. The server adds them atomically and caps each
member’s total per post at bpmb_max_claps (default 50). Clapping your own post returns
403 bpmb_own_post.
{ "claps": 7, "total": 214, "maxed": false }claps is the member’s own total for the post, total is the post’s. Fires bpmb_post_clapped
($post_id, $user_id, $mine, $total).
Composer
Section titled “Composer”src/Rest/FrontendController.php. The routes the post form uses.
POST /autosave
Section titled “POST /autosave”Permission: signed in; bpmb_access()->can_edit() on an existing post, or
bpmb_access()->can_create() for a new draft. Returns 403 bpmb_autosave_disabled when the site
owner has switched autosave off.
| Param | Type | Default | Notes |
|---|---|---|---|
post_id |
integer | 0 | 0 creates a new draft. |
title |
string | '' |
|
content |
string | '' |
Sanitized by PostSubmissionService::sanitize_content(). |
categories |
integer[] | [] |
Excluded categories are removed. |
tags |
string[] | [] |
|
editor_data |
string | '' |
Editor.js block JSON, stored in _bpmb_editorjs_blocks when it decodes. |
Autosave never changes a post’s status. The one exception is auto-draft, which becomes draft
on the first save with content.
It also never writes over a post readers can see. For a post that is publish, private or
future, the content goes to the member’s own autosave revision and the live post is untouched;
categories and tags are not written on that path. draft and pending posts are saved in place.
{ "saved": true, "post_id": 42, "stored": "post", "time": "2026-08-12 09:47:11" }{ "saved": true, "post_id": 42, "stored": "revision", "revision_id": 43, "time": "2026-08-12 09:47:11" }post_id is always the post, never the revision. An empty title with empty content saves nothing
and returns { "saved": false, "post_id": 0 }. time is site-local time.
GET /draft
Section titled “GET /draft”Asks whether there are unsaved changes on a post the member is reopening, so the editor can offer them back.
Permission: signed in (can_mutate()).
| Param | Type | Required |
|---|---|---|
post_id |
integer | yes |
post_id is required. In 4.3.0 the call without an id, which offered the member’s latest stray
draft to the blank new-post form, was removed; a new post is never prompted.
The answer reads only this member’s own autosave revision of the post, needs edit rights on the post, and ignores a revision older than the post itself or one the member has dismissed.
{ "has_draft": false }{ "has_draft": true, "post_id": 412, "title": "Draft about indexes", "content": "<p>...</p>", "modified": "2026-07-11T16:49:00Z", "editor_data": "{\"blocks\":[...]}", "context": "unpublished_changes"}modified is the autosave time in UTC (ISO 8601 with Z). Format it on the client, in the
member’s own clock. The old modified_display field was removed in 4.3.0.
DELETE /draft
Section titled “DELETE /draft”“Stop offering me this one.” Records that the member dismissed the changes on this post; it does not delete anything. Newer changes made after the dismissal are offered again. Dismissals older than 30 days are pruned.
| Param | Type | Required |
|---|---|---|
post_id |
integer | yes |
Needs edit rights on the post (403 bpmb_cannot_dismiss). Returns
{ "dismissed": true, "post_id": 412 }.
DELETE /posts/{id}/featured-image
Section titled “DELETE /posts/{id}/featured-image”Permission: signed in plus bpmb_access()->can_edit( $id ). Clears the post thumbnail. Returns
{ "removed": true, "post_id": 412 }.
POST /categories
Section titled “POST /categories”Adds a category from the post form. Permission: signed in; the callback then asks
bpmb_access()->can_manage_categories(), which is where the Allow custom categories setting is
enforced (403 bpmb_cannot_add_category). This creates a term only; there is no route to rename or
delete one.
| Param | Type | Required |
|---|---|---|
name |
string | yes (1 to 200 characters) |
parent |
integer | no, default 0; must exist (400 bpmb_invalid_parent) |
A name that already exists returns the existing term. A category the site owner has excluded returns
403 bpmb_category_excluded. Returns { "id": 19, "name": "Engineering" }.
POST /upload-image
Section titled “POST /upload-image”public/class-buddypress-member-blog-public.php. The only upload transport for the editor.
Permission: signed in, and either upload_files or bpmb_access()->can_create().
multipart/form-data, field name image, optional post_id (needs edit rights on it).
Allowed types come from bpmb_media()->allowed_mime_types(): the Allowed image types setting, never
SVG, then the bpmb_allowed_image_mime_types and bpmb_rest_upload_allowed_types filters. The size
limit comes from bpmb_media()->max_upload_bytes(): the upload size setting in MB, then
bpmb_max_upload_size (MB) and bpmb_rest_upload_max_size (bytes).
{ "success": true, "data": { "file": { "url": "https://example.com/wp-content/uploads/2026/07/photo.jpg", "width": 1600, "height": 900 }, "attachment_id": 913 }}Error codes (no bpmb_ prefix on this route): no_file, invalid_file, invalid_type,
file_too_large (all 400), no_permission (403), upload_failed (500).
POST /attach-image
Section titled “POST /attach-image”Moves an existing attachment onto a post.
| Param | Type | Required |
|---|---|---|
post_id |
integer | yes |
attachment_id |
integer | yes |
Needs edit rights on the post, and the caller must be able to edit the attachment or own it.
Returns { "success": true, "data": { "message": "Image attached to post." } }.
Core’s post endpoint
Section titled “Core’s post endpoint”Free does not add a create or update route for posts. Members write through core’s
/wp/v2/posts, and two classes make that endpoint follow the plugin’s rules.
RestGate
Section titled “RestGate”src/Rest/RestGate.php hooks rest_pre_insert_post and rest_after_insert_post for the post type:
- On create,
bpmb_access()->can_create(); on update,bpmb_access()->can_edit(). Refusals return403 bpmb_rest_cannot_create(with the real reason, such as a post limit or no credits) or403 bpmb_rest_cannot_edit. - A request for
publish,futureorprivateis passed throughbpmb_submission()->resolve_status(), so a moderated member lands inpending. It only clamps down; a request fordraftstays a draft, and an edit to a live post does not pull it off the site. - A request for
privatethat cannot be honoured (the member’s posts go to review, orbpmb_allow_private_postsis off) is refused with403 bpmb_rest_private_not_allowed. It is never downgraded, because a clampedpendingpost would be published publicly on approval. - Runs the
bp_member_blog_pro_validate_postfilter, where Pro enforces the word limits and the co-author edit lock. Failures return400 bpmb_rest_validation_failed. - After insert, excluded categories are stripped.
Administrators and anyone with edit_others_posts are exempt. Change that with
bpmb_rest_gate_exempt (bool $exempt, int $user_id).
Pro adds one more guard on the same hook: a member can only assign their post to a series they own.
MetaFields
Section titled “MetaFields”src/Rest/MetaFields.php registers three post meta keys on /wp/v2/posts, readable by anyone who
can read the post and writable by anyone who can edit it: _bpmb_focus_keyword,
_bpmb_meta_description, _bpmb_editorjs_blocks. Credit and moderation state is deliberately not
exposed. Add keys with bpmb_rest_exposed_post_meta.
Pro routes
Section titled “Pro routes”Pro routes live in includes/class-buddypress-member-blog-pro-rest.php. Every one uses
can_mutate() (signed in, no Application Password) unless noted, and the object-level check lives in
the module’s own method, which is also what the page’s buttons call. Errors use the same
bpmb_ envelope.
Member posts
Section titled “Member posts”| Route | What it does | Who may |
|---|---|---|
DELETE /posts/{id} |
Moves the post to Trash (not a permanent delete). | bpmb_access()->can_delete() on the post. |
POST /posts/{id}/status |
Takes a published post offline, or puts an unpublished one live. | can_edit(); going live also needs can_publish(). |
Series
Section titled “Series”| Route | Params | Who may |
|---|---|---|
POST /series |
name (required) |
The capability from bpmb_series_create_capability (default edit_posts). |
PATCH /series/{id} |
name, description, status (active or completed). Fields left out are kept. |
The series owner, or a user with edit_others_posts. |
DELETE /series/{id} |
The series owner, or a user with edit_others_posts. |
|
PATCH /series/{id}/order |
order (post IDs) |
The series owner only. IDs not in the series are dropped. |
POST /series/{id}/progress |
post_id (required) |
Signed-in reader. Records reading progress. |
POST /series/{id}/guest-progress |
progress (object) |
Public, rate limited (429 bpmb_rate_limited). Validates a guest’s locally stored progress. |
The owner check reads the series’ own author. Other members get 403 bpmb_forbidden. An unknown status returns 400 bpmb_invalid_status. POST /series/{id}/progress returns 403 bpmb_progress_off when progress tracking is off. POST /series reuses a series of that name only when the caller owns it; otherwise it creates a separate series for them. Core’s
/wp/v2/bp_member_blog_series term endpoint requires edit_others_posts to rename or delete a
series.
Co-authors
Section titled “Co-authors”| Route | Params | Notes |
|---|---|---|
GET /coauthors/search |
query (required), post_id |
Members to invite. Matches names and whole email addresses, not partial ones. |
POST /posts/{id}/coauthors |
invitee (required) |
Invite. The post must be saved first (400 bpmb_post_not_saved); the caller must manage the post’s co-authors. |
PATCH /posts/{id}/coauthors |
order (user IDs, required) |
Reorder. |
DELETE /posts/{id}/coauthors/{user_id} |
The author removes a co-author, or a co-author removes themselves. | |
POST /posts/{id}/coauthors/invitation/accept |
The invitee’s answer. Checks the invitation, not edit rights. | |
POST /posts/{id}/coauthors/invitation/decline |
Same. | |
POST /posts/{id}/lock |
force (boolean) |
Take the edit lock. Another holder returns 409 with locked_by; force: true is Take Over. Needs edit rights. |
DELETE /posts/{id}/lock |
Release the lock. | |
POST /posts/{id}/review |
decision (approve or reject, required), feedback |
Registered only when the editorial workflow setting is on. Reviewers only. A reject needs feedback (400 bpmb_feedback_required); a post no longer pending returns 409 bpmb_not_pending. Uses the same approve and send-back path as Free’s moderation. |
Scheduling
Section titled “Scheduling”| Route | Params | Notes |
|---|---|---|
POST /posts/{id}/schedule |
datetime (required) |
Schedule or reschedule a draft or scheduled post. |
DELETE /posts/{id}/schedule |
Cancel a schedule. |
Both need rights over the post’s schedule (403 bpmb_forbidden). A post that is not a draft or
scheduled post returns 404.
Analytics
Section titled “Analytics”| Route | Params | Notes |
|---|---|---|
GET /analytics |
user_id, post_id, days (default 30) |
An author’s roll-up, or one post’s numbers. |
GET /analytics/export |
user_id, days |
The same roll-up as { csv, filename }. |
A post’s numbers are visible only to that post’s author and to users with edit_others_posts.
The check reads the post’s real author, not a user_id in the request. A roll-up for another member
also needs edit_others_posts. The caller must also hold one of the roles allowed in the Analytics settings (all signed-in members when none are set; administrators always).
Group blogs
Section titled “Group blogs”POST /groups/{group_id}/posts/{id}/featured toggles a post’s featured flag inside a group. The post
must be linked to the group (400 bpmb_not_in_group) and the caller must be allowed to feature posts
in that group.
Notification preferences
Section titled “Notification preferences”PATCH /me/notifications saves the current member’s email and on-site notification choices, the
same form as the Author Dashboard settings screen. It is a whole-form save: every preference field
not sent (for example bpmb_notify_published, bpmb_notify_digest) is stored as off.
Filters
Section titled “Filters”| Filter | Default | Effect |
|---|---|---|
bpmb_rest_allow_app_passwords |
false |
Allow Application Passwords to write. |
bpmb_rest_gate_exempt |
Staff exempt | Who skips the submission rules on /wp/v2/posts. |
bpmb_rest_exposed_post_meta |
Three keys | Post meta exposed on /wp/v2/posts. |
bpmb_rest_collection_items |
Filter the items of any collection response before it is sent. | |
bpmb_feature_capability |
edit_others_posts |
The capability /posts/{id}/featured needs. |
bpmb_max_claps |
50 |
The per-member clap cap. |
bpmb_followable_taxonomies |
category |
Taxonomies a member may follow with object_type=term. |
bpmb_allowed_image_mime_types |
Setting | Upload allowlist everywhere. |
bpmb_rest_upload_allowed_types |
Setting | Upload allowlist, applied last. |
bpmb_max_upload_size |
Setting (MB) | Upload size limit everywhere. |
bpmb_rest_upload_max_size |
Setting (bytes) | Upload size limit, applied last. |
bp_member_blog_dashboard_query_args |
Widens the dashboard query; applies to /dashboard and /posts/render. |
|
bpmb_series_create_capability |
edit_posts |
Who may create a series (Pro). |
The complete list is in the Hook Reference. To add your own routes, see Extend the REST API.

