Forråd API

For udviklere og Home Assistant
API-version 1.7.0 · senest opdateret 16. oktober 2026 · Hent OpenAPI-kontrakten (YAML)

Med API'et kan scripts, Home Assistant og andre systemer læse et steds lager og, hvis du tillader det, nedskrive eller rette varer. Alt sker gennem samme versionerede API, som appen selv bruger. Siden her kan læses af alle; selve lageret kræver altid en gyldig nøgle til det konkrete sted.

Base-URL: https://lager.steen.xyz/api/v1

Kontrakten: forraad-api-v1.yaml (OpenAPI 3.1) beskriver hver rute, hvert felt og hver fejlkode. Den er den samme fil, som Forråds egne tests kontrollerer serveren mod, så den følger det, serveren faktisk gør.

1. Få en nøgle

  1. Åbn stedet i Forråd, og gå til Stedets indstillinger → Forbundne apps. Kun stedets ejer kan oprette nøgler.
  2. Tryk Ny nøgle, giv den et navn (fx "Home Assistant"), vælg hvad den må, og hvornår den udløber (30 dage til 2 år).
  3. Kopiér nøglen. Den vises kun én gang. Den begynder med fzg_.

Gem nøglen i systemets lager til hemmeligheder, fx Home Assistants secrets.yaml eller en miljøvariabel på din server. Læg den aldrig i en app, et browserprogram eller på en hjemmeside, som andre kan hente: alle med nøglen kan bruge den, indtil den udløber eller tilbagekaldes. Mister du den, så tilbagekald den under Forbundne apps og opret en ny; tilbagekaldelsen virker fra næste kald.

Send nøglen i hvert kald som Authorization: Bearer fzg_…. Den må aldrig stå i en adresse.

2. Rettigheder og adgang

Valg i appenScopesMå
Kun læseinventory:readListe opbevaringer og varer, hente en vare og dens billede.
Læse og nedskrive+ inventory:adjustOgså ændre antal (POST …/adjustments) og fortryde en ændring (POST …/undo).
Fuld adgang+ inventory:writeOgså oprette, rette og slette varer.

3. Første kald

Eksemplerne bruger to miljøvariabler. Udskift STED-ID, VARE-ID osv. med rigtige id'er fra svarene.

export FORRAAD="https://lager.steen.xyz/api/v1"
export FORRAAD_KEY="fzg_…"   # fra dit lager til hemmeligheder

# Stedet, nøglen hører til: id, navn og de aktive typer (enabledKinds)
curl -s -H "Authorization: Bearer $FORRAAD_KEY" "$FORRAAD/workspaces"

Svaret har ét sted med fx "enabledKinds": ["freezer", "fridge"]. Typerne er freezer (fryser), fridge (køleskab) og pantry (kolonial); et sted kan godt være uden fryser.

# Opbevaringerne (fx "Kummefryser", "Køleskab") med deres placeringer
curl -s -H "Authorization: Bearer $FORRAAD_KEY" "$FORRAAD/workspaces/STED-ID/storage-places"
# Det aktive lager (højst 100 pr. side); kun køleskabet med kind=fridge
curl -s -H "Authorization: Bearer $FORRAAD_KEY" "$FORRAAD/workspaces/STED-ID/items?limit=100"
curl -s -H "Authorization: Bearer $FORRAAD_KEY" "$FORRAAD/workspaces/STED-ID/items?kind=fridge&limit=100"

4. Varer, antal og datoer

Send ikke helbredsoplysninger (diagnoser, medicin, allergier) gennem API'et; varenavne og noter gemmes som almindelig tekst.

5. Nedskriv sikkert

En nedskrivning er en relativ ændring af antallet med en årsag: used (brugt), discarded (smidt ud), correction (rettelse) eller restocked (fyldt op). Den kræver rettigheden Læse og nedskrive.

# "Brugt én"
curl -s -X POST "$FORRAAD/workspaces/STED-ID/items/VARE-ID/adjustments" \
  -H "Authorization: Bearer $FORRAAD_KEY" -H "Content-Type: application/json" \
  -d '{"delta": -1, "reason": "used", "operationId": "brugt-2026-10-16-0001"}'

Svaret har den opdaterede vare og bevægelsen (movement.id).

Genforsøg uden dobbelt nedskrivning

# Fortryd en bevægelse (fx en fejlagtig nedskrivning)
curl -s -X POST "$FORRAAD/workspaces/STED-ID/movements/BEVAEGELSE-ID/undo" \
  -H "Authorization: Bearer $FORRAAD_KEY" -H "Content-Type: application/json" \
  -d '{"operationId": "fortryd-2026-10-16-0001"}'

6. Opret og ret varer

Kræver rettigheden Fuld adgang.

# Opret: Idempotency-Key gør det sikkert at prøve igen efter et tabt svar
curl -s -X POST "$FORRAAD/workspaces/STED-ID/items" \
  -H "Authorization: Bearer $FORRAAD_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: opret-2026-10-16-0001" \
  -d '{"name": "Hakket oksekød", "quantity": 2, "amount": 500, "unit": "g", "storagePlaceId": "OPBEVARING-ID", "frozenDate": "2026-10-16"}'
# Ret: send varens nuværende version; er den ændret imens, svarer API'et 409 version_conflict
curl -s -X PATCH "$FORRAAD/workspaces/STED-ID/items/VARE-ID" \
  -H "Authorization: Bearer $FORRAAD_KEY" -H "Content-Type: application/json" \
  -d '{"version": 3, "quantity": 1.5, "location": "Øverste skuffe"}'

7. Sider og synkronisering

8. Home Assistant

Med Home Assistants indbyggede rest- og rest_command-integrationer kan du vise lageret og nedskrive fra et dashboard eller en automatisering. Læg nøglen i secrets.yaml:

forraad_auth: "Bearer fzg_…"

Og i configuration.yaml (udskift STED-ID):

rest:
  - resource: "https://lager.steen.xyz/api/v1/workspaces"
    headers:
      Authorization: !secret forraad_auth
    scan_interval: 900
    sensor:
      - name: "Varer i Forråd"
        unique_id: forraad_varer
        value_template: "{{ value_json.workspaces[0].itemCount }}"

rest_command:
  forraad_brugt_en:
    url: "https://lager.steen.xyz/api/v1/workspaces/STED-ID/items/{{ item_id }}/adjustments"
    method: POST
    headers:
      Authorization: !secret forraad_auth
    content_type: "application/json"
    payload: '{"delta": -1, "reason": "used", "operationId": "ha-{{ item_id }}-{{ now().timestamp() | int }}"}'

9. Fejl og grænser

Alle fejl har formen {"error": {"code": "…", "message": "…", "details": {…}}}. message er dansk tekst til mennesker og kan ændre sig; dit program skal reagere på code.

StatusTypiske koderBetyder
401unauthenticatedNøglen mangler, er forkert, udløbet eller tilbagekaldt.
403insufficient_scopeNøglen har ikke rettigheden til kaldet.
404not_foundFindes ikke, eller hører ikke til nøglens sted.
409version_conflict, idempotency_conflict, insufficient_stock, not_undoableVaren er ændret imens, et id er brugt til noget andet, antallet ville blive negativt, eller bevægelsen kan ikke fortrydes (igen).
422invalid_requestUgyldigt indhold; details.field peger på feltet.
429rate_limitedFor mange kald; vent det antal sekunder, Retry-After siger.
503maintenanceKortvarig vedligeholdelse: skrivning afvises, i sjældne tilfælde også læsning. Prøv igen efter Retry-After sekunder.

Grænser: 120 læsninger og 60 skrivninger pr. minut pr. nøgle og sted, og 600 billedhentninger pr. minut. Den fulde liste over koder står i kontrakten.

10. Browsere og CORS

API'et sender kun CORS-headere til få, godkendte adresser (fx Overskud). CORS er en regel i browseren og giver ingen adgang: et kald kræver stadig en gyldig nøgle. Byg derfor ikke en hjemmeside, der kalder API'et direkte med en nøgle; lad din egen server kalde det.

11. Nøgler og forbundne apps

12. Kompatibilitet

Alt under /api/v1 er stabilt for integrationer:

13. Ændringslog

De vigtigste ændringer for integrationer. Hele loggen står i kontrakten.

← Tilbage til Forråd · Privatlivspolitik