> Documentation index: https://stilldeeppos.com/llms.txt

# StillDeep SDK — Generate a POSClient in any language

> **The `.proto` contracts are public. This guide explains how to generate a client and run a sale.**

## Overview

Every POS UI client talks to `POSIntelligenceSvc` over **gRPC HTTP/2 on `localhost:50051`** (default). A sale uses these services:

| Service | Description | .proto |
|---------|-------------|--------|
| `UserService` | employee sign-in (`Authenticate`) | `user.proto` |
| `ShiftService` | open, read, pause, close the shift | `shift.proto` |
| `SalesService` | cart, payment, finalization | `sales.proto` |
| `CatalogService` | products, categories, taxes | `catalog.proto` |
| `MemberService` | members, memberships, wallets | `member.proto` |
| `DeviceService` | printers, scanners, terminals | `device.proto` |
| `EventService` | real-time stream of sale events | `events.proto` |

`DeviceService` and `EventService` are declared in the contract but not served by the current `POSIntelligenceSvc`: calls return `UNIMPLEMENTED`.

All services share the types in `common.proto` (`Money`, `Quantity`, `Percentage`, `Pagination`, ...). `sales.proto` imports `receipt.proto`, and `events.proto` imports `sales.proto` and `device.proto`: generate them together.

### Conventions

- Package `stilldeep.v1`. A V2 would be a separate package (no breaking change in V1).
- Money: **`Money { int64 cents; string currency_code; }`**. Never `double` / `float`.
- Percentages: **`Percentage { int64 basis_points; }`**, 1 basis point = 1/1,000,000.
- Quantities: **`Quantity { int64 milli_units; }`**, 1 unit = 1000 (`1500` = 1.5).
- Timestamps: `google.protobuf.Timestamp` (UTC).
- Ids are opaque strings returned by earlier calls. Never hardcode them; take the post id from your configuration.
- Errors: standard gRPC status codes, with `ErrorDetail` in `details[]` when present.

## Call sequence

Every call after `OpenShift` should carry the open shift id as gRPC metadata **`x-shift-id: <shift_id>`**. The server rejects a sensitive RPC without it (`UNAUTHENTICATED`) or with a shift that is not the open shift of this post (`PERMISSION_DENIED`).

| Step | RPC | Required | Notes |
|------|-----|----------|-------|
| 1 | `UserService.Authenticate` | yes | `post_id` (from configuration), `mode = AUTH_MODE_PASSWORD`, `login`, `password`. Keep `user.user_id`. If `must_change_password` is true, call `UserService.ChangePassword` first. |
| 2 | `ShiftService.GetCurrentShift` | optional | `post_id`. Returns the open or paused `Shift`, or `NOT_FOUND`. |
| 3 | `ShiftService.OpenShift` | yes, if step 2 returned `NOT_FOUND` | `post_id`, `user_id`, `opening_cash` (`Money`, 0 cents allowed), `idempotency_key`. Keep `shift.shift_id`. |
| 4 | `SalesService.CreateCart` | yes | `post_id`, `idempotency_key`. `cashier_user_id` optional (defaults to the shift's employee). Keep `cart.cart_id`. |
| 5 | `SalesService.AddItem` | yes, once per item | `cart_id`, one of `product_id` / `sku` / `barcode`, `quantity` (`Quantity`, defaults to 1000 = 1 unit), `idempotency_key`. |
| 6 | `SalesService.BeginPayment` | optional | `cart_id`. Moves the cart to checkout. If `CartResponse.question` is set, replay with `answers[question.code]`. |
| 7 | `SalesService.SelectPaymentMethod` | optional | `cart_id`, `method_code`. Begins payment if needed. |
| 8 | `SalesService.ProcessPayment` | yes | `cart_id`, `method_code`, `amount` (`Money`), `idempotency_key`. Selects the method and begins payment if not done. Repeat for split payments until `cart.remaining_due.cents` is 0. On `PAYMENT_STATUS_DECLINED` / `PAYMENT_STATUS_FAILED`, follow `refusal_guide`. |
| 9 | `SalesService.FinalizeTransaction` | yes | `cart_id`, `idempotency_key`. Returns `transaction` with `transaction_id` and `receipt_number`. |

Payment method codes come from `ConfigService.GetPostConfig` (`config.proto`, `payment_methods[].code`). The client never sends totals: read them from `CartResponse.cart` (`grand_total`, `remaining_due`).

`idempotency_key`: a new UUID per logical operation, reused when retrying that same operation.

## Get the `.proto` files

StillDeep's code is private; the client contract is public and versioned. The official website publishes the `.proto` files
(`stilldeep.v1`, all except `pos_proxy.proto`, reserved for posts and Server.Service) in one archive:
`/downloads/stilldeep-contracts.zip`. .NET clients use the `StillDeep.Intelligence.Contracts` NuGet package.

```bash
curl -fsSLO https://<site-address>/downloads/stilldeep-contracts.zip
unzip stilldeep-contracts.zip && cp -r stilldeep-contracts/protos ./protos
```

## Guides per language

| Language | Guide |
|----------|-------|
| TypeScript / Node.js | [`typescript.md`](https://stilldeeppos.com/docs/reference/sdk/typescript.md) |
| Python 3 | [`python.md`](https://stilldeeppos.com/docs/reference/sdk/python.md) |
| Go | [`go.md`](https://stilldeeppos.com/docs/reference/sdk/go.md) |
| .NET | use the `StillDeep.Intelligence.Contracts` NuGet package directly |

Other languages supported by official gRPC (Java, Kotlin, C++, Rust, Ruby, PHP, Dart, Swift) follow the same pattern: `protoc --proto_path=./protos --<lang>_out=./generated protos/*.proto`.

## Versioning

- **No breaking change in V1.** New fields are added as proto3 `optional`.
- A field is **never removed** before 2 major versions in deprecated state.
- A breaking change goes to a separate `stilldeep.v2.*` package.

See the [generated gRPC reference](https://stilldeeppos.com/docs/reference/grpc.md) for every service, message and call metadata.

Source: https://stilldeeppos.com/docs/reference/sdk
