# ZIPLINE > Zipline hosts personal Zero-Trust Packet Routing (ZPR) networks. Machines join a network by > running an adapter; nothing reaches anything until a rule allows it. Everything a user can do > in the web UI is also available over a REST/JSON API under `/api/v1` on this host. Operations written as `METHOD /path` (`GET /network`, `POST /rules`) are relative to the API base `/api/v1`: `GET /network` is `GET https:///api/v1/network`. Every other path that starts with `/api/` (the contract, the downloads) is relative to this host. ## Start here - [OpenAPI contract](/api/v1/openapi.json): every operation, schema and error code. No token needed to fetch it. It is large (~150 KB); read `info.description` first, then look up operations as you need them. ## Authentication - Send `Authorization: Bearer zl_…` on every call. - A human creates the first token on the web UI's "API Tokens" page. An agent cannot bootstrap one on its own, and an ADMIN token can only be made in the UI. - A token is bound to one network and acts only in it, with its user's role in that network. A call needs both a high enough token level and a high enough role (each operation lists `x-allowed-levels` and, if it has one, `x-minimum-role`). - Levels: READ_ONLY < READ_WRITE < ADMIN. ENROLL can only confirm a registration and revoke itself. - Roles: OWNER > MANAGER > CONTRIBUTOR (CONTRIBUTOR adds adapters and manages the ones they added). ## Concepts Words here have ZPR meanings, not their usual networking meanings. - **Network**: one user's ZPR network (a ZPRnet). Deny by default. - **Adapter**: one machine joined to the network. Has an immutable name (`adapter-17l13u`) and an editable display name (`work-laptop`); both resolve in DNS under the network's zone. - **Tag**: a label in the network's tag catalog. A *device tag* goes on adapters; a *user tag* goes on members and applies to every adapter that member added. A name is one kind, never both. - **Service**: a protocol and ports (`tcp` `22`) offered by a host. The host is an adapter, a device tag, or `any`. Start from `GET /service-catalog` (ssh, web, http, https, rdp, smb, vnc, ping) or give a custom protocol and ports. - **Rule** (an "Access Policy" in the UI): `allow` or `never` a subject (an adapter, a device tag, a user tag, or `any`) to reach one service. `never` overrides `allow`. - **Policy**: all rules compiled into ZPL, ZPR's policy language, and pushed to the network. Creating or deleting a service or rule compiles and pushes. The policy can be ejected to hand-written ZPL (`POST /policy/eject`); that is one-way until `POST /policy/restore`, which drops the hand edits. - **Visa**: ZPR's permission for one flow. **Deny**: a refused visa request. Both are listed per adapter and are how you check whether a rule works. - **Member / Invitation**: other users join a network by accepting an emailed invitation. ## Recipes Let devices tagged `laptops` reach SSH on devices tagged `servers`: 1. `POST /adapters/{name}/tags` `{"tag": "servers"}` on each server, and `{"tag": "laptops"}` on each laptop. New tags enter the catalog as device tags. 2. `POST /services` `{"name": "ssh", "host": {"kind": "device.tags", "value": "servers"}, "catalog": "ssh"}` 3. `POST /rules` `{"effect": "allow", "subject": {"kind": "device.tags", "value": "laptops"}, "service": "ssh"}` 4. Check: `GET /adapters/{name}/visas` and `GET /adapters/{name}/denies`. Let everyone in the network ping one machine: create a service with `"catalog": "ping"` and `"host": {"kind": "device", "value": ""}`, then a rule with `"subject": {"kind": "any"}`. Add a machine without a browser: create an ENROLL token (`POST /tokens` `{"name": "...", "level": "ENROLL"}`; needs an ADMIN token), install the adapter package from `/api/download/linux`, `/api/download/macos` or `/api/download/windows` on the machine, then run `zipline register` elevated with the token in `ZIPLINE_TOKEN`. Never put the token on a command line, where `ps` and shell history keep it; `zipline register --help` shows how to read it without echo and pass it through `sudo` (Linux, macOS) or an Administrator PowerShell (Windows). Add `--revoke-token` to revoke it afterwards. Without a token, `zipline register` prints a code and an approval URL instead; approve it with `POST /registrations/{code}/confirm`. Inspect: `GET /network`, `GET /adapters`, `GET /rules` (includes each rule's ZPL), `GET /policy` (the whole compiled policy). ## Errors - Every error is `{"error": "", "code": ""}`. Branch on `code`. - `422 compile_failed`: the change would not compile; nothing was saved. - `502 push_failed`: the change *was* saved but not made live. Do not retry the same create; read the state back. - `409 needs_confirmation`: deleting a tag that devices or members carry; repeat with `?confirmDeviceCount=` or `?confirmMemberCount=` set to the count the error returns. - `409 in_use`: a service or rule still uses the tag; delete those first. On a network whose policy is ZPL, `usedBy.zpl` lists the ZPL attributes that name the tag; edit those out first. - `409 policy_changed`: the network changed while the policy was compiled; nothing was saved. Retry the same request. - `409 network_not_running`: the network exists but is stopped or starting; check `GET /network`. - Unknown request fields are rejected with 400. ## What the API cannot do - Create the first token or any ADMIN token (UI only). - Install software on a machine. Joining a machine needs `zipline register` run on it. - Act in more than one network per token. Use one token per network.