# Quickstart – din första upplåsning

Målet: låsa upp en testenhet i STAGE med tre anrop. Bas-URL (STAGE): `https://staging.zesec.com/api`

## Förutsättningar

- Ett STAGE-API-konto (`{{phoneNumber}}` + `{{password}}`). Har du inget? Se [Få access](/docs/access) och [Från sandbox till produktion](/docs/production).
- En testenhet som ert konto har nyckel till.
- cURL, Swagger-UI eller Postman.

> **En aktiv session per konto** — En ny inloggning på samma konto avlivar den föregående sessionen. Testa inte från två klienter samtidigt, och logga in server-side i den riktiga integrationen — annars slår er egen testning ut er produktionssession.

## 1. Logga in

`POST /api/auth/login-by-phone` med telefonnummer och lösenord. Du får en access-token (JWT) och en refresh-token.

**Begäran**

_cURL_

```bash
curl -X POST https://staging.zesec.com/api/auth/login-by-phone \
  -H "Content-Type: application/json" \
  -d '{"phoneNumber": "{{phoneNumber}}", "password": "{{password}}"}'
```

_Node / TypeScript_

```typescript
const res = await fetch(`${BASE_URL}/auth/login-by-phone`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ phoneNumber: PHONE_NUMBER, password: PASSWORD }),
});
if (!res.ok) throw new Error(`login failed: ${res.status}`);
const { AccessToken, RefreshToken } = await res.json();
```

_Python_

```python
import requests

res = requests.post(
    f"{BASE_URL}/auth/login-by-phone",
    json={"phoneNumber": PHONE_NUMBER, "password": PASSWORD},
    timeout=10,
)
res.raise_for_status()
tokens = res.json()  # {"AccessToken": "...", "RefreshToken": "..."}
```

**Svar**

```json
{
  "AccessToken": "<AccessToken>",
  "RefreshToken": "<RefreshToken>"
}
```

Spara båda. Access-token används i `Authorization`-headern; refresh-token används för att förnya paret — se [Autentisering & tokens](/docs/authentication).

## 2. Hämta dina enheter

`GET /api/user/device` returnerar de enheter kontot har access till. Fältet `id` är det `{deviceId}` du behöver i steg 3.

**Begäran**

_cURL_

```bash
curl https://staging.zesec.com/api/user/device \
  -H "Authorization: Bearer <AccessToken>"
```

_Node / TypeScript_

```typescript
const res = await fetch(`${BASE_URL}/user/device`, {
  headers: { Authorization: `Bearer ${accessToken}` },
});
const devices = await res.json();
// Persist the mapping: your internal door key -> device.id
const mapping = new Map(devices.map((d) => [d.name, d.id]));
```

_Python_

```python
res = requests.get(
    f"{BASE_URL}/user/device",
    headers={"Authorization": f"Bearer {access_token}"},
    timeout=10,
)
res.raise_for_status()
mapping = {d["name"]: d["id"] for d in res.json()}
```

**Svar**

```json
[
  {
    "id": 1001,
    "name": "Door A",
    "locationId": 42,
    "locationName": "Location 1",
    "companyName": "Example Inc.",
    "doorType": "Entrance",
    "online": true
  },
  {
    "id": 1002,
    "name": "Door B",
    "locationId": 42,
    "locationName": "Location 1",
    "companyName": "Example Inc.",
    "doorType": "Garage",
    "online": true
  }
]
```

> **Mappa, cachelagra, hårdkoda inte** — Matcha `name`/`locationName` mot era egna dörrnamn en gång och spara mappningen. Se [Koncept & entitetsmodell](/docs/concepts#device-id).

## 3. Lås upp

`PUT /api/device/{deviceId}/unlock` med access-token i headern. Enheten tar emot kommandot och öppnar dörren.

**Begäran**

_cURL_

```bash
curl -X PUT https://staging.zesec.com/api/device/{deviceId}/unlock \
  -H "Authorization: Bearer <AccessToken>"
```

_Node / TypeScript_

```typescript
const res = await fetch(`${BASE_URL}/device/${deviceId}/unlock`, {
  method: "PUT",
  headers: { Authorization: `Bearer ${accessToken}` },
});
// 200 means the unlock command was accepted and forwarded to the device.
if (!res.ok) throw new UnlockFailed(res.status);
```

_Python_

```python
res = requests.put(
    f"{BASE_URL}/device/{device_id}/unlock",
    headers={"Authorization": f"Bearer {access_token}"},
    timeout=10,
)
res.raise_for_status()  # do not blind-retry: see the limits page
```

**Svar**

```text
200 OK — kommandot är accepterat och vidarebefordrat till enheten.
```

> **200 betyder accepterat, inte bekräftat öppnad** — Svaret säger att KiiOn tog emot och skickade kommandot. Vill ni verifiera tillståndet, läs enheten med `GET /api/device/{deviceId}`. Gör aldrig blind retry på unlock — se [Gränser & retry](/docs/limits).

**Vanliga fel i steg 3**
| Status | Betyder | Gör så här |
| --- | --- | --- |
| 401 | Access-token saknas eller har gått ut | Förnya via `/api/auth/refresh` och gör om anropet |
| 403 | Kontot har ingen nyckel till enheten | Kontrollera nyckeldelningen med KiiOn |
| 404 | Okänt `{deviceId}` | Hämta enhetslistan på nytt — id:t kan ha ändrats |
| 5xx | Enheten eller gatewayen svarar inte | Visa felet för användaren, retry:a inte i loop |

## Samma flöde i Swagger

1. Öppna [API-referensen](/docs/api-reference) — den renderas direkt ur `/openapi.json`.
2. Välj servern **STAGE** i serverväljaren.
3. Kör `POST /api/auth/login-by-phone` med `{{phoneNumber}}` och `{{password}}`. Kopiera `AccessToken` ur svaret.
4. Klicka **Authorize** och klistra in `Bearer <AccessToken>`.
5. Kör `GET /api/user/device` och notera `id` för testdörren.
6. Kör `PUT /api/device/{deviceId}/unlock` med det id:t.

## Samma flöde i Postman

Ladda ner [KiiOn-samlingen för Postman](/kiion-postman-collection.json) och importera den (**Import → File**). Samlingen innehåller de fyra anropen och en miljö med variablerna nedan.

1. Sätt `BASE_URL` till `https://staging.zesec.com/api`.
2. Sätt `phoneNumber` och `password` till era STAGE-uppgifter.
3. Kör **1. Login by phone** — testskriptet sparar `AccessToken` och `RefreshToken` som samlingsvariabler automatiskt.
4. Kör **2. List devices** och sätt `deviceId` till `id` för testdörren.
5. Kör **3. Unlock device**.

> **Spara aldrig riktiga uppgifter i samlingen** — Lägg `phoneNumber` och `password` i en Postman-miljö av typen *initial value: tom*, så att de inte följer med när samlingen exporteras eller delas.

## Nästa steg

- [Autentisering & tokens — proaktiv förnyelse och 401-fallback](/docs/authentication)
- [Golden path — så bygger ni integrationen robust](/docs/golden-path)
- [Hela API-referensen](/docs/api-reference)
