# API Reference

## Filters

### phynite_supported_post_types

Modify the post types that are synced.

```php
add_filter( 'phynite_supported_post_types', function( $types ) {
    // Add a custom post type
    $types[] = 'my_custom_type';
    return $types;
});
```

**Default**: `['post', 'page']` (plus recipe post types if detected)

---

### phynite_post_data

Modify the extracted post data before it's sent to the API.

```php
add_filter( 'phynite_post_data', function( $data, $post ) {
    // Add custom field
    $data['my_custom_field'] = get_post_meta( $post->ID, 'my_field', true );
    return $data;
}, 10, 2 );
```

**Parameters**:
- `$data` (array) - Extracted post data
- `$post` (WP_Post) - The post object

---

### phynite_extractors

Add or modify data extractors.

```php
add_filter( 'phynite_extractors', function( $extractors ) {
    $extractors['my_extractor'] = new My_Custom_Extractor();
    return $extractors;
});
```

---

### phynite_api_timeout

Modify API request timeout.

```php
add_filter( 'phynite_api_timeout', function( $timeout, $method ) {
    if ( $method === 'POST' ) {
        return 30; // 30 seconds for POST requests
    }
    return $timeout;
}, 10, 2 );
```

**Default**: 15 seconds for POST, 10 seconds for GET

---

### phynite_batch_size

Modify the sync batch size.

```php
add_filter( 'phynite_batch_size', function( $size ) {
    return 50; // Process 50 posts per batch
});
```

**Default**: 25

---

### phynite_rate_limit

Modify the rate limit for API requests.

```php
add_filter( 'phynite_rate_limit', function( $limit ) {
    return 30; // 30 requests per minute
});
```

**Default**: 60 requests per minute

---

### phynite_max_links_per_post

Modify the maximum number of internal links extracted per post.

```php
add_filter( 'phynite_max_links_per_post', function( $max ) {
    return 100; // Extract up to 100 links
});
```

**Default**: 200

---

## Actions

### phynite_before_sync

Fired before a post is synced.

```php
add_action( 'phynite_before_sync', function( $post_id ) {
    // Do something before sync
}, 10, 1 );
```

---

### phynite_after_sync

Fired after a post is successfully synced.

```php
add_action( 'phynite_after_sync', function( $post_id, $response ) {
    // Do something after sync
}, 10, 2 );
```

---

### phynite_sync_failed

Fired when a sync fails.

```php
add_action( 'phynite_sync_failed', function( $post_id, $error ) {
    // Handle sync failure
    error_log( "Phynite sync failed for post {$post_id}: {$error}" );
}, 10, 2 );
```

---

### phynite_bulk_sync_started

Fired when a bulk sync operation starts.

```php
add_action( 'phynite_bulk_sync_started', function( $total_posts ) {
    // Log or notify
});
```

---

### phynite_bulk_sync_completed

Fired when a bulk sync operation completes.

```php
add_action( 'phynite_bulk_sync_completed', function( $total_synced ) {
    // Log or notify
});
```

---

## Functions

### phynite_sync_post()

Manually trigger a sync for a specific post.

```php
$result = phynite_sync_post( $post_id );

if ( $result['success'] ) {
    echo 'Post synced successfully';
} else {
    echo 'Sync failed: ' . $result['error'];
}
```

---

### phynite_is_connected()

Check if the plugin is connected to the API.

```php
if ( phynite_is_connected() ) {
    // Plugin is connected
}
```

---

### phynite_get_sync_status()

Get the current sync queue status.

```php
$status = phynite_get_sync_status();
// Returns: ['pending' => 5, 'failed' => 0, 'last_sync' => 1234567890]
```

---

## REST API Endpoints

The plugin registers internal AJAX endpoints (not public REST API):

| Action | Method | Description |
|--------|--------|-------------|
| `phynite_sync_all` | POST | Start bulk sync |
| `phynite_sync_single` | POST | Sync single post |
| `phynite_get_sync_status` | POST | Get sync progress |
| `phynite_cancel_sync` | POST | Cancel bulk sync |

All endpoints require:
- User capability: `manage_options` (admin) or `edit_posts`
- Valid nonce: `phynite_sync_nonce`

---

## Data Structures

### Extracted Post Data

```php
[
    // Core fields
    'post_id'          => 123,
    'title'            => 'Post Title',
    'content'          => 'Full post content...',
    'excerpt'          => 'Post excerpt...',
    'url'              => 'https://example.com/post-slug/',
    'slug'             => 'post-slug',
    'post_type'        => 'post',
    'status'           => 'publish',
    'author_id'        => 1,
    'author_name'      => 'John Doe',
    'published_at'     => '2024-01-15T10:30:00Z',
    'modified_at'      => '2024-01-16T14:20:00Z',
    'featured_image'   => 'https://example.com/image.jpg',
    'categories'       => ['Category 1', 'Category 2'],
    'tags'             => ['tag1', 'tag2'],
    'word_count'       => 1500,
    'reading_time'     => 6,

    // SEO data (if available)
    'seo' => [
        'seo_plugin'          => 'yoast',
        'seo_plugin_version'  => '21.0',
        'seo_title'           => 'Custom SEO Title',
        'seo_description'     => 'Meta description...',
        'focus_keyword'       => 'main keyword',
        'seo_score'           => 85,
        'readability_score'   => 72,
        'canonical_url'       => null,
        'is_noindex'          => false,
        'is_nofollow'         => false,
        'schema_article_type' => 'Article',
    ],

    // Recipe data (if available)
    'recipe' => [
        'has_recipe'    => true,
        'recipe_plugin' => 'wprm',
        'recipe_count'  => 1,
        'recipes'       => [
            [
                'recipe_id'        => 456,
                'name'             => 'Chocolate Cake',
                'summary'          => 'Delicious chocolate cake...',
                'prep_time'        => 30,
                'cook_time'        => 45,
                'total_time'       => 75,
                'servings'         => '8',
                'servings_unit'    => 'servings',
                'cuisine'          => 'American',
                'course'           => 'Dessert',
                'difficulty'       => 'Medium',
                'ingredient_count' => 12,
                'calories'         => 350,
                'rating'           => 4.8,
                'rating_count'     => 125,
            ],
        ],
    ],

    // Internal links
    'internal_links' => [
        [
            'target_url'   => '/related-post/',
            'target_id'    => 789,
            'anchor_text'  => 'related post',
            'context'      => '...check out this related post for more...',
            'is_image'     => false,
        ],
    ],
    'internal_link_count' => 5,

    // Metadata
    'extracted_at'      => '2024-01-16T15:00:00Z',
    'extractor_version' => '1.0.0',
]
```

### Sync Queue Item

```php
[
    'post_id'   => 123,
    'priority'  => 'normal', // 'high' or 'normal'
    'added_at'  => 1705412400,
]
```

### Retry Queue Item

```php
[
    'post_id'    => 123,
    'attempts'   => 1,
    'last_error' => 'Connection timeout',
    'added_at'   => 1705412400,
    'next_retry' => 1705412700, // 5 minutes later
]
```
