# `POST /api/print/invoice`

> **Endpoint:** `POST /api/print/invoice`  
> **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  
> **Rendering Engine:** Headless Microsoft Edge / Google Chrome (300 DPI)  

---

## 1. Description & Purpose

`POST /api/print/invoice` enables web applications to print rich, fully styled HTML documents directly to any physical Windows printer (inkjet, laser, or high-resolution continuous thermal rolls) **without displaying the browser print dialog (`Ctrl+P`)**.

### How It Works Under the Hood:
1. **HTML Ingestion**: Accepts a complete HTML string with embedded CSS (fonts, Flexbox/Grid, SVG logos, barcodes, tables).
2. **Sandbox Watermark Injection**: If the counter is running in a Sandbox environment, DaemonX injects top/bottom security banners and a 45° diagonal watermark before rendering.
3. **Headless Vector Rasterization**: Microsoft Edge or Google Chrome renders the HTML headlessly into an exact vector PDF at 300 DPI.
4. **Direct Spooler Dispatch**: The generated vector document is dispatched directly to the target Windows printer queue via `System.Drawing.Printing.PrintDocument`.
5. **Instant Cleanup**: All temporary PDF and image artifacts are immediately unlinked from `%TEMP%`.

---

## 2. Authentication & Required Headers

| Header Name | Type | Required | Description | Example |
| :--- | :--- | :--- | :--- | :--- |
| `Content-Type` | `string` | **Yes** | `application/json` | `application/json` |
| `Origin` | `string` | **Yes** | Web POS browser origin. Must be whitelisted in profile. | `https://pos.yourdomain.com` |
| `X-Bridge-Counter-Id` | `string` (UUID) | **Yes** | Target counter UUID registered on this workstation. | `d402ddec-ecf7-4b39-b57a-86ce6008df05` |
| `X-Bridge-Profile-Secret` | `string` | **Yes** | Counter secret issued during pairing (`dxp_...`). | `dxp_202b541b2a72ecc32867e0f62b26b...` |

---

## 3. TypeScript Contracts

```typescript
export interface InvoicePrintRequest {
  /** Target Windows printer name (from GET /api/printers) */
  printer_name: string;

  /** Full standalone HTML document string with <style> */
  html: string;

  /** Target paper format: 'A4' | 'Letter' | 'receipt_80mm'. Default: 'A4' */
  format?: 'A4' | 'Letter' | 'receipt_80mm' | string;

  /** Number of physical copies to print (1 to 10). Default: 1 */
  copies?: number;

  /** Document title displayed in Windows Print Queue. Default: 'Nyxzie POS Receipt' */
  title?: string;
}

export interface InvoicePrintResponse {
  success: boolean;
  counter_id: string;
  printer: string;
  format: string;
  pages: number;
  copies: number;
}
```

---

## 4. Parameter Matrix

| Parameter | Type | Required | Default | Validation & Description |
| :--- | :--- | :--- | :--- | :--- |
| `printer_name` | `string` | **Yes** | - | Name of target Windows printer as reported by `GET /api/printers`. |
| `html` | `string` | **Yes** | - | Valid HTML markup. Should include self-contained CSS styles. |
| `format` | `string` | No | `"A4"` | Document paper sizing: `"A4"`, `"Letter"`, or custom width. |
| `copies` | `integer`| No | `1` | Range: `1` to `10`. Each copy decrements 1 offline allowance unit when disconnected. |
| `title` | `string` | No | `"POS Receipt"` | Job title visible in Windows Spooler queue. |

---

## 5. Real-World Request & Response Examples

### Example A: Full A4 Invoice Print
**Endpoint:** `POST http://127.0.0.1:9123/api/print/invoice`

```json
{
  "printer_name": "EPSON L130 Series",
  "format": "A4",
  "copies": 1,
  "title": "Tax Invoice #INV-8891",
  "html": "<!DOCTYPE html><html><head><meta charset='utf-8'><style>body { font-family: -apple-system, sans-serif; margin: 20px; color: #111; } .header { border-bottom: 2px solid #7c3aed; padding-bottom: 12px; } .title { font-size: 24px; font-weight: 900; color: #7c3aed; } table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { padding: 10px; border-bottom: 1px solid #e5e7eb; text-align: left; } th { background: #f9fafb; font-size: 12px; text-transform: uppercase; } .total-row { font-weight: bold; font-size: 16px; }</style></head><body><div class='header'><div class='title'>STUDIO MILAN</div><div>Commercial Tax Invoice #INV-8891</div></div><table><thead><tr><th>Description</th><th>Qty</th><th>Unit Price</th><th>Total</th></tr></thead><tbody><tr><td>Italian Linen Blazer (Navy - 40R)</td><td>1</td><td>LKR 28,500.00</td><td>LKR 28,500.00</td></tr><tr><td>Custom Tailoring & Alteration</td><td>1</td><td>LKR 3,500.00</td><td>LKR 3,500.00</td></tr><tr class='total-row'><td colspan='3'>GRAND TOTAL</td><td>LKR 32,000.00</td></tr></tbody></table></body></html>"
}
```

#### Successful Response (200 OK)
```json
{
  "success": true,
  "counter_id": "d402ddec-ecf7-4b39-b57a-86ce6008df05",
  "printer": "EPSON L130 Series",
  "format": "A4",
  "pages": 1,
  "copies": 1
}
```

---

### Example B: Offline Allowance Lockout (403 Forbidden)
```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": "print_invoice"
  }
}
```

---

## 6. HTML Rendering Best Practices for Silent Spooling

To ensure pixel-perfect printing across all printer brands:

1. **Use Self-Contained Styles**:
   Do not rely on external CSS stylesheets (`<link rel="stylesheet">`) that require internet requests during rendering. Inline your CSS rules in a `<style>` block.
2. **Explicit Page Dimensions**:
   For A4 documents, set `@page { size: A4; margin: 10mm; }` in CSS.
3. **Use Web-Safe Fonts or Embedded SVGs**:
   Standard system fonts (Arial, Segoe UI, Roboto, sans-serif) render instantly without network latency. For logos and barcodes, embed SVG code or inline Base64 data URLs (`data:image/png;base64,...`).

---

## 7. Sandbox Watermarking

When connected to a **Sandbox API Key** (`nyx_daemonx_sandbox_*`), DaemonX automatically injects:
- **Red Top Banner**: `[ DAEMONX SANDBOX TEST INVOICE - NOT A VALID TAX RECEIPT ]`
- **Red Bottom Banner**: `[ TEST RECEIPT ONLY - UNAUTHORIZED FOR COMMERCIAL SALE ]`
- **Center Diagonal Watermark**: A semi-transparent 45-degree rotated box with `"DAEMONX SANDBOX - TEST RECEIPT ONLY"`.

In live environments, zero watermarks are injected.

---

## 8. Integration Snippets

### TypeScript Client Function
```typescript
export async function printInvoiceHtml(
  request: InvoicePrintRequest,
  counterId: string,
  profileSecret: string
): Promise<InvoicePrintResponse> {
  const res = await fetch('http://127.0.0.1:9123/api/print/invoice', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Bridge-Counter-Id': counterId,
      'X-Bridge-Profile-Secret': profileSecret,
    },
    body: JSON.stringify({
      format: 'A4',
      copies: 1,
      title: 'POS Receipt',
      ...request,
    }),
  });

  if (!res.ok) {
    const errorPayload = await res.json().catch(() => null);
    const detail = errorPayload?.detail;

    if (res.status === 403 && detail?.reconnect_required) {
      throw new Error(`OFFLINE_LOCKED: ${detail.message}`);
    }
    throw new Error(detail?.message || `Invoice print failed with HTTP ${res.status}`);
  }

  return (await res.json()) as InvoicePrintResponse;
}
```
