# API Documentation - Multilingual Press Zone

> **Complete REST API reference for developers building integrations**

---

## Base URL

```
https://example.com/wp-json/multilingual-press-zone/v1
```

## Authentication

All endpoints use **WordPress REST API nonces** for authentication.

### JavaScript (Admin Panel)

```javascript
// Nonce automatically passed via wp_localize_script
fetch(presszoneMultilingualAdmin.restUrl + '/languages', {
  headers: {
    'X-WP-Nonce': presszoneMultilingualAdmin.nonce
  }
});
```

### External API Requests

```bash
# Get nonce first
curl -c cookies.txt https://example.com/wp-login.php \
  -d "log=admin&pwd=password"

# Use nonce in subsequent requests
curl -b cookies.txt https://example.com/wp-json/multilingual-press-zone/v1/languages \
  -H "X-WP-Nonce: <nonce-from-page>"
```

---

## Endpoints Overview

| Resource | Endpoint | Methods |
|----------|----------|---------|
| **Languages** | `/languages` | GET, POST, PUT, DELETE |
| **Translations** | `/translations` | GET, POST, PUT, DELETE |
| **Dashboard** | `/dashboard/stats` | GET |
| **Settings** | `/settings` | GET, POST |
| **License** | `/license/activate` | POST |
| **Migration** | `/migration/start` | POST |

---

## Languages API

### GET /languages

**Description**: List all configured languages

**Parameters**: None

**Response** (200):
```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "code": "en_US",
      "name": "English (US)",
      "flag": "🇺🇸",
      "direction": "ltr",
      "status": "active",
      "is_default": true,
      "priority": 1,
      "url_structure": "directories",
      "translated_posts": 12450,
      "total_posts": 12450,
      "percentage": 100
    },
    {
      "id": 2,
      "code": "es_ES",
      "name": "Spanish (Spain)",
      "flag": "🇪🇸",
      "direction": "ltr",
      "status": "active",
      "is_default": false,
      "priority": 2,
      "url_structure": "directories",
      "translated_posts": 11454,
      "total_posts": 12450,
      "percentage": 92
    }
  ]
}
```

### POST /languages

**Description**: Add a new language

**Request Body**:
```json
{
  "code": "fr_FR",
  "name": "French (France)",
  "flag": "🇫🇷",
  "direction": "ltr",
  "status": "active",
  "url_structure": "directories"
}
```

**Response** (201):
```json
{
  "success": true,
  "data": {
    "id": 3,
    "code": "fr_FR",
    "name": "French (France)",
    "flag": "🇫🇷",
    "direction": "ltr",
    "status": "active",
    "is_default": false,
    "priority": 3,
    "url_structure": "directories",
    "translated_posts": 0,
    "total_posts": 12450,
    "percentage": 0
  }
}
```

**Error** (400):
```json
{
  "success": false,
  "error": {
    "code": "language_exists",
    "message": "Language with code fr_FR already exists"
  }
}
```

### PUT /languages/{id}

**Description**: Update a language

**Request Body**:
```json
{
  "name": "French (Canada)",
  "code": "fr_CA",
  "status": "inactive"
}
```

**Response** (200):
```json
{
  "success": true,
  "data": {
    "id": 3,
    "code": "fr_CA",
    "name": "French (Canada)",
    "status": "inactive"
  }
}
```

### DELETE /languages/{id}

**Description**: Delete a language (and all its translations)

**Response** (200):
```json
{
  "success": true,
  "message": "Language deleted successfully. 9711 translations removed."
}
```

**Error** (400):
```json
{
  "success": false,
  "error": {
    "code": "cannot_delete_default",
    "message": "Cannot delete the default language"
  }
}
```

### POST /languages/reorder

**Description**: Reorder language priorities

**Request Body**:
```json
{
  "order": [1, 3, 2]
}
```

**Response** (200):
```json
{
  "success": true,
  "message": "Languages reordered successfully"
}
```

---

## Translations API

### GET /translations

**Description**: List translations with filtering

**Parameters**:
- `type` (string): Content type filter (post, page, product, all)
- `language` (string): Language code filter (en_US, es_ES, all)
- `status` (string): Status filter (complete, partial, missing, all)
- `search` (string): Search query
- `page` (int): Page number (default: 1)
- `per_page` (int): Items per page (default: 25)

**Example**:
```
GET /translations?type=post&language=es_ES&status=partial&page=1&per_page=25
```

**Response** (200):
```json
{
  "success": true,
  "data": {
    "items": [
      {
        "element_id": 123,
        "element_type": "post_page",
        "title": "About Us",
        "translation_group_id": 45,
        "languages": {
          "en_US": { "id": 123, "status": "published" },
          "es_ES": { "id": 456, "status": "published" },
          "fr_FR": { "id": null, "status": "missing" }
        },
        "completion": 66,
        "last_modified": "2026-01-25T10:30:00Z"
      }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 25,
      "total_items": 12450,
      "total_pages": 498
    }
  }
}
```

### POST /translations

**Description**: Create a translation for existing content

**Request Body**:
```json
{
  "element_id": 123,
  "element_type": "post_page",
  "source_language": "en_US",
  "target_language": "fr_FR",
  "content": {
    "title": "À propos de nous",
    "content": "Bienvenue sur notre site...",
    "excerpt": "Notre histoire"
  },
  "status": "draft"
}
```

**Response** (201):
```json
{
  "success": true,
  "data": {
    "translation_id": 789,
    "element_id": 789,
    "source_element_id": 123,
    "language_code": "fr_FR",
    "translation_group_id": 45,
    "status": "draft",
    "created_at": "2026-01-25T11:00:00Z"
  }
}
```

### PUT /translations/{id}

**Description**: Update a translation

**Request Body**:
```json
{
  "content": {
    "title": "À propos de nous (updated)",
    "content": "Updated French content..."
  },
  "status": "published"
}
```

**Response** (200):
```json
{
  "success": true,
  "data": {
    "translation_id": 789,
    "element_id": 789,
    "status": "published",
    "updated_at": "2026-01-25T11:15:00Z"
  }
}
```

### DELETE /translations/{id}

**Description**: Delete a translation

**Response** (200):
```json
{
  "success": true,
  "message": "Translation deleted successfully"
}
```

### POST /translations/bulk-action

**Description**: Perform bulk actions on translations

**Request Body**:
```json
{
  "action": "delete",
  "ids": [123, 456, 789]
}
```

**Actions**: `delete`, `publish`, `draft`, `translate`

**Response** (200):
```json
{
  "success": true,
  "message": "Bulk action completed",
  "results": {
    "processed": 3,
    "succeeded": 2,
    "failed": 1,
    "errors": [
      { "id": 456, "error": "Permission denied" }
    ]
  }
}
```

---

## Dashboard API

### GET /dashboard/stats

**Description**: Get dashboard statistics

**Response** (200):
```json
{
  "success": true,
  "data": {
    "languages": {
      "total": 3,
      "active": 3
    },
    "posts": {
      "total": 12450,
      "translated": 9711,
      "percentage": 78
    },
    "pending_reviews": 234,
    "performance": {
      "avg_load_time_ms": 45,
      "avg_queries_per_page": 3
    },
    "coverage_by_language": [
      { "code": "en_US", "name": "English", "percentage": 100 },
      { "code": "es_ES", "name": "Spanish", "percentage": 92 },
      { "code": "fr_FR", "name": "French", "percentage": 78 }
    ]
  }
}
```

### GET /dashboard/activity

**Description**: Get recent activity feed

**Parameters**:
- `limit` (int): Number of items (default: 10)

**Response** (200):
```json
{
  "success": true,
  "data": [
    {
      "type": "translation_created",
      "post_id": 123,
      "post_title": "Homepage",
      "language_code": "es_ES",
      "language_name": "Spanish",
      "user_id": 1,
      "user_name": "Admin",
      "timestamp": "2026-01-25T10:00:00Z",
      "relative_time": "2 minutes ago"
    },
    {
      "type": "translation_approved",
      "post_id": 456,
      "post_title": "About Us",
      "language_code": "fr_FR",
      "language_name": "French",
      "user_id": 2,
      "user_name": "Translator",
      "timestamp": "2026-01-25T09:45:00Z",
      "relative_time": "15 minutes ago"
    }
  ]
}
```

---

## Settings API

### GET /settings

**Description**: Get all plugin settings

**Response** (200):
```json
{
  "success": true,
  "data": {
    "general": {
      "default_language": "en_US",
      "url_structure": "directories",
      "show_switcher": true,
      "include_flags": true,
      "translation_memory": true
    },
    "workflow": {
      "approval_required": false,
      "auto_publish": true
    },
    "notifications": {
      "email_enabled": true,
      "slack_enabled": false,
      "slack_webhook": ""
    },
    "api": {
      "enabled": true,
      "rate_limit": 100
    },
    "advanced": {
      "debug_mode": false,
      "cache_enabled": true
    }
  }
}
```

### POST /settings

**Description**: Update plugin settings

**Request Body**:
```json
{
  "general": {
    "default_language": "es_ES",
    "url_structure": "subdomains"
  },
  "workflow": {
    "approval_required": true
  }
}
```

**Response** (200):
```json
{
  "success": true,
  "message": "Settings updated successfully"
}
```

---

## License API

### POST /license/activate

**Description**: Activate a license key

**Request Body**:
```json
{
  "license_key": "MPZ-P-XXXX-XXXX-XXXX"
}
```

**Response** (200):
```json
{
  "success": true,
  "data": {
    "tier": "pro",
    "status": "active",
    "sites_allowed": 3,
    "sites_used": 1,
    "updates_until": "2027-01-25T00:00:00Z",
    "features": {
      "team_management": true,
      "workflow": true,
      "priority_support": true
    }
  }
}
```

**Error** (400):
```json
{
  "success": false,
  "error": {
    "code": "invalid_license",
    "message": "The license key is invalid or has been revoked"
  }
}
```

### GET /license/status

**Description**: Check license status (requires active license)

**Response** (200):
```json
{
  "success": true,
  "data": {
    "tier": "pro",
    "status": "active",
    "updates_until": "2027-01-25T00:00:00Z",
    "days_remaining": 365,
    "active_sites": [
      {
        "url": "https://example.com",
        "activated_at": "2026-01-01T00:00:00Z"
      }
    ]
  }
}
```

### POST /license/deactivate

**Description**: Deactivate license from this site

**Response** (200):
```json
{
  "success": true,
  "message": "License deactivated successfully"
}
```

---

## Migration API

### POST /migration/start

**Description**: Start WPML migration wizard

**Request Body**:
```json
{
  "batch_size": 1000,
  "content_types": ["post", "page", "product"],
  "create_redirects": true,
  "preserve_wpml_tables": true
}
```

**Response** (202):
```json
{
  "success": true,
  "data": {
    "migration_id": "mig_abc123",
    "status": "in_progress",
    "progress": 0,
    "estimated_batches": 126,
    "estimated_time_minutes": 45
  }
}
```

### GET /migration/status

**Description**: Check migration progress

**Response** (200):
```json
{
  "success": true,
  "data": {
    "migration_id": "mig_abc123",
    "status": "in_progress",
    "progress": 65,
    "current_phase": "migrating_products",
    "completed_items": 81230,
    "total_items": 125432,
    "errors": 8,
    "elapsed_minutes": 32,
    "estimated_remaining_minutes": 18
  }
}
```

---

## PHP Hooks & Filters

### Filters

#### mpz_before_language_save

Modify language data before saving

```php
add_filter('mpz_before_language_save', function($language) {
    // Modify language data
    $language['custom_field'] = 'value';
    return $language;
}, 10, 1);
```

#### mpz_before_translation_save

Modify translation data before saving

```php
add_filter('mpz_before_translation_save', function($translation) {
    // Auto-uppercase titles
    $translation['title'] = strtoupper($translation['title']);
    return $translation;
}, 10, 1);
```

#### mpz_language_switcher_html

Customize language switcher output

```php
add_filter('mpz_language_switcher_html', function($html, $languages) {
    // Wrap in custom container
    return '<div class="custom-switcher">' . $html . '</div>';
}, 10, 2);
```

### Actions

#### mpz_language_created

Triggered after a language is created

```php
add_action('mpz_language_created', function($language_id, $language) {
    // Send notification
    error_log("New language added: " . $language['name']);
}, 10, 2);
```

#### mpz_translation_published

Triggered when a translation is published

```php
add_action('mpz_translation_published', function($translation_id, $post_id, $language_code) {
    // Clear cache, send notifications, etc.
    wp_cache_delete('mpz_post_' . $post_id);
}, 10, 3);
```

#### mpz_migration_completed

Triggered after WPML migration completes

```php
add_action('mpz_migration_completed', function($results) {
    // Log migration results
    error_log("Migration completed: " . $results['total_items'] . " items migrated");
}, 10, 1);
```

---

## JavaScript Events

### mpz:language-changed

Fired when the current language changes

```javascript
document.addEventListener('mpz:language-changed', (e) => {
    console.log('Language changed to:', e.detail.language);
    // Reload content, update UI, etc.
});
```

### mpz:translation-saved

Fired when a translation is saved

```javascript
document.addEventListener('mpz:translation-saved', (e) => {
    console.log('Translation saved:', e.detail.translationId);
    // Show success message, refresh list, etc.
});
```

### mpz:dark-mode-changed

Fired when dark mode changes (from theme)

```javascript
document.addEventListener('presszone:dark-change', (e) => {
    console.log('Dark mode:', e.detail.enabled);
    // Update UI to match dark mode
});
```

---

## Error Codes

| Code | HTTP Status | Description |
|------|-------------|-------------|
| `invalid_language_code` | 400 | Language code format invalid |
| `language_exists` | 400 | Language already configured |
| `cannot_delete_default` | 400 | Cannot delete default language |
| `translation_not_found` | 404 | Translation does not exist |
| `invalid_license` | 400 | License key invalid or revoked |
| `site_limit_reached` | 400 | License site limit exceeded |
| `updates_expired` | 403 | License updates expired |
| `permission_denied` | 403 | User lacks required capability |
| `rate_limit_exceeded` | 429 | Too many requests |
| `internal_error` | 500 | Server error |

---

## Rate Limiting

**Limits**:
- **General endpoints**: 100 requests/minute per user
- **License activation**: 10 requests/minute per IP
- **Migration endpoints**: 1 concurrent migration per site

**Response Header**:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1737806400
```

**Error Response** (429):
```json
{
  "success": false,
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please try again in 60 seconds.",
    "retry_after": 60
  }
}
```

---

## OpenAPI Specification

**Download**: https://press.zone/docs/multilingual/openapi.yaml

**Swagger UI**: https://press.zone/docs/multilingual/api

---

## Code Examples

### JavaScript (Fetch API)

```javascript
// Get all languages
async function getLanguages() {
  const response = await fetch(
    presszoneMultilingualAdmin.restUrl + '/languages',
    {
      headers: {
        'X-WP-Nonce': presszoneMultilingualAdmin.nonce
      }
    }
  );
  
  if (!response.ok) {
    throw new Error('Failed to fetch languages');
  }
  
  const data = await response.json();
  return data.data;
}

// Create new language
async function createLanguage(languageData) {
  const response = await fetch(
    presszoneMultilingualAdmin.restUrl + '/languages',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-WP-Nonce': presszoneMultilingualAdmin.nonce
      },
      body: JSON.stringify(languageData)
    }
  );
  
  const data = await response.json();
  
  if (!data.success) {
    throw new Error(data.error.message);
  }
  
  return data.data;
}
```

### PHP (WordPress HTTP API)

```php
// Get all languages
$response = wp_remote_get(
    rest_url('multilingual-press-zone/v1/languages'),
    [
        'headers' => [
            'X-WP-Nonce' => wp_create_nonce('wp_rest')
        ]
    ]
);

if (is_wp_error($response)) {
    return [];
}

$body = json_decode(wp_remote_retrieve_body($response), true);
return $body['data'] ?? [];

// Create new language
$response = wp_remote_post(
    rest_url('multilingual-press-zone/v1/languages'),
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'X-WP-Nonce' => wp_create_nonce('wp_rest')
        ],
        'body' => wp_json_encode([
            'code' => 'de_DE',
            'name' => 'German (Germany)',
            'flag' => '🇩🇪'
        ])
    ]
);
```

### cURL

```bash
# Get all languages
curl -X GET https://example.com/wp-json/multilingual-press-zone/v1/languages \
  -H "X-WP-Nonce: YOUR_NONCE"

# Create new language
curl -X POST https://example.com/wp-json/multilingual-press-zone/v1/languages \
  -H "Content-Type: application/json" \
  -H "X-WP-Nonce: YOUR_NONCE" \
  -d '{
    "code": "de_DE",
    "name": "German (Germany)",
    "flag": "🇩🇪",
    "direction": "ltr",
    "status": "active"
  }'
```

---

## Plugin Abstraction Layer

For integrating with other multilingual plugins, see `PLUGIN-ABSTRACTION-LAYER.md`.

**Example**: Create custom adapter

```php
use MultilingualPressZone\Integration\IMultilingualBridge;

class MyCustomAdapter implements IMultilingualBridge {
    public function getCurrentLanguage(): string {
        return get_option('my_current_language', 'en');
    }
    
    public function getAvailableLanguages(): array {
        return get_option('my_languages', []);
    }
    
    // Implement other methods...
}

// Register adapter
add_filter('mpz_multilingual_bridge', function() {
    return new MyCustomAdapter();
});
```

---

## Related Documents

- `ADMIN-PANEL-ARCHITECTURE.md` - Vanilla JS API client implementation
- `LICENSING-IMPLEMENTATION-PLAN.md` - License API (api.press.zone)
- `PLUGIN-ABSTRACTION-LAYER.md` - IMultilingualBridge interface
- `WPML-MIGRATION-GUIDE.md` - Migration API usage
- `PHASE1-CORE-FOUNDATION.md` - REST API implementation tasks

---

## Support

- **Documentation**: https://press.zone/docs/multilingual/api
- **Community Forum**: https://community.press.zone/multilingual
- **Email Support**: support@press.zone
- **Priority Support** (Pro/Enterprise): 24h response time

---

## Summary

**REST API Endpoints**: 15+ endpoints for languages, translations, dashboard, settings, licensing, migration

**Authentication**: WordPress REST API nonces (X-WP-Nonce header)

**PHP Hooks**: 6 filters + 3 actions for extensibility

**JavaScript Events**: 3 custom events for frontend integration

**Rate Limiting**: 100 req/min general, 10 req/min licensing

**Error Handling**: Consistent error codes and messages

**Code Examples**: JavaScript, PHP, cURL

**OpenAPI Spec**: Full specification available for Swagger/Postman
