# 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() {
?>