# SDK reference — overview The SDK is the set of functions your Rhai scripts can call. It comes in two layers: - **Services** — stateful, app-scoped capabilities backed by the platform: `kv`, `docs`, `files`, `http`, `email`, `users`, `pubsub`, `queue`, `secrets`, `invoke`, `retry`, `dead_letters`, and `log`. These appear and disappear with releases (each is tagged with the SDK minor that added it). - **Standard library** — pure, stateless helpers: `json`, `base64`, `hex`, `url`, `regex`, `random`, `time`. See [Standard library](stdlib.md). This page covers the conventions that hold across *every* service. The per-service pages give exact signatures. ## Namespacing and the handle pattern Functions live in namespaces, called with `::`: ```rhai let id = random::uuid(); log::info("hi"); ``` Storage services are **collection-scoped**: you first get a *handle* to a named collection, then call methods on it. This is intentional — it makes the `(app, collection, key)` identity explicit. ```rhai let users = docs::collection("users"); // handle let id = users.create(#{ name: "Ada" }); // method on the handle let doc = users.get(id); ``` So it's `kv::collection("x").get(k)`, **not** `kv::get("x", k)`. Collections are mandatory; a collection name may not be empty. ## App scoping is automatic and non-negotiable Every service call resolves the app from the server-side execution context. **Nothing your script passes can change which app's data it touches** — there is no `app_id` argument anywhere in the SDK. This is the isolation boundary described in [Core concepts](../../guide/concepts.md#apps); treat it as a hard guarantee, not a convention. ## Error conventions Uniform across all services (also covered in [Writing scripts](../../guide/writing-scripts.md#errors)): | Situation | Behavior | |---|---| | Real failure (DB error, payload too large, authorization denied) | **throws** — catch with `try/catch`, or let it become a 502 | | Item not found / no result | returns **`()`** — test `== ()` | | Existence / was-present check | returns a **`bool`** | ## Value encoding Values you store or send are JSON-encoded on the wire: - Maps, arrays, strings, numbers, booleans round-trip cleanly. - `()` (Rhai unit) becomes JSON `null`. - **Blobs** (byte arrays, e.g. from `base64::decode`) are base64-encoded inside JSON payloads (`pubsub`, `queue`). `files` stores raw bytes directly. - **Function pointers / closures cannot be serialized** and are rejected by `queue`, `invoke`, etc. ## Size caps Several services cap payload size to protect Postgres. Defaults (all tunable, see [env vars](../config/env-vars.md)): | Service | Env var | Default | |---|---|---| | `kv` value | `PICLOUD_KV_MAX_VALUE_BYTES` | 256 KiB | | `docs` document | `PICLOUD_DOCS_MAX_VALUE_BYTES` | 256 KiB | | `pubsub` message | `PICLOUD_PUBSUB_MAX_MESSAGE_BYTES` | 256 KiB | | `queue` message | `PICLOUD_QUEUE_MAX_PAYLOAD_BYTES` | 256 KiB | | `files` blob | `PICLOUD_FILES_MAX_FILE_SIZE_BYTES` | 100 MiB | Exceeding a cap **throws**. For `kv`/`queue` the size is checked *before* authorization so a public script can't be used to hammer the database. ## The full surface at a glance | Namespace | Since SDK | Page | |---|---|---| | `log` | 1.0 | [Writing scripts](../../guide/writing-scripts.md#logging) | | `kv` | 1.2 | [Storage](storage.md#kv) | | `docs` | 1.3 | [Storage](storage.md#docs) | | `files` | 1.6 | [Storage](storage.md#files) | | `http` | 1.5 | [Outbound HTTP](http.md) | | `pubsub` | 1.6 / 1.7 | [Messaging](messaging.md#pubsub) | | `secrets`, `email` | 1.8 | [Secrets](secrets.md), [Email](email.md) | | `users` | 1.9 | [Users & auth](users.md) | | `queue`, `invoke`, `retry` | 1.10 | [Messaging](messaging.md#queue), [Composition](composition.md) | | `dead_letters` | 1.2 | [Composition](composition.md#dead-letters) | | `json` `base64` `hex` `url` `regex` `random` `time` | 1.0 | [Standard library](stdlib.md) | Many services also have an **admin/inspection** side on the HTTP API and the `pic` CLI (e.g. browse KV, download files, read secret names). Those are read-mostly; *writing* data is the script's job. Each SDK page links to its admin counterpart.