# WordPress Plugin Integration Guide **Version**: 1.0.0 **Last Updated**: 2025-11-16 Complete guide for integrating WordPress plugins with IGNY8 API v1.0. --- ## Overview This guide helps WordPress plugin developers integrate with the IGNY8 API using the unified response format. --- ## Authentication ### Getting Access Token ```php function igny8_login($email, $password) { $response = wp_remote_post('https://api.igny8.com/api/v1/auth/login/', [ 'headers' => [ 'Content-Type' => 'application/json' ], 'body' => json_encode([ 'email' => $email, 'password' => $password ]) ]); $body = json_decode(wp_remote_retrieve_body($response), true); if ($body['success']) { // Store tokens update_option('igny8_access_token', $body['data']['access']); update_option('igny8_refresh_token', $body['data']['refresh']); return $body['data']['access']; } else { return new WP_Error('login_failed', $body['error']); } } ``` ### Using Access Token ```php function igny8_get_headers() { $token = get_option('igny8_access_token'); if (!$token) { return false; } return [ 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json' ]; } ``` --- ## API Client Class ### Complete PHP Implementation ```php class Igny8API { private $base_url = 'https://api.igny8.com/api/v1'; private $access_token = null; private $refresh_token = null; public function __construct() { $this->access_token = get_option('igny8_access_token'); $this->refresh_token = get_option('igny8_refresh_token'); } /** * Login and store tokens */ public function login($email, $password) { $response = wp_remote_post($this->base_url . '/auth/login/', [ 'headers' => [ 'Content-Type' => 'application/json' ], 'body' => json_encode([ 'email' => $email, 'password' => $password ]) ]); $body = $this->parse_response($response); if ($body['success']) { $this->access_token = $body['data']['access']; $this->refresh_token = $body['data']['refresh']; update_option('igny8_access_token', $this->access_token); update_option('igny8_refresh_token', $this->refresh_token); return true; } return false; } /** * Refresh access token */ public function refresh_token() { if (!$this->refresh_token) { return false; } $response = wp_remote_post($this->base_url . '/auth/refresh/', [ 'headers' => [ 'Content-Type' => 'application/json' ], 'body' => json_encode([ 'refresh' => $this->refresh_token ]) ]); $body = $this->parse_response($response); if ($body['success']) { $this->access_token = $body['data']['access']; $this->refresh_token = $body['data']['refresh']; update_option('igny8_access_token', $this->access_token); update_option('igny8_refresh_token', $this->refresh_token); return true; } return false; } /** * Parse unified API response */ private function parse_response($response) { if (is_wp_error($response)) { return [ 'success' => false, 'error' => $response->get_error_message() ]; } $body = json_decode(wp_remote_retrieve_body($response), true); $status_code = wp_remote_retrieve_response_code($response); // Handle non-JSON responses if (!$body) { return [ 'success' => false, 'error' => 'Invalid response format' ]; } // Check if response follows unified format if (isset($body['success'])) { return $body; } // Legacy format - wrap in unified format if ($status_code >= 200 && $status_code < 300) { return [ 'success' => true, 'data' => $body ]; } else { return [ 'success' => false, 'error' => $body['detail'] ?? 'Unknown error' ]; } } /** * Get headers with authentication */ private function get_headers() { if (!$this->access_token) { throw new Exception('Not authenticated'); } return [ 'Authorization' => 'Bearer ' . $this->access_token, 'Content-Type' => 'application/json' ]; } /** * Make GET request */ public function get($endpoint) { $response = wp_remote_get($this->base_url . $endpoint, [ 'headers' => $this->get_headers() ]); $body = $this->parse_response($response); // Handle 401 - token expired if (!$body['success'] && wp_remote_retrieve_response_code($response) == 401) { // Try to refresh token if ($this->refresh_token()) { // Retry request $response = wp_remote_get($this->base_url . $endpoint, [ 'headers' => $this->get_headers() ]); $body = $this->parse_response($response); } } return $body; } /** * Make POST request */ public function post($endpoint, $data) { $response = wp_remote_post($this->base_url . $endpoint, [ 'headers' => $this->get_headers(), 'body' => json_encode($data) ]); $body = $this->parse_response($response); // Handle 401 - token expired if (!$body['success'] && wp_remote_retrieve_response_code($response) == 401) { // Try to refresh token if ($this->refresh_token()) { // Retry request $response = wp_remote_post($this->base_url . $endpoint, [ 'headers' => $this->get_headers(), 'body' => json_encode($data) ]); $body = $this->parse_response($response); } } return $body; } /** * Make PUT request */ public function put($endpoint, $data) { $response = wp_remote_request($this->base_url . $endpoint, [ 'method' => 'PUT', 'headers' => $this->get_headers(), 'body' => json_encode($data) ]); return $this->parse_response($response); } /** * Make DELETE request */ public function delete($endpoint) { $response = wp_remote_request($this->base_url . $endpoint, [ 'method' => 'DELETE', 'headers' => $this->get_headers() ]); return $this->parse_response($response); } } ``` --- ## Usage Examples ### Get Keywords ```php $api = new Igny8API(); // Get keywords $response = $api->get('/planner/keywords/'); if ($response['success']) { $keywords = $response['results']; $count = $response['count']; foreach ($keywords as $keyword) { echo $keyword['name'] . '
'; } } else { echo 'Error: ' . $response['error']; } ``` ### Create Keyword ```php $api = new Igny8API(); $data = [ 'seed_keyword_id' => 1, 'site_id' => 1, 'sector_id' => 1, 'status' => 'active' ]; $response = $api->post('/planner/keywords/', $data); if ($response['success']) { $keyword = $response['data']; echo 'Created keyword: ' . $keyword['id']; } else { echo 'Error: ' . $response['error']; if (isset($response['errors'])) { foreach ($response['errors'] as $field => $errors) { echo $field . ': ' . implode(', ', $errors) . '
'; } } } ``` ### Handle Pagination ```php $api = new Igny8API(); function get_all_keywords($api) { $all_keywords = []; $page = 1; do { $response = $api->get("/planner/keywords/?page={$page}&page_size=100"); if ($response['success']) { $all_keywords = array_merge($all_keywords, $response['results']); $page++; } else { break; } } while ($response['next']); return $all_keywords; } $keywords = get_all_keywords($api); ``` ### Handle Rate Limiting ```php function make_rate_limited_request($api, $endpoint, $max_retries = 3) { for ($attempt = 0; $attempt < $max_retries; $attempt++) { $response = $api->get($endpoint); // Check if rate limited if (!$response['success'] && isset($response['error'])) { if (strpos($response['error'], 'Rate limit') !== false) { // Wait before retry sleep(pow(2, $attempt)); // Exponential backoff continue; } } return $response; } return ['success' => false, 'error' => 'Max retries exceeded']; } ``` --- ## Error Handling ### Unified Error Handling ```php function handle_api_response($response) { if ($response['success']) { return $response['data'] ?? $response['results']; } else { $error_message = $response['error']; // Log error with request ID error_log(sprintf( 'IGNY8 API Error: %s (Request ID: %s)', $error_message, $response['request_id'] ?? 'unknown' )); // Handle field-specific errors if (isset($response['errors'])) { foreach ($response['errors'] as $field => $errors) { error_log(" {$field}: " . implode(', ', $errors)); } } return new WP_Error('igny8_api_error', $error_message, $response); } } ``` --- ## Best Practices ### 1. Store Tokens Securely ```php // Use WordPress options API with encryption function save_token($token) { // Encrypt token before storing $encrypted = base64_encode($token); update_option('igny8_access_token', $encrypted, false); } function get_token() { $encrypted = get_option('igny8_access_token'); return base64_decode($encrypted); } ``` ### 2. Implement Token Refresh ```php function ensure_valid_token($api) { // Check if token is about to expire (refresh 1 minute before) // Token expires in 15 minutes, refresh at 14 minutes $last_refresh = get_option('igny8_token_refreshed_at', 0); if (time() - $last_refresh > 14 * 60) { if ($api->refresh_token()) { update_option('igny8_token_refreshed_at', time()); } } } ``` ### 3. Cache Responses ```php function get_cached_keywords($api, $cache_key = 'igny8_keywords', $ttl = 300) { $cached = get_transient($cache_key); if ($cached !== false) { return $cached; } $response = $api->get('/planner/keywords/'); if ($response['success']) { $keywords = $response['results']; set_transient($cache_key, $keywords, $ttl); return $keywords; } return false; } ``` ### 4. Handle Rate Limits ```php function check_rate_limit($response) { // Note: WordPress wp_remote_* doesn't expose all headers easily // Consider using cURL or checking response for 429 status if (isset($response['error']) && strpos($response['error'], 'Rate limit') !== false) { // Wait and retry sleep(60); return true; // Should retry } return false; } ``` --- ## WordPress Admin Integration ### Settings Page ```php function igny8_settings_page() { ?>

IGNY8 API Settings

API Email
API Password
login($_POST['igny8_email'], $_POST['igny8_password'])) { update_option('igny8_email', $_POST['igny8_email']); add_settings_error('igny8_settings', 'igny8_connected', 'Successfully connected to IGNY8 API', 'updated'); } else { add_settings_error('igny8_settings', 'igny8_error', 'Failed to connect to IGNY8 API', 'error'); } } } add_action('admin_init', 'igny8_save_settings'); ``` --- ## Testing ### Unit Tests ```php class TestIgny8API extends WP_UnitTestCase { public function test_login() { $api = new Igny8API(); $result = $api->login('test@example.com', 'password'); $this->assertTrue($result); $this->assertNotEmpty(get_option('igny8_access_token')); } public function test_get_keywords() { $api = new Igny8API(); $response = $api->get('/planner/keywords/'); $this->assertTrue($response['success']); $this->assertArrayHasKey('results', $response); $this->assertArrayHasKey('count', $response); } } ``` --- ## Troubleshooting ### Issue: Authentication Fails **Check**: 1. Email and password are correct 2. Account is active 3. API endpoint is accessible ### Issue: Token Expires Frequently **Solution**: Implement automatic token refresh before expiration. ### Issue: Rate Limited **Solution**: Implement request throttling and caching. --- **Last Updated**: 2025-11-16 **API Version**: 1.0.0