# SpecFit WordPress REST API

This document covers the SpecFit plugin REST endpoints exposed by the WooCommerce plugin for Studio-driven sync, mapping, and product listing flows.

## Base URL

```text
https://your-store.com/wp-json/specfit/v1
```

## Authentication

All endpoints in this document require both:

- `X-Api-Key: <shop_api_key>`
- `plugin_reference_id`

The API key is validated against the plugin option `specfit_v10_api_key`.
The `plugin_reference_id` is validated against the plugin option `specfit_v10_plugin_reference_id`.

You can also send the API key as:

```http
Authorization: Bearer <shop_api_key>
```

Example:

```bash
curl "https://your-store.com/wp-json/specfit/v1/tryon/categories?plugin_reference_id=specfit-abc123" \
  -H "X-Api-Key: sk_live_xxx"
```

## Endpoints

### 1. List Products

```http
GET /tryon/products
```

Query params:

- `plugin_reference_id` required
- `category_id` optional WooCommerce `product_cat` term id
- `category_ids` optional comma-separated WooCommerce `product_cat` term ids
- `search` optional
- `paged` optional, default `1`
- `per_page` optional, default `25`, max `100`

Example:

```bash
curl "https://your-store.com/wp-json/specfit/v1/tryon/products?plugin_reference_id=specfit-abc123&category_id=17&paged=1&per_page=25" \
  -H "X-Api-Key: sk_live_xxx"
```

Response shape:

```json
{
  "success": true,
  "items": [
    {
      "product_id": 123,
      "source_product_id": "123",
      "parent_product_id": 0,
      "type": "variable",
      "name": "Frame A",
      "sku": "FRAME-A",
      "status": "publish",
      "price": "199",
      "image_url": "https://...",
      "permalink": "https://...",
      "sync_state": "synced",
      "remote_status": "synced",
      "local_published": true,
      "remote_published": true,
      "ready": true,
      "has_3d_assets": true,
      "remote_category_id": "cat_123",
      "last_synced_at": "2026-06-13 10:00:00",
      "categories": [],
      "variants": [
        {
          "product_id": 124,
          "source_product_id": "124",
          "parent_product_id": 123,
          "type": "variation",
          "name": "Frame A - Black",
          "sku": "FRAME-A-BLK",
          "status": "publish",
          "price": "199",
          "attributes": {
            "attribute_pa_color": "black"
          }
        }
      ]
    }
  ],
  "meta": {
    "paged": 1,
    "per_page": 25,
    "total_items": 40,
    "total_pages": 2
  }
}
```

`sync_state` values currently used:

- `synced`
- `inactive`
- `missing`
- `needs_sync`
- `checking`

### 2. Get Try-On Summary

```http
GET /tryon/summary
```

Query params:

- `plugin_reference_id` required
- `category_ids` optional comma-separated WooCommerce `product_cat` term ids

Example:

```bash
curl "https://your-store.com/wp-json/specfit/v1/tryon/summary?plugin_reference_id=specfit-abc123&category_ids=17,22" \
  -H "X-Api-Key: sk_live_xxx"
```

Response shape:

```json
{
  "success": true,
  "summary": {
    "total_products": 42,
    "requested_count": 6,
    "ready_count": 12,
    "sync_needed_count": 3
  },
  "status_counts": {
    "synced": 18,
    "inactive": 1,
    "missing": 1,
    "needs_sync": 1,
    "checking": 21
  }
}
```

### 3. List WooCommerce Categories

```http
GET /tryon/categories
```

Query params:

- `plugin_reference_id` required

Example:

```bash
curl "https://your-store.com/wp-json/specfit/v1/tryon/categories?plugin_reference_id=specfit-abc123" \
  -H "X-Api-Key: sk_live_xxx"
```

Response shape:

```json
{
  "success": true,
  "items": [
    {
      "id": "17",
      "name": "Eyeglasses",
      "slug": "eyeglasses",
      "parent_id": "0",
      "product_count": 25,
      "has_mapping": true,
      "remote_category_id": "cat_123",
      "mapping_updated_at": "2026-06-13 10:00:00"
    }
  ]
}
```

### 4. List Attribute Sources

```http
GET /tryon/attribute-sources
```

Query params:

- `plugin_reference_id` required
- `local_category_id` optional

Use this to get the available WooCommerce source fields for Studio-side mapping UI.

Example:

```bash
curl "https://your-store.com/wp-json/specfit/v1/tryon/attribute-sources?plugin_reference_id=specfit-abc123&local_category_id=17" \
  -H "X-Api-Key: sk_live_xxx"
```

Response shape:

```json
{
  "success": true,
  "local_category": {
    "id": "17",
    "name": "Eyeglasses",
    "slug": "eyeglasses",
    "parent_id": "0"
  },
  "sources": [
    { "value": "field:name", "label": "Product name" },
    { "value": "field:sku", "label": "SKU" },
    { "value": "attribute:pa_color", "label": "Attribute: Color (pa_color)" }
  ],
  "mapping": {
    "local_category_id": "17",
    "local_category_name": "Eyeglasses",
    "remote_category_id": "cat_123",
    "attribute_map": {
      "brand": "attribute:pa_brand"
    },
    "remote_attributes": [],
    "updated_at": "2026-06-13 10:00:00"
  }
}
```

### 4. Save Category Mapping

```http
POST /tryon/category-mapping
```

JSON body:

- `plugin_reference_id` required
- `local_category_id` required
- `remote_category_id` required
- `local_category_name` optional
- `attribute_map` optional object
- `remote_attributes` optional array

Example:

```bash
curl -X POST "https://your-store.com/wp-json/specfit/v1/tryon/category-mapping" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: sk_live_xxx" \
  -d '{
    "plugin_reference_id": "specfit-abc123",
    "local_category_id": 17,
    "local_category_name": "Eyeglasses",
    "remote_category_id": "cat_123",
    "attribute_map": {
      "brand": "attribute:pa_brand",
      "model_name": "field:name"
    },
    "remote_attributes": [
      { "name": "brand" },
      { "name": "model_name" }
    ]
  }'
```

Response shape:

```json
{
  "success": true,
  "message": "Attribute mapping saved successfully.",
  "mapping": {},
  "savedMappings": {}
}
```

### 5. Delete Category Mapping

```http
DELETE /tryon/category-mapping
```

Params:

- `plugin_reference_id` required
- `local_category_id` required

Example:

```bash
curl -X DELETE "https://your-store.com/wp-json/specfit/v1/tryon/category-mapping?plugin_reference_id=specfit-abc123&local_category_id=17" \
  -H "X-Api-Key: sk_live_xxx"
```

Response shape:

```json
{
  "success": true,
  "message": "Category mapping removed successfully.",
  "savedMappings": {}
}
```

### 6. Sync Product Status

```http
POST /tryon/sync-product
```

JSON body:

- `plugin_reference_id` required
- `product_id` optional
- `source_product_id` optional

One of `product_id` or `source_product_id` must be sent. In current plugin behavior, this is the local WooCommerce product id.

This endpoint does not publish products to Studio. It reads Studio sync status through the plugin API and writes Try-On state back to WooCommerce. Variable products are synced per variation; the parent only stores an aggregate status.

Example:

```bash
curl -X POST "https://your-store.com/wp-json/specfit/v1/tryon/sync-product" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: sk_live_xxx" \
  -d '{
    "plugin_reference_id": "specfit-abc123",
    "source_product_id": 123
  }'
```

Response shape:

```json
{
  "success": true,
  "message": "Variant Try On statuses synchronized.",
  "product_id": 123,
  "source_product_id": "123",
  "synced": true,
  "ready": true,
  "remote_status": "synced",
  "tryon_status": "ready",
  "items": [
    {
      "source_product_id": "124",
      "parent_source_product_id": "123",
      "remote_status": "synced",
      "product_status": "ready",
      "tryon_status": "ready",
      "tryon_image_url": "https://images.trynshop.com/.../tryon.png",
      "ready": true
    }
  ]
}
```

### 7. Sync Variant Try-On Status and Images

```http
POST /tryon/sync-images
```

JSON body:

- `plugin_reference_id` required
- `source_product_ids` required array

This endpoint uses Studio sync status and saves ready variant image URLs from that response. It does not fall back to all products; callers must send the product ids they want to refresh.

Example:

```bash
curl -X POST "https://your-store.com/wp-json/specfit/v1/tryon/sync-images" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: sk_live_xxx" \
  -d '{
    "plugin_reference_id": "specfit-abc123",
    "source_product_ids": [123, 124]
  }'
```

Response shape:

```json
{
  "success": true,
  "message": "Synchronized 2 ready Try On variants from 2 variants.",
  "requested_count": 2,
  "saved_count": 2,
  "items": [
    {
      "source_product_id": "123",
      "remote_status": "synced",
      "product_status": "ready",
      "tryon_status": "ready",
      "tryon_image_url": "https://...",
      "ready": true
    }
  ],
  "ready_map": {
    "123": true,
    "124": false
  }
}
```

## Product Readiness and Metadata

The plugin does not store one single `3d_ready=true` meta flag.

Current readiness is derived from product status and assets:

- `specfit_product_try_on_color_keys`
- `try_on_image_specfit_platinum`
- `_specfit_tryon_image_url`
- `_specfit_tryon_remote_ready_state`
- `_specfit_tryon_status=ready`

Saved category mapping only allows publishing/requesting Try-On. It does not make a product ready.

The main synced Try On image metadata currently used is:

- `_specfit_tryon_image_url`
- `_specfit_tryon_image_payload`
- `_specfit_tryon_image_synced_at`

The main remote sync metadata currently used is:

- `_specfit_tryon_remote_status`
- `_specfit_tryon_remote_product_status`
- `_specfit_tryon_status`
- `_specfit_tryon_remote_published`
- `_specfit_tryon_published`
- `_specfit_tryon_last_sync_at`
- `_specfit_tryon_remote_ready_state`

## Recommended Studio Flow

1. Call `GET /tryon/categories`
2. Call `GET /tryon/attribute-sources?local_category_id=...`
3. Save mapping with `POST /tryon/category-mapping`
4. List products with `GET /tryon/products`
5. Sync a product with `POST /tryon/sync-product`
6. Refresh selected product/variant status and ready image URLs with `POST /tryon/sync-images`

## Notes

- All calls must be made over HTTPS.
- These APIs are intended for server-to-server or trusted iframe-backed Studio flows.
- Do not expose the store API key in frontend browser code outside your controlled embedded flow.
