# `GET /api/printers`

> **Endpoint:** `GET /api/printers`  
> **Auth Scope:** Profile Protected (`verify_operational_profile_access`)  
> **Target Service:** Local DaemonX Bridge Daemon (`127.0.0.1:9123`)  
> **Introduced In:** v1.0.0  
> **Last Updated:** v1.0.0  

---

## 1. Description & Purpose

`GET /api/printers` queries the host machine's Windows Print Spooler (`Win32_Printer`) and returns an inventory of all currently installed printer devices, their associated driver names, assigned hardware ports (e.g. `USB001`, `COM1`, or IP socket ports), online readiness status, and default printer flag.

Web POS applications use this endpoint in **Hardware / Register Settings** to populate printer selection dropdowns for:
- Thermal Receipt Printers (e.g., Epson TM-T82, Star TSP100, Rongta, Xprinter)
- Kitchen Order Printers (KOT)
- Full-page A4 / Letter Invoice Printers (Epson L-series, HP LaserJet, Canon)

---

## 2. Authentication & Required Headers

This endpoint requires counter credentials and verifies caller origin. It also enforces the **operational offline gate** (blocked with HTTP 403 if the workstation is offline and its emergency print allowance is exhausted).

| Header Name | Type | Required | Description | Example |
| :--- | :--- | :--- | :--- | :--- |
| `Accept` | `string` | No | `application/json` | `application/json` |
| `Origin` | `string` | **Yes** | Web POS browser origin. Must match counter's `allowed_origins`. | `https://pos.yourdomain.com` |
| `X-Bridge-Counter-Id` | `string` (UUID) | **Yes** | Counter ID registered in local DaemonX profile store. | `d402ddec-ecf7-4b39-b57a-86ce6008df05` |
| `X-Bridge-Profile-Secret` | `string` | **Yes** | Counter profile secret issued during pairing (`dxp_...`). | `dxp_202b541b2a72ecc32867e0f62b26b...` |

---

## 3. TypeScript Contracts

```typescript
export interface PrinterInfo {
  name: string;
  driver_name: string;
  port_name: string;
  status: 'Ready' | string;
  is_default: boolean;
}

export interface DaemonXPrintersResponse {
  success: boolean;
  counter_id: string;
  printers: PrinterInfo[];
}

export interface DaemonXErrorResponse {
  detail: {
    error: string;
    message: string;
    counter_id?: string;
    offline_remaining?: number;
    reconnect_required?: boolean;
    gate_reason?: string;
    operation?: string;
  };
}
```

---

## 4. Response Field Matrix

| Field | Type | Description |
| :--- | :--- | :--- |
| `success` | `boolean` | `true` when query succeeds. |
| `counter_id` | `string` | UUID of the authenticated counter profile. |
| `printers` | `PrinterInfo[]`| Array of installed Windows printer devices. |
| `printers[].name` | `string` | **Exact Windows printer name**. Pass this string to `/api/print/*` endpoints. |
| `printers[].driver_name` | `string` | Windows driver model (e.g. `"EPSON Advanced Printer Driver 6"`). |
| `printers[].port_name` | `string` | Windows hardware port (e.g. `"USB001"`, `"192.168.1.100"`, `"COM3"`). |
| `printers[].status` | `string` | `"Ready"` if online and ready to accept print spooler payloads. |
| `printers[].is_default` | `boolean` | `true` if this printer is configured as the Windows default device. |

---

## 5. Real-World Response Examples

### Example A: Successful Query (200 OK)
```json
{
  "success": true,
  "counter_id": "d402ddec-ecf7-4b39-b57a-86ce6008df05",
  "printers": [
    {
      "name": "EPSON TM-T82III Receipt",
      "driver_name": "EPSON Advanced Printer Driver 6",
      "port_name": "USB001",
      "status": "Ready",
      "is_default": true
    },
    {
      "name": "EPSON L130 Series",
      "driver_name": "EPSON L130 Series",
      "port_name": "USB002",
      "status": "Ready",
      "is_default": false
    },
    {
      "name": "Microsoft Print to PDF",
      "driver_name": "Microsoft Print To PDF",
      "port_name": "PORTPROMPT:",
      "status": "Ready",
      "is_default": false
    }
  ]
}
```

### Example B: Operational Lockout (403 Forbidden)
Returned when the workstation has been disconnected from Core and has exhausted all 30 emergency offline prints:
```json
{
  "detail": {
    "error": "DAEMONX_OFFLINE_ALLOWANCE_EXHAUSTED",
    "message": "Emergency offline allowance exhausted. Reconnect this counter to continue.",
    "counter_id": "d402ddec-ecf7-4b39-b57a-86ce6008df05",
    "offline_remaining": 0,
    "reconnect_required": true,
    "gate_reason": "OFFLINE_ALLOWANCE_EXHAUSTED",
    "operation": "profile_operation"
  }
}
```

---

## 6. Integration Snippets

### cURL
```bash
curl -X GET "http://127.0.0.1:9123/api/printers" \
  -H "X-Bridge-Counter-Id: d402ddec-ecf7-4b39-b57a-86ce6008df05" \
  -H "X-Bridge-Profile-Secret: dxp_202b541b2a72ecc32867e0f62b26b07be38024210e30af90" \
  -H "Origin: https://pos.yourdomain.com"
```

### TypeScript Client Function
```typescript
export async function getInstalledPrinters(
  counterId: string,
  profileSecret: string
): Promise<PrinterInfo[]> {
  const res = await fetch('http://127.0.0.1:9123/api/printers', {
    method: 'GET',
    headers: {
      'Accept': 'application/json',
      'X-Bridge-Counter-Id': counterId,
      'X-Bridge-Profile-Secret': profileSecret,
    },
  });

  if (!res.ok) {
    const errorData = await res.json().catch(() => null);
    if (res.status === 403 && errorData?.detail?.reconnect_required) {
      throw new Error('OFFLINE_LOCKED: Please reconnect terminal to internet.');
    }
    throw new Error(errorData?.detail?.message || `Failed to fetch printers (HTTP ${res.status})`);
  }

  const data: DaemonXPrintersResponse = await res.json();
  return data.printers;
}
```
