Skip to main content

Error Handling

Standard error format and common error codes for the WooCommerce Appointments REST API.

Error Response Format

All errors follow the standard WooCommerce REST API error format:

{
"code": "error_code",
"message": "Human-readable error message",
"data": {
"status": 400
}
}

HTTP Status Codes

Status CodeMeaningCommon Causes
200SuccessRequest completed successfully
201CreatedResource created successfully
400Bad RequestInvalid parameters or validation failure
401UnauthorizedAuthentication required or invalid
403ForbiddenInsufficient permissions
404Not FoundResource doesn't exist
500Internal Server ErrorServer-side error

Common Error Codes

Authentication Errors

rest_forbidden

  • Status: 401
  • Message: "Sorry, you are not allowed to do that."
  • Cause: Missing or invalid authentication

woocommerce_rest_cannot_view

  • Status: 401
  • Message: "Sorry, you cannot view this resource."
  • Cause: Authentication required but not provided

Permission Errors

woocommerce_rest_cannot_create

  • Status: 403
  • Message: "Sorry, you are not allowed to create resources."
  • Cause: Missing manage_woocommerce capability

woocommerce_rest_cannot_update

  • Status: 403
  • Message: "Sorry, you are not allowed to edit this resource."
  • Cause: Missing manage_woocommerce capability

woocommerce_rest_cannot_delete

  • Status: 403
  • Message: "Sorry, you are not allowed to delete this resource."
  • Cause: Missing manage_woocommerce capability

Validation Errors

woocommerce_appointments_invalid_status

  • Status: 400
  • Message: "Invalid appointment status."
  • Cause: Invalid status value provided in create/update request
  • Valid values: unpaid, pending-confirmation, confirmed, paid, cancelled

woocommerce_rest_invalid_param

  • Status: 400
  • Message: "Invalid parameter(s): {param_name}"
  • Cause: Invalid parameter value or type

woocommerce_rest_missing_callback_param

  • Status: 400
  • Message: "Missing parameter(s): {param_name}"
  • Cause: Required parameter not provided

Resource Errors

woocommerce_rest_invalid_id

  • Status: 404
  • Message: "Invalid ID."
  • Cause: Resource ID doesn't exist or is invalid
  • Resolution: Verify the ID exists and is correct. Check that the resource hasn't been deleted.

rest_post_invalid_id

  • Status: 404
  • Message: "Invalid post ID."
  • Cause: Appointment/product ID doesn't exist
  • Resolution: Verify the appointment or product exists in the database. Check for typos in the ID.

woocommerce_rest_appointment_invalid_product_id

  • Status: 400
  • Message: "Invalid product ID."
  • Cause: The product ID doesn't exist or isn't an appointable product
  • Resolution: Ensure the product exists and has the "appointment" product type.

woocommerce_rest_appointment_invalid_staff_id

  • Status: 400
  • Message: "Invalid staff ID."
  • Cause: Staff member doesn't exist or isn't assigned to the product
  • Resolution: Verify the staff member exists and is assigned to the appointable product.

Availability Errors

woocommerce_appointments_invalid_date_range

  • Status: 400
  • Message: "Invalid date range."
  • Cause: Start date is after end date, or dates are in the past
  • Resolution: Ensure start_date is before end_date and both dates are in the future (unless editing existing appointment).

woocommerce_appointments_slot_not_available

  • Status: 400
  • Message: "The selected time slot is not available."
  • Cause: The requested time slot conflicts with existing appointments or availability rules
  • Resolution: Check availability using /slots endpoint before creating appointment. Verify no conflicts with other appointments or blocked time rules.

woocommerce_appointments_invalid_timezone

  • Status: 400
  • Message: "Invalid timezone."
  • Cause: Timezone string is not valid
  • Resolution: Use valid timezone identifiers (e.g., "America/New_York", "UTC"). See PHP timezone list.

Configuration Errors

rest_no_route

  • Status: 404
  • Message: "No route was found matching the URL and request method."
  • Cause: Incorrect endpoint URL or HTTP method
  • Resolution:
    • Verify the endpoint URL is correct: /wp-json/wc-appointments/v2/...
    • Check that permalinks are not set to "Plain" (Settings → Permalinks)
    • Ensure you're using the correct HTTP method (GET, POST, PATCH, DELETE)
    • Verify the API version (v1 or v2) exists

rest_cookie_invalid_nonce

  • Status: 403
  • Message: "Cookie nonce is invalid."
  • Cause: Nonce expired or invalid when using cookie authentication
  • Resolution: Regenerate the nonce. For admin pages, refresh the page to get a new nonce. Nonces expire after 24 hours.

woocommerce_rest_authentication_error

  • Status: 401
  • Message: "Invalid authentication details."
  • Cause: Incorrect username/password or API key/secret
  • Resolution:
    • Verify username and application password are correct
    • Check that API keys haven't been revoked
    • Ensure no extra spaces in credentials
    • For application passwords, you can use with or without spaces

Data Validation Errors

woocommerce_rest_missing_callback_param

  • Status: 400
  • Message: "Missing parameter(s): {param_name}"
  • Cause: Required parameter not provided in request
  • Resolution: Check the endpoint documentation for required parameters. Common required fields:
    • product_id - Required for creating appointments
    • start_date - Required for appointments
    • end_date - Required for appointments

woocommerce_rest_invalid_param

  • Status: 400
  • Message: "Invalid parameter(s): {param_name}"
  • Cause: Parameter value is invalid or wrong type
  • Resolution:
    • Verify parameter types (string, integer, boolean, etc.)
    • Check date formats: YYYY-MM-DD HH:MM:SS (e.g., "2025-12-25 10:00:00")
    • Ensure numeric IDs are integers, not strings
    • Validate enum values (status must be one of: unpaid, pending-confirmation, confirmed, paid, cancelled, completed)

woocommerce_rest_invalid_date

  • Status: 400
  • Message: "Invalid date format."
  • Cause: Date string doesn't match expected format
  • Resolution: Use format YYYY-MM-DD HH:MM:SS (e.g., "2025-12-25 10:00:00"). Ensure dates are in the site's timezone or include timezone offset.

Server Errors

rest_cannot_connect

  • Status: 500
  • Message: "Error connecting to the API."
  • Cause: Server configuration issue or plugin conflict
  • Resolution:
    • Check WordPress and WooCommerce are active
    • Verify WooCommerce Appointments plugin is active
    • Check for plugin conflicts
    • Review server error logs
    • Ensure REST API is enabled (not disabled in wp-config.php)

rest_invalid_json

  • Status: 400
  • Message: "Invalid JSON in request body."
  • Cause: Malformed JSON in POST/PATCH request
  • Resolution:
    • Validate JSON syntax using a JSON validator
    • Ensure Content-Type header is application/json
    • Check for unescaped quotes or special characters
    • Verify all brackets and braces are properly closed

woocommerce_rest_database_error

  • Status: 500
  • Message: "Database error occurred."
  • Cause: Database connection issue or query failure
  • Resolution:
    • Check database connection
    • Review database error logs
    • Verify database tables exist
    • Check for database permission issues

Error Handling Examples

JavaScript

async function handleApiRequest(url, options = {}) {
try {
const response = await fetch(url, options);

if (!response.ok) {
const error = await response.json();

switch (error.code) {
case 'rest_forbidden':
case 'woocommerce_rest_cannot_view':
console.error('Authentication required');
break;

case 'woocommerce_rest_cannot_create':
case 'woocommerce_rest_cannot_update':
case 'woocommerce_rest_cannot_delete':
console.error('Insufficient permissions');
break;

case 'woocommerce_appointments_invalid_status':
console.error('Invalid status:', error.message);
break;

default:
console.error('API Error:', error.message);
}

throw error;
}

return await response.json();
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}

PHP

function handle_api_response($response) {
if (is_wp_error($response)) {
return [
'success' => false,
'error' => $response->get_error_message()
];
}

$status_code = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);

if ($status_code >= 400) {
$error_code = $data['code'] ?? 'unknown_error';
$error_message = $data['message'] ?? 'An error occurred';

return [
'success' => false,
'error_code' => $error_code,
'error_message' => $error_message,
'status_code' => $status_code
];
}

return [
'success' => true,
'data' => $data
];
}

Common Error Scenarios & Solutions

Scenario 1: "401 Unauthorized" when using Application Password

Problem: Getting 401 even with correct credentials.

Solutions:

  1. Check Application Password format:

    • Application passwords are 24 characters
    • Can include spaces: xxxx xxxx xxxx xxxx xxxx xxxx
    • Can be used without spaces: xxxxxxxxxxxxxxxxxxxxxxxx
    • Ensure no extra characters or line breaks
  2. Verify username:

    • Use your WordPress username (not email)
    • Check for typos or case sensitivity
  3. Check Application Password is active:

    • Go to Users → Profile
    • Verify the application password hasn't been revoked
    • Create a new one if needed
  4. Test with cURL:

    curl -u username:app_password \
    "https://your-site.com/wp-json/wc-appointments/v2/appointments"

Scenario 2: "404 No route was found" - Routes Not Registered

Problem: Endpoint returns 404 and routes don't appear in route list (e.g., rest_get_server()->get_routes() shows no wc-appointments routes).

This is different from a simple 404 - if routes aren't registered at all, the plugin's REST API isn't initializing.

Solutions:

  1. Verify plugin is active:

    // Check if plugin is active
    if ( ! class_exists( 'WC_Appointments' ) ) {
    // Plugin not loaded
    }
  2. Check permalink settings (CRITICAL):

    • Go to Settings → Permalinks
    • MUST NOT be set to "Plain"
    • Choose any other option (Post name, Day and name, Month and name, etc.)
    • Click "Save Changes" (even if no changes made)
    • This is required for REST API routes to register
  3. Flush rewrite rules:

    // In functions.php or via WP-CLI
    flush_rewrite_rules();

    Or:

    • Deactivate WooCommerce Appointments plugin
    • Reactivate it
    • This forces rewrite rules to regenerate
  4. Verify REST API class loads:

    // Debug: Check if REST API class exists
    if ( class_exists( 'WC_Appointments_REST_API' ) ) {
    $rest_api = new WC_Appointments_REST_API();
    // Routes should register on rest_api_init hook
    } else {
    // Plugin file not loaded - check includes
    }
  5. Check for REST API blocking:

    • Verify REST API isn't disabled in wp-config.php
    • Remove any code that blocks /wp-json/ requests
    • Check .htaccess for rules blocking /wp-json/
    • Verify security plugins aren't blocking REST API
  6. Test REST API availability:

    // Check if WordPress REST API is available
    if ( ! function_exists( 'rest_url' ) ) {
    // REST API disabled or not available
    }

    // Test basic REST API
    $test = wp_remote_get( site_url( '/wp-json/' ) );
    if ( is_wp_error( $test ) ) {
    // REST API not accessible
    }
  7. Check hook firing:

    // Add debug to see if rest_api_init fires
    add_action( 'rest_api_init', function() {
    error_log( 'REST API init fired' );
    if ( class_exists( 'WC_Appointments_REST_API' ) ) {
    error_log( 'WC_Appointments_REST_API class exists' );
    }
    }, 5 );
  8. Verify plugin file inclusion:

    • Check that includes/class-wc-appointments-rest-api.php is being included
    • File should be included in woocommerce-appointments.php around line 369
    • Verify no fatal errors preventing file from loading

Quick Diagnostic Script:

// Add this temporarily to diagnose the issue
add_action( 'init', function() {
if ( ! is_admin() ) return;

echo '<h2>REST API Diagnostic</h2>';

// Check plugin
echo '<p>Plugin Active: ' . ( class_exists( 'WC_Appointments' ) ? 'YES' : 'NO' ) . '</p>';

// Check REST API class
echo '<p>REST API Class: ' . ( class_exists( 'WC_Appointments_REST_API' ) ? 'YES' : 'NO' ) . '</p>';

// Check permalinks
$permalink_structure = get_option( 'permalink_structure' );
echo '<p>Permalink Structure: ' . ( $permalink_structure ? $permalink_structure : 'PLAIN (PROBLEM!)' ) . '</p>';

// Check REST API available
echo '<p>REST API Functions: ' . ( function_exists( 'rest_url' ) ? 'YES' : 'NO' ) . '</p>';

// List routes
global $wp_rest_server;
$wp_rest_server = rest_get_server();
$routes = $wp_rest_server->get_routes();
$appointment_routes = array_filter( array_keys( $routes ), function( $route ) {
return strpos( $route, 'wc-appointments' ) !== false;
} );

echo '<p>Appointment Routes Found: ' . count( $appointment_routes ) . '</p>';
if ( empty( $appointment_routes ) ) {
echo '<p style="color:red;"><strong>No routes found! Check permalinks and flush rewrite rules.</strong></p>';
} else {
echo '<pre>' . print_r( $appointment_routes, true ) . '</pre>';
}
}, 999 );

Scenario 3: "400 Invalid date range" when creating appointment

Problem: Appointment creation fails with date validation error.

Solutions:

  1. Check date format:

    • Required format: YYYY-MM-DD HH:MM:SS
    • Example: "2025-12-25 10:00:00"
    • Include leading zeros: "2025-01-05 09:00:00" (not "2025-1-5 9:0:0")
  2. Verify date order:

    • start_date must be before end_date
    • Check for timezone issues
  3. Ensure future dates:

    • For new appointments, dates must be in the future
    • Unless editing existing appointment
  4. Example correct payload:

    {
    "product_id": 123,
    "start_date": "2025-12-25 10:00:00",
    "end_date": "2025-12-25 11:00:00"
    }

Scenario 4: "400 Slot not available" error

Problem: Can't create appointment because slot is unavailable.

Solutions:

  1. Check availability first:

    curl "https://your-site.com/wp-json/wc-appointments/v2/slots?product_ids=123&min_date=2025-12-25&max_date=2025-12-25"
  2. Verify no conflicts:

    • Check for existing appointments at that time
    • Verify availability rules aren't blocking the time
    • Check staff availability if staff is assigned
  3. Check capacity:

    • Verify product inventory/capacity allows more bookings
    • Check if staff capacity is reached
  4. Use available slot:

    • Query /slots endpoint to find available times
    • Use a slot marked as available: true

Scenario 5: "403 Forbidden" when user has correct role

Problem: User has admin role but still gets 403.

Solutions:

  1. Check capabilities:

    • Required: manage_woocommerce capability
    • Verify user role includes this capability
    • Check if custom role has been modified
  2. Verify API key permissions:

    • For WooCommerce API keys, check read/write permissions
    • Regenerate keys if needed
  3. Test with different user:

    • Try with a different admin account
    • Verify the issue is user-specific or global

Scenario 6: CORS errors in browser

Problem: Browser blocks API requests with CORS errors.

Solutions:

  1. Server-side solution (recommended):

    • Add CORS headers in .htaccess or server config
    • Or use a plugin like "CORS Headers"
  2. For development:

    • Use a browser extension to disable CORS (not for production)
    • Or use server-to-server requests instead
  3. Check request origin:

    • Ensure requests are from allowed domains
    • Verify Access-Control-Allow-Origin header is set

Best Practices

  1. Always check response status - Don't assume success
  2. Handle specific error codes - Provide user-friendly messages
  3. Log errors - For debugging and monitoring
  4. Retry on network errors - With exponential backoff
  5. Validate input client-side - Prevent unnecessary API calls
  6. Show user-friendly messages - Don't expose technical error details
  7. Test authentication first - Verify credentials before making complex requests
  8. Check availability before booking - Query /slots endpoint first
  9. Handle rate limiting - Implement retry logic with backoff
  10. Monitor error patterns - Track common errors to identify issues