npm package: @ihc/terminal-cloud-api-client
Description: Vanilla TypeScript API client for Terminal Cloud
Latest version: 0.2.1

# @ihc/terminal-cloud-api-client

Vanilla TypeScript API client for Terminal Cloud. Zero external dependencies — uses native `fetch` API.

Works in Node.js, browsers, Deno, and Bun.

## Installation

```bash
npm install @ihc/terminal-cloud-api-client
```

## Quick Start

```typescript
import { createTerminalCloudClient } from "@ihc/terminal-cloud-api-client"

const client = createTerminalCloudClient({
  apiKey: "your_api_key",
})

// List terminals
const { items: terminals } = await client.terminals.list({ limit: 10 })

// Create a payment
const { id: operationId } = await client.terminals.createPayment(
  terminals[0].id,
  { amount: 1999, currency: "EUR" } // 19.99 EUR
)

// Check operation status
const operation = await client.operations.get(operationId)
console.log(operation.status) // "pending" | "completed" | "failed" | ...
```

## Configuration

```typescript
interface ClientConfig {
  /** API key for authentication */
  apiKey: string
  /** Request timeout in milliseconds (default: 30000) */
  timeout?: number
  /** Custom headers to include in all requests */
  headers?: Record<string, string>
}
```

## API Reference

### Terminals

Manage payment terminals — register devices, update configuration, and trigger payment operations.

**Required scopes:** `terminals:read` (read), `terminals:write` (create/update/delete), `terminal-actions:execute` (payment actions)

| Method | Scope | Description |
|--------|-------|-------------|
| `client.terminals.list(params?)` | `terminals:read` | Retrieve all terminals for your organization. Supports pagination and sorting. |
| `client.terminals.get(id)` | `terminals:read` | Retrieve a single terminal by its ID. |
| `client.terminals.create(data)` | `terminals:write` | Register a new terminal. Requires `name` and `terminalId` (the hardware serial number). |
| `client.terminals.update(id, data)` | `terminals:write` | Update terminal properties such as name, location, or connection settings. |
| `client.terminals.delete(id)` | `terminals:write` | Remove a terminal from your organization. |
| `client.terminals.createPayment(id, data)` | `terminal-actions:execute` | Initiate a payment on a terminal. Requires `amount` (in cents) and `currency`. |
| `client.terminals.createReversal(id, data)` | `terminal-actions:execute` | Reverse (void) a previous transaction before settlement. Requires `transactionId`. |
| `client.terminals.createRefund(id, data)` | `terminal-actions:execute` | Refund a settled transaction. Requires `transactionId`, optionally `amount` for partial refunds. |
| `client.terminals.createEndOfDay(id)` | `terminal-actions:execute` | Trigger an end-of-day settlement (Kassenschnitt). Settles all pending transactions. |
| `client.terminals.createReadCard(id)` | `terminal-actions:execute` | Read card data without initiating a payment. Useful for loyalty programs or card registration. |
| `client.terminals.createTip(id, data)` | `terminal-actions:execute` | Book a tip (gratuity) for an existing transaction. Requires `amount` (in cents) and `receiptNumber`. |
| `client.terminals.createPreAuthReversal(id, data)` | `terminal-actions:execute` | Cancel a pre-authorization. Requires `receiptNumber` of the original pre-auth. |

All terminal actions return an `OperationCreatedResponse` with the operation `id` and initial `status: "pending"`. Use `client.operations.get(id)` to poll for the result.

### Proxies

Manage terminal proxies — the software components that maintain the connection between your terminals and the cloud.

**Required scopes:** `terminal-proxies:read` (read), `terminal-proxies:write` (update/delete)

| Method | Scope | Description |
|--------|-------|-------------|
| `client.proxies.list(params?)` | `terminal-proxies:read` | Retrieve all proxies for your organization. Filterable by `status`. |
| `client.proxies.get(id)` | `terminal-proxies:read` | Retrieve a single proxy by its ID, including connection status and version info. |
| `client.proxies.update(id, data)` | `terminal-proxies:write` | Update proxy properties (e.g., `name`). |
| `client.proxies.delete(id)` | `terminal-proxies:write` | Remove a proxy from your organization. |

### Transactions

Read-only access to payment transactions. Transactions are created automatically when terminal operations complete.

**Required scope:** `transactions:read`

| Method | Scope | Description |
|--------|-------|-------------|
| `client.transactions.list(params?)` | `transactions:read` | Retrieve all transactions. Filterable by `status` (approved, declined, etc.) and `type` (payment, refund, reversal, etc.). |
| `client.transactions.get(id)` | `transactions:read` | Retrieve a single transaction with full details including card brand, amounts, and timestamps. |

### Settlements

Read-only access to end-of-day settlements. A settlement groups all transactions that were settled together.

**Required scope:** `settlements:read`

| Method | Scope | Description |
|--------|-------|-------------|
| `client.settlements.list(params?)` | `settlements:read` | Retrieve all settlements. Filterable by `status` (completed, failed). |
| `client.settlements.get(id)` | `settlements:read` | Retrieve a single settlement with transaction counts and totals. |

### Operations

Read-only access to terminal operations. Every action sent to a terminal (payment, reversal, settlement, etc.) creates an operation that tracks its lifecycle.

**Required scope:** `terminal-operations:read`

| Method | Scope | Description |
|--------|-------|-------------|
| `client.operations.list(params?)` | `terminal-operations:read` | Retrieve all operations. Filterable by `status` and `operationType`. |
| `client.operations.get(id)` | `terminal-operations:read` | Retrieve a single operation with current status, timing info, and error details if failed. |

Calling a method without the required scope throws an `AuthorizationError` (HTTP 403).

### Pagination

All list endpoints support pagination and sorting:

```typescript
const result = await client.terminals.list({
  offset: 0,    // Skip N items (default: 0)
  limit: 10,    // Max items per page (default: 10, max: 100)
  sortBy: "createdAt",
  order: "desc", // "asc" | "desc"
})

// Response shape:
// {
//   items: Terminal[],
//   pagination: { total, offset, limit, hasMore },
//   sorting: { sortBy, order }
// }
```

## Error Handling

All errors extend the `ApiError` base class:

```typescript
import {
  ApiError,
  AuthenticationError,
  AuthorizationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  NetworkError,
  TimeoutError,
  TerminalNotConnectedError,
  ProxyOfflineError,
} from "@ihc/terminal-cloud-api-client"

try {
  await client.terminals.createPayment(terminalId, { amount: 1999, currency: "EUR" })
} catch (error) {
  if (error instanceof TerminalNotConnectedError) {
    console.log(`Terminal ${error.terminalId} is not connected`)
  } else if (error instanceof ProxyOfflineError) {
    console.log(`Proxy for terminal ${error.terminalId} is offline`)
  } else if (error instanceof NotFoundError) {
    console.log(`${error.resource} not found`)
  } else if (error instanceof AuthenticationError) {
    console.log("Invalid API key")
  } else if (error instanceof RateLimitError) {
    console.log(`Rate limited, retry after ${error.retryAfter}s`)
  } else if (error instanceof ApiError) {
    console.log(`API error: ${error.code} (${error.statusCode})`)
  }
}
```

## Effect Wrapper

For Effect-TS users, see [@ihc/terminal-cloud-api-client-effect](https://www.npmjs.com/package/@ihc/terminal-cloud-api-client-effect) which provides type-safe error handling and dependency injection.

## License

See LICENSE file.