Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nk-crew/visual-portfolio/llms.txt
Use this file to discover all available pages before exploring further.
This page documents the REST API endpoints provided by Visual Portfolio for dynamic content loading and portfolio management.
Base URL
All endpoints are prefixed with:
/wp-json/visual-portfolio/v1/
Namespace: visual-portfolio/v1
Endpoints
Get Layouts List
Retrieve a list of all saved portfolio layouts.
Endpoint: GET /get_layouts/
Permission: edit_posts
Response:
{
"success": true,
"response": [
{
"id": 123,
"title": "My Portfolio",
"edit_url": "https://example.com/wp-admin/post.php?post=123&action=edit"
},
{
"id": 456,
"title": "Image Gallery",
"edit_url": "https://example.com/wp-admin/post.php?post=456&action=edit"
}
]
}
Error Response:
{
"error": true,
"success": false,
"error_code": "no_layouts_found",
"response": "Layouts not found."
}
Example:
fetch( '/wp-json/visual-portfolio/v1/get_layouts/' )
.then( response => response.json() )
.then( data => {
console.log( 'Layouts:', data.response );
} );
Update Layout Data
Update portfolio layout configuration.
Endpoint: POST /update_layout/
Permission: edit_post (for the specific post)
Parameters:
post_id (integer, required) - Portfolio post ID
data (object, required) - Layout configuration data
Request Body:
{
"post_id": 123,
"data": {
"vp_layout": "grid",
"vp_items_style": "classic",
"vp_items_gap": "30",
"vp_items_count": "12"
}
}
Response:
{
"success": true,
"response": true
}
Error Response:
{
"error": true,
"success": false,
"error_code": "not_allowed",
"response": "Sorry, you are not allowed to edit saved layouts data."
}
Example:
fetch( '/wp-json/visual-portfolio/v1/update_layout/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify( {
post_id: 123,
data: {
vp_layout: 'masonry',
vp_items_gap: '20'
}
} )
} )
.then( response => response.json() )
.then( data => console.log( data ) );
Get Filter Items
Retrieve filter items for a portfolio based on content source.
Endpoint: POST /get_filter_items/
Permission: edit_posts
Parameters:
content_source (string, required) - Content source type (‘post-based’, ‘images’)
post_id (integer, required) - Current post ID for URL generation
- Additional parameters based on content source
For post-based content:
posts_source (string) - Posts source
post_types_set (array) - Post types to include
posts_taxonomies (object) - Taxonomy filters
posts_order_by (string) - Order by field
posts_order_direction (string) - Order direction
For images content:
images (array) - Array of image IDs
images_order_by (string) - Order by field
Request Body:
{
"content_source": "post-based",
"post_id": 789,
"posts_source": "portfolio",
"post_types_set": ["post", "portfolio"]
}
Response:
{
"success": true,
"response": [
{
"filter": "*",
"label": "All",
"description": "",
"count": false,
"active": true,
"url": "https://example.com/portfolio/",
"taxonomy": "",
"id": 0,
"parent": 0
},
{
"filter": "15",
"label": "Category Name",
"description": "Category description",
"count": 8,
"active": false,
"url": "https://example.com/portfolio/?vp_filter=category%3A15",
"taxonomy": "category",
"id": 15,
"parent": 0
}
]
}
Error Response:
{
"error": true,
"success": false,
"error_code": "missing_params",
"response": "Required parameters are missing."
}
Example:
fetch( '/wp-json/visual-portfolio/v1/get_filter_items/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify( {
content_source: 'post-based',
post_id: 789,
posts_source: 'portfolio'
} )
} )
.then( response => response.json() )
.then( data => {
const filters = data.response;
console.log( 'Available filters:', filters );
} );
Get Max Pages
Calculate the maximum number of pages for pagination.
Endpoint: GET|POST /get-max-pages/
Permission: edit_posts
Parameters:
content_source (string, required) - Content source type
items_count (integer, required) - Number of items per page
- Additional content-specific parameters
Query String (GET):
/wp-json/visual-portfolio/v1/get-max-pages/?content_source=post-based&items_count=12&posts_source=portfolio
Request Body (POST):
{
"content_source": "post-based",
"items_count": 12,
"posts_source": "portfolio",
"post_types_set": ["post"]
}
Response:
Example (GET):
const params = new URLSearchParams( {
content_source: 'post-based',
items_count: 12,
posts_source: 'portfolio'
} );
fetch( `/wp-json/visual-portfolio/v1/get-max-pages/?${params}` )
.then( response => response.json() )
.then( data => {
console.log( 'Max pages:', data.max_pages );
} );
Example (POST):
fetch( '/wp-json/visual-portfolio/v1/get-max-pages/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify( {
content_source: 'images',
items_count: 20,
images: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
} )
} )
.then( response => response.json() )
.then( data => console.log( 'Max pages:', data.max_pages ) );
Update Gallery Items Count Notice State
Update the visibility state of the gallery items count notice.
Endpoint: POST /update_gallery_items_count_notice_state/
Permission: manage_options and edit_post
Parameters:
post_id (integer, required) - Portfolio post ID
notice_state (string, required) - Notice state value
Request Body:
{
"post_id": 123,
"notice_state": "dismissed"
}
Response:
{
"success": true,
"response": true
}
PHP Implementation
Accessing REST Endpoints in PHP
You can make internal REST API requests using WordPress functions.
Example:
$request = new WP_REST_Request( 'GET', '/visual-portfolio/v1/get_layouts/' );
$response = rest_do_request( $request );
$server = rest_get_server();
$data = $server->response_to_data( $response, false );
if ( $data['success'] ) {
$layouts = $data['response'];
// Use layouts data
}
Making External API Calls
Using wp_remote_post:
$response = wp_remote_post(
home_url( '/wp-json/visual-portfolio/v1/get_filter_items/' ),
array(
'headers' => array(
'Content-Type' => 'application/json',
),
'body' => wp_json_encode(
array(
'content_source' => 'post-based',
'post_id' => get_the_ID(),
'posts_source' => 'portfolio',
)
),
)
);
if ( ! is_wp_error( $response ) ) {
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( isset( $body['success'] ) && $body['success'] ) {
$filters = $body['response'];
// Use filter items
}
}
JavaScript Helper Functions
Making Authenticated Requests
With nonce authentication:
const { nonce } = window.VPData;
fetch( '/wp-json/visual-portfolio/v1/update_layout/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': nonce
},
body: JSON.stringify( {
post_id: 123,
data: { vp_layout: 'grid' }
} )
} )
.then( response => response.json() )
.then( data => console.log( data ) );
Using jQuery with WordPress AJAX:
jQuery.ajax( {
url: window.VPData.ajaxUrl,
method: 'POST',
data: {
action: 'vp_custom_action',
nonce: window.VPData.nonce,
post_id: 123
},
success: function( response ) {
console.log( response );
}
} );
Error Handling
Common Error Codes
not_allowed - User lacks required permissions
missing_params - Required parameters not provided
no_layouts_found - No portfolio layouts exist
invalid_content_source - Invalid content source specified
post_id_required - Post ID parameter missing
user_dont_have_permission - User lacks specific permission
Error Response Format
All error responses follow this structure:
{
"error": true,
"success": false,
"error_code": "error_code_here",
"response": "Human-readable error message"
}
Handling Errors
JavaScript:
fetch( '/wp-json/visual-portfolio/v1/get_layouts/' )
.then( response => response.json() )
.then( data => {
if ( data.error ) {
console.error( 'Error:', data.error_code, data.response );
return;
}
// Handle success
console.log( data.response );
} )
.catch( error => {
console.error( 'Request failed:', error );
} );
PHP:
$response = rest_do_request( $request );
if ( is_wp_error( $response ) ) {
// Handle WP_Error
error_log( $response->get_error_message() );
} else {
$data = $response->get_data();
if ( isset( $data['error'] ) && $data['error'] ) {
// Handle API error
error_log( 'API Error: ' . $data['error_code'] );
} else {
// Handle success
$result = $data['response'];
}
}
Security
Permission Checks
All endpoints implement WordPress capability checks:
- edit_posts - Required for reading layouts and filters
- edit_post - Required for updating specific layouts
- manage_options - Required for plugin settings
Nonce Verification
When making requests from the frontend, include the nonce:
const { nonce } = window.VPData;
fetch( endpoint, {
headers: {
'X-WP-Nonce': nonce
}
} );
Data Sanitization
All input data is sanitized using:
sanitize_text_field() - For text inputs
intval() - For integer values
Visual_Portfolio_Security::sanitize_attributes() - For attribute arrays
Visual_Portfolio_Security::validate_calculate_max_pages_params() - For pagination params