Preskoči na vsebino
nalog.

Za razvijalce

Tvoji podatki, tvoj API.

Paketi Nalog MAX, Podjetje in Računovodstvo vključujejo MCP strežnik za AI asistente in REST API: potni nalogi, evidenca delovnega časa, odsotnosti in mesečni obračuni — vprašaš Claude-a ali povežeš ERP. Za MCP ti ni treba biti podjetje: dovolj je Nalog MAX. Ključ privzeto samo bere; ustvarjanje odkleneš posebej in AI tudi takrat ničesar ne uredi, ne izda in ne potrdi. Brez skritih pravil: vse, kar dostop zmore in česa ne, piše na tej strani.

MCP strežnik za AI asistente ključ = samo tvoja organizacija privzeto samo branje 120 zahtev/min na ključ uporaba iz brskalnika je blokirana

Začetek v dveh minutah

  1. 1 · Ustvari ključ — v aplikaciji: Nastavitve podjetja → API za razvijalce (lastnik ali admin). Ključ nalog_live_… se prikaže samo enkrat; hranimo zgolj njegov SHA-256.
  2. 2 · Pošlji zahtevo — ključ sodi v glavo Authorization: Bearer … in živi izključno na strežniku. Klici z brskalniškimi glavami (Sec-Fetch, Origin) so zavrnjeni, ključ pa označen kot razkrit.
  3. 3 · Določi podjetje — organizacije z enim podjetjem parameter ?company= lahko izpustijo; računovodski servisi ga podajo za vsako stranko (seznam: /v1/companies).

MCP strežnik — nalog.si v tvojem AI asistentu

Poleg REST API-ja je na isti ključ vezan tudi MCP strežnik (Model Context Protocol, Streamable HTTP). Poveži ga s Claude-om ali katerim koli MCP odjemalcem in vprašaj kar po slovensko: »koliko nadur je imela ekipa maja?« — asistent sam pokliče prava orodja.

Claude Code / CLI
claude mcp add --transport http nalog https://api.nalog.si/mcp \
  --header "Authorization: Bearer $NALOG_KEY"
Drugi MCP odjemalci (JSON konfiguracija)
{
  "mcpServers": {
    "nalog": {
      "type": "http",
      "url": "https://api.nalog.si/mcp",
      "headers": { "Authorization": "Bearer nalog_live_…" }
    }
  }
}
OrodjeKaj vrne · ✎ = ustvarja
list_companies podjetja organizacije (servisi: vse stranke)
list_members člani z vlogami in userId-ji
list_trips / get_trip potni nalogi z relacijo, km in zneski
list_time_entries evidenca delovnega časa
list_absences dopusti in bolniške
list_shift_assignments razpored: kdo je razporejen na katero delovišče po dnevih
list_sites delovišča — edini način, da dobiš siteId za create_shift_assignment
get_urnik urnik osebe ali privzeti urnik podjetja — z navedbo, kateri od obeh dejansko velja
get_pravila veljavna pravila odobritev za osebo (pravila podjetja + njene izjeme) — pojasni, zakaj je zapis čakal
monthly_summary mesečni zbir po osebah: ure, nadure, km, EUR, nalogi — iste deterministične številke kot obračun
create_trip_draft ✎ USTVARI potni nalog kot osnutek (samo ključ z obsegom pisanja)
get_member VSE o eni osebi v enem klicu: urnik, pravila, nalogi, ure, odsotnosti, razpored
describe_modules kaj aplikacija zna in kaj ima ta organizacija vklopljeno — zakaj nekdo česa ne vidi
create_shift_assignment ✎ razporedi osebo na PROST dan; obstoječega razporeda ne prepiše (samo ključ z obsegom pisanja)
create_site ✎ ustvari delovišče (samo ključ z obsegom pisanja)
invite_member ✎ povabi osebo in ji hkrati dodeli module; vrne žeton, e-pošte ne pošlje (samo ključ z obsegom pisanja)

MCP je podvržen istim pravilom kot REST: isti ključi, ista izolacija organizacije, ista zaščita pred razkritjem v brskalniku in ista omejitev 120 zahtev/min. Isti obseg ključa velja povsod: branje je odprto vsakemu veljavnemu ključu, ustvarjanje pa zahteva ključ z obsegom pisanja — v MCP in v REST enako.

Pisanje: ključ z obsegom »write«

Ključ ima obseg. Privzeto je read — takrat asistent lahko samo bere. Ob izdaji lahko izbereš write, ki odklene samo ustvarjanje. AI ne izdaja, ne ureja in ne potrjuje ničesar. Ključi, izdani pred tem, ostanejo bralni — obseg se ne podeli za nazaj.

Orodje Kaj naredi Meja
create_trip_draft Ustvari potni nalog kot osnutek. Nikoli izdan — brez zaporedne številke, dokler ga človek ne potrdi v aplikaciji.
create_shift_assignment Razporedi osebo na delovišče za en dan; oseba prejme obvestilo. Samo na PROST dan. Če je vodja tisti dan že razporedil, vrne napako in ne prepiše ničesar.
create_site Ustvari delovišče, na katero razpored kaže. Referenčni podatek: nikogar ne obvesti, ur ne premakne. Zahteva modul Razpored.
invite_member Povabi osebo in ji dodeli module — glej Povabila prek API-ja. Prek MCP samo zaposlenega (vodjo prek REST ali v aplikaciji). E-pošte ne pošljemo in nihče ni samodejno včlanjen. Dodeljeni moduli spremenijo znesek.

Pravilo, po katerem se odločamo, kaj sme AI pisati: samo tam, kjer že obstaja človekova potrditev. Zato urnika in pravil odobritev prek MCP ni mogoče spreminjati — urnik premakne normo ur in s tem saldo, pravila pa določajo, kdo je sploh podvržen nadzoru. Oboje lahko asistent bere (get_urnik, get_pravila), ne more pa spreminjati.

Pisalni ključ mora imeti tudi znanega avtorja — zapis nastane v imenu osebe, ki je ključ izdala, in zanjo veljajo iste omejitve modula, vloge in mesečnega števila nalogov kot v aplikaciji.

Povabila prek API-ja

Povabilo in dodelitev modulov sta en klic, tako kot v aplikaciji. Dvoje je vredno vedeti: e-pošte ne pošljemo — dobiš žeton in povezavo dostaviš sam, oseba pa mora povabilo sprejeti (nihče ni nikoli samodejno včlanjen); in dodeljeni moduli spremenijo znesek, ker se zaračunavajo po sedežu. Zato povabilo preverimo proti rezerviranim količinam (skupaj z že odprtimi povabili), da sprejem ne dvigne obračuna mimo rezervacije.

Prek MCP lahko povabiš samo zaposlenega, prek REST tudi vodjo; administratorja in računovodjo dodeliš izključno v aplikaciji. Razlika ni muha: klic na /v1 napiše razvijalec, klic prek MCP pa izbere model, ki je v istem pogovoru bral besedilo iz tvoje baze — namene poti, opombe razporeda. Kdor to besedilo piše, ne sme prek asistenta doseči vloge, ki bere tuje podatke ali potrjuje delo. Vsako povabilo prek ključa zato tudi sproži obvestilo lastnikom in administratorjem organizacije — rezultat orodja vidi model, obvestilo pa človek.

Zaščita pred ključem v brskalniku

Ključ, vgrajen v spletno stran, lahko prebere vsak — zato zahteve, ki pridejo iz brskalnika, zavrnemo z browser_blocked in ključ v aplikaciji označimo za zamenjavo. Prepoznamo jih po glavah, ki jih nastavi brskalnik sam in jih koda na strani ne more ne odstraniti ne ponarediti: Sec-Fetch-Site, Sec-Fetch-Dest in Origin.

Sec-Fetch-Mode namenoma NI med njimi: Node-ov vgrajeni fetch ga pošlje sam, čeprav teče na strežniku. Odjemalci MCP, ki stojijo nanj (Claude Desktop, Claude Code …), zato delujejo normalno.

REST končne točke

Vsi datumi so YYYY-MM-DD in se, tako kot v aplikaciji, razlagajo po slovenskem (stenskem) času. V primerih je $NALOG_KEY tvoj ključ.

GET /v1/absences

Dopusti, bolniške in druge odsotnosti, ki se prekrivajo z obdobjem from/to.

Zahteva
curl "https://api.nalog.si/v1/absences?from=2026-06-01&to=2026-06-30" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": [
    {
      "id": "5fc38b91-…",
      "userId": "71ac9d02-…",
      "kind": "dopust",
      "fromDate": "2026-06-22",
      "toDate": "2026-06-26",
      "hoursPerDay": null,
      "note": null
    }
  ],
  "count": 1
}
Polja odgovora
Polje Tip Pomen
data[].kind "dopust" | "bolniska" | "drugo" vrsta odsotnosti
data[].fromDate string · YYYY-MM-DD prvi dan
data[].toDate string · YYYY-MM-DD | null zadnji dan; null = do nadaljnjega
data[].hoursPerDay number | null delna bolniška (ure/dan); null = cel dan
GET /v1/companies

Podjetja organizacije. Računovodski servis tu dobi seznam vseh svojih strank.

Zahteva
curl "https://api.nalog.si/v1/companies" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": [
    {
      "id": "9b2f1c4e-…",
      "name": "TermoFin d.o.o.",
      "address": "Obrtna ulica 5, Celje",
      "taxId": "SI12345678",
      "createdAt": "2026-01-12T09:30:00.000Z",
      "managed": false,
      "clientOrgName": null
    },
    {
      "id": "3d7a0f9b-…",
      "name": "Kovinar s.p.",
      "address": "Cesta v Mestni log 12, Ljubljana",
      "taxId": "SI87654321",
      "createdAt": "2026-02-03T08:15:00.000Z",
      "managed": true,
      "clientOrgName": "Kovinar s.p."
    }
  ]
}
Polja odgovora
Polje Tip Pomen
data[].id string · uuid identifikator podjetja — uporabi ga kot ?company=
data[].name string naziv podjetja
data[].address string | null naslov sedeža
data[].taxId string | null davčna številka
data[].createdAt string · ISO 8601 kdaj je bilo podjetje dodano
data[].managed boolean true = stranka računovodskega servisa (dostop prek aktivne povezave), ne servisova lastna organizacija
data[].clientOrgName string | null naziv stranke, kadar managed = true; sicer null
POST /v1/invites

Povabi osebo v podjetje IN ji hkrati dodeli module — pravi postopek povabila v enem klicu. Zahteva ključ z obsegom pisanja in paket, ki sme vabiti (Podjetje / Računovodstvo).

Zahteva
curl -X POST "https://api.nalog.si/v1/invites" -H "Authorization: Bearer $NALOG_KEY" -H "Content-Type: application/json" -d '{"email":"ana@podjetje.si","role":"employee","modules":["cas","nalogi","voznje"]}'
Primer odgovora
{ "data": { "id": "…", "email": "ana@podjetje.si", "role": "employee", "token": "8f2c…" } }
Polja odgovora
Polje Tip Pomen
email string naslov povabljenca (obvezno)
role "manager" | "employee" privzeto employee — admin in računovodja se dodelita samo v aplikaciji (ključ ne sme ustvariti trajnega administratorja)
modules[] string[] moduli, ki jih oseba dobi ob sprejemu (cas, dnevnik, razpored, nalogi, voznje, ai, aiPro, glas) — glej describe_modules; velja le v licenčnem načinu
pkg "evidenca" | "teren" | "direktor" paket namesto naštevanja modulov
data.token string ŽETON povabila. E-pošte NE pošljemo — povezavo dostaviš sam; oseba mora povabilo sprejeti in ni nikoli samodejno včlanjena.
GET /v1/members

Člani z dostopom do podjetja. Parameter ?company= je obvezen, kadar ima organizacija več podjetij.

Zahteva
curl "https://api.nalog.si/v1/members?company=9b2f1c4e-…" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": [
    {
      "userId": "71ac9d02-…",
      "name": "Ana Kovačič",
      "email": "ana@termofin.si",
      "role": "employee"
    }
  ]
}
Polja odgovora
Polje Tip Pomen
data[].userId string · uuid identifikator osebe — uporabi ga kot ?member=
data[].name string ime in priimek
data[].email string prijavni e-naslov
data[].role "owner" | "admin" | "manager" | "employee" | "accountant" vloga v organizaciji
GET /v1/members/{userId}

VSE o eni osebi v enem klicu: profil, urnik, pravila, nalogi, ure, odsotnosti in razpored. Privzeto tekoči mesec; &from/&to za drugo obdobje, &include=urnik,pravila za manjši odgovor.

Zahteva
curl "https://api.nalog.si/v1/members/71ac9d02-…?include=urnik,pravila" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": {
    "member": { "userId": "71ac9d02-…", "name": "Ana Kovačič", "role": "employee" },
    "range": { "from": "2026-06-01", "to": "2026-06-30" },
    "urnik": { "source": "company-default" },
    "pravila": { "time": "wfh", "presenceCheck": "wfh" },
    "trips": [ { "id": "…", "status": "issued", "totalKm": 256, "totalEur": 123.96 } ],
    "tripsHasMore": false,
    "timeEntries": [], "absences": [], "shifts": []
  }
}
Polja odgovora
Polje Tip Pomen
data.member object userId, ime, e-pošta, vloga
data.range object obdobje, ki ga pokriva odgovor
data.urnik / data.pravila object veljavni urnik in veljavna pravila odobritev
data.trips / timeEntries / absences / shifts array zapisi osebe v obdobju
data.*HasMore boolean razdelek je odrezan pri 500 — zoži obdobje ali uporabi seznamsko končno točko s &limit/&offset
GET /v1/obracun/{YYYY-MM}

Mesečni obračun kot .xlsx — bajtno enak izvozu iz aplikacije (nalogi + evidenca ur + zbir po osebah). En klic na mesec in plače so pokrite.

Zahteva
curl -OJ "https://api.nalog.si/v1/obracun/2026-06?company=9b2f1c4e-…" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
HTTP/1.1 200 OK
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Disposition: attachment; filename="obracun-2026-06.xlsx"

<binarni xlsx>
Polja odgovora
Polje Tip Pomen
binary · xlsx trije listi: Obračun (nalogi), Evidenca ur, Obračun skupaj (po osebah)
GET /v1/pravila

Veljavna pravila odobritev za osebo: pravila podjetja, prepisana z njenimi izjemami. &member= je obvezen.

Zahteva
curl "https://api.nalog.si/v1/pravila?member=71ac9d02-…" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": {
    "companyId": "9b2f1c4e-…",
    "userId": "71ac9d02-…",
    "policy": {
      "time": "wfh",
      "liveClockAuto": true,
      "dopust": true,
      "bolniska": true,
      "nalog": false,
      "presenceCheck": "wfh",
      "journal": "off"
    }
  }
}
Polja odgovora
Polje Tip Pomen
data.policy.time "off" | "wfh" | "all" kateri zapisi delovnega časa potrebujejo odobritev
data.policy.liveClockAuto boolean izmene z živo uro se odobrijo same (ročni vnosi in popravki še vedno čakajo)
data.policy.nalog boolean potni nalogi potrebujejo odobritev
data.policy.presenceCheck "off" | "wfh" | "all" preverjanje prisotnosti ob prijavi; shrani se samo razsodba, nikoli koordinate
data.policy.journal "off" | "optional" | "required" | "wfh" ali izmena zahteva zapis »kaj si delal«
GET /v1/shift-assignments

Razpored — kdo je razporejen na katero delovišče, po dnevih. Neobvezno: &member=<userId>.

Zahteva
curl "https://api.nalog.si/v1/shift-assignments?from=2026-06-01&to=2026-06-30" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": [
    {
      "id": "7c9a3f10-…",
      "userId": "71ac9d02-…",
      "date": "2026-06-10",
      "siteId": "b41d8e22-…",
      "siteName": "Gradbišče Kranj",
      "note": "pridi ob 7h",
      "assignedBy": "5ac1d7f3-…"
    }
  ],
  "count": 1
}
Polja odgovora
Polje Tip Pomen
data[].userId string · uuid kdo je razporejen (glej /v1/members)
data[].date string · YYYY-MM-DD dan razporeda
data[].siteId string · uuid delovišče
data[].siteName string | null naziv delovišča; ob preimenovanju pade nazaj na posnetek ob razporeditvi
data[].note string | null opomba vodje
data[].assignedBy string · uuid | null vodja, ki je razporedil; null, če je bil račun izbrisan
POST /v1/shift-assignments

Razporedi osebo na delovišče za EN dan. Samo na prost dan — če je vodja tisti dan že razporedil, dobiš 409 in nič se ne prepiše. Oseba prejme obvestilo. Zahteva ključ z obsegom pisanja.

Zahteva
curl -X POST "https://api.nalog.si/v1/shift-assignments" -H "Authorization: Bearer $NALOG_KEY" -H "Content-Type: application/json" -d '{"member":"71ac9d02-…","siteId":"b41d8e22-…","date":"2026-06-10","note":"pridi ob 7h"}'
Primer odgovora
{ "data": { "id": "7c9a3f10-…", "siteName": "Gradbišče Kranj" } }
Polja odgovora
Polje Tip Pomen
member string · uuid koga razporediš (userId iz /v1/members) — obvezno
siteId string · uuid delovišče iz GET /v1/sites — obvezno
date string · YYYY-MM-DD dan razporeda — obvezno
note string | null opomba za osebo
409 day_already_assigned tisti dan je že razporejen; obstoječi razpored se NE prepiše
GET /v1/sites

Delovišča za razpored. Edini način, da dobiš siteId, preden razporediš osebo (POST /v1/shift-assignments). Arhivirana so izpuščena, razen z &includeArchived=true.

Zahteva
curl "https://api.nalog.si/v1/sites" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": [
    {
      "id": "b41d8e22-…",
      "name": "Gradbišče Kranj",
      "address": "Kranj",
      "lat": 46.239,
      "lng": 14.355,
      "radiusM": 200,
      "kind": "permanent",
      "archived": false
    }
  ],
  "count": 1
}
Polja odgovora
Polje Tip Pomen
data[].id string · uuid siteId za POST /v1/shift-assignments
data[].name / address string naziv in naslov delovišča
data[].lat / lng number koordinati delovišča
data[].radiusM number polmer preverjanja prisotnosti (m)
data[].kind "permanent" | "disposable" stalno ali enkratno (terensko) delovišče
data[].archived boolean arhivirano (le z &includeArchived=true)
POST /v1/sites

Ustvari delovišče za razpored. Zahteva ključ z obsegom pisanja.

Zahteva
curl -X POST "https://api.nalog.si/v1/sites" -H "Authorization: Bearer $NALOG_KEY" -H "Content-Type: application/json" -d '{"name":"Gradbišče Kranj","address":"Kranj","lat":46.239,"lng":14.355}'
Primer odgovora
{ "data": { "id": "b41d8e22-…", "name": "Gradbišče Kranj" } }
Polja odgovora
Polje Tip Pomen
name string naziv delovišča (najmanj 2 znaka)
address string naslov (obvezno)
lat / lng number koordinati; preverjanje prisotnosti meri od tod, zato sta obvezni in validirani
radiusM number polmer prisotnosti, privzeto 200 m
GET /v1/summary/{YYYY-MM}

Mesečni zbir po osebah kot JSON: ure, nadure, kilometri, povračila in število nalogov. Iste deterministične številke kot obračun v aplikaciji — brez prebiranja xlsx.

Zahteva
curl "https://api.nalog.si/v1/summary/2026-06" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": {
    "month": "2026-06",
    "members": [
      {
        "name": "Ana Kovačič",
        "hours": 168.5,
        "overtime": 4.5,
        "km": 1240,
        "eur": 533.2,
        "trips": 9
      }
    ],
    "totals": { "hours": 168.5, "overtime": 4.5, "km": 1240, "eur": 533.2, "trips": 9 }
  }
}
Polja odgovora
Polje Tip Pomen
data.month string · YYYY-MM mesec zbira
data.members[].name string ime osebe
data.members[].hours number opravljene ure v mesecu
data.members[].overtime number nadure
data.members[].km number prevoženi kilometri iz nalogov
data.members[].eur number skupno povračilo (kilometrina + dnevnice + stroški)
data.members[].trips number število nalogov
data.totals object isti ključi, sešteti čez vse osebe
GET /v1/time-entries

Evidenca delovnega časa (privzeto zadnjih 31 dni; privzeto 500, največ 2000 zapisov). Neobvezno: &member=<userId>, &limit / &offset za strani.

Zahteva
curl "https://api.nalog.si/v1/time-entries?from=2026-06-01&to=2026-06-07" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": [
    {
      "id": "ab21f6e8-…",
      "userId": "71ac9d02-…",
      "startedAt": "2026-06-01T06:00:00.000Z",
      "endedAt": "2026-06-01T14:00:00.000Z",
      "breaks": [
        { "start": "2026-06-01T10:00:00.000Z", "end": "2026-06-01T10:30:00.000Z" }
      ],
      "homeOffice": false,
      "note": null
    }
  ],
  "count": 1
}
Polja odgovora
Polje Tip Pomen
data[].id string · uuid identifikator zapisa
data[].userId string · uuid kdo je delal (glej /v1/members)
data[].startedAt string · ISO 8601 prihod
data[].endedAt string · ISO 8601 | null odhod; null = izmena še teče
data[].breaks { start, end | null }[] malice/premori znotraj izmene
data[].homeOffice boolean delo od doma
data[].note string | null opomba
GET /v1/trips

Potni nalogi po datumu izdaje (from/to, YYYY-MM-DD, vključujoče; privzeto od 1. tega meseca naprej). Neobvezno: &status=draft|confirmed|issued|settled, &member=<userId> za nalogé ene osebe, &limit / &offset za strani.

Zahteva
curl "https://api.nalog.si/v1/trips?from=2026-06-01&to=2026-06-30&member=71ac9d02-…" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": [
    {
      "id": "d41e7a55-…",
      "status": "issued",
      "sequenceNumber": 42,
      "createdBy": "71ac9d02-…",
      "issuedAt": "2026-06-08T14:02:11.000Z",
      "nalog": {
        "issueDate": "2026-06-08",
        "purpose": "Sestanek pri stranki",
        "travelMeans": "own_vehicle",
        "basis": "kilometrina",
        "country": "SI"
      },
      "itinerary": { "startAt": "…", "endAt": "…", "roundTrip": true, "legs": [] },
      "calc": {
        "totalKm": 256,
        "kilometrinaEur": 110.08,
        "dnevniceEur": 13.88,
        "totalEur": 123.96
      },
      "createdAt": "2026-06-08T07:55:00.000Z",
      "updatedAt": "2026-06-08T14:02:11.000Z"
    }
  ],
  "count": 1
}
Polja odgovora
Polje Tip Pomen
data[].id string · uuid identifikator naloga
data[].status "draft" | "confirmed" | "issued" | "settled" stanje naloga
data[].sequenceNumber number | null zaporedna številka (brez vrzeli); null pred izdajo
data[].createdBy string · uuid | null avtor (glej /v1/members)
data[].issuedAt string · ISO 8601 | null trenutek izdaje
data[].nalog object glava naloga: issueDate, purpose, travelMeans, basis, country
data[].itinerary object pot: startAt, endAt, roundTrip, legs[] (from/to/distanceKm)
data[].calc object izračun: totalKm, kilometrinaEur, dnevniceEur, stroški, totalEur
count number število vrnjenih zapisov NA TEJ STRANI
hasMore boolean obstaja še naslednja stran — ponovi z večjim &offset
limit / offset number velikost strani in odmik (privzeto 200, največ 500)
POST /v1/trips

Ustvari potni nalog kot OSNUTEK. Zahteva ključ z obsegom pisanja. Nalog NI izdan — v aplikaciji ga človek pregleda in potrdi.

Zahteva
curl -X POST "https://api.nalog.si/v1/trips" -H "Authorization: Bearer $NALOG_KEY" -H "Content-Type: application/json" -d '{"purpose":"Sestanek pri stranki","issueDate":"2026-06-08","startAt":"2026-06-08T07:40:00.000Z","legs":[{"from":"Ljubljana","to":"Maribor","distanceKm":128}]}'
Primer odgovora
{ "data": { "id": "d41e7a55-…", "status": "draft" } }
Polja odgovora
Polje Tip Pomen
purpose string namen poti (obvezno)
issueDate string · YYYY-MM-DD datum naloga (obvezno)
startAt string · ISO 8601 začetek poti (obvezno)
legs[] { from, to, distanceKm? } etape; vsaj ena (obvezno)
data.status "draft" VEDNO osnutek — izdaja ostane človekovo dejanje
GET /v1/trips/{id}

En nalog v celoti — enak objekt kot v seznamu, ovit v { data }.

Zahteva
curl "https://api.nalog.si/v1/trips/d41e7a55-…" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{ "data": { "id": "d41e7a55-…", "status": "issued", "nalog": { … }, "calc": { … } } }
Polja odgovora
Polje Tip Pomen
data object isti objekt kot element seznama /v1/trips
GET /v1/urnik

Urnik. Brez &member= vrne privzeti urnik podjetja; z &member= urnik te osebe in pove, kateri od obeh dejansko velja.

Zahteva
curl "https://api.nalog.si/v1/urnik?member=71ac9d02-…" -H "Authorization: Bearer $NALOG_KEY"
Primer odgovora
{
  "data": {
    "scope": "member",
    "userId": "71ac9d02-…",
    "source": "company-default",
    "urnik": { "izmene": [] },
    "workPattern": null,
    "dayNormMinutes": 480
  }
}
Polja odgovora
Polje Tip Pomen
data.scope "company" | "member" ali je bil zahtevan urnik podjetja ali osebe
data.source "member" | "company-default" KATERI urnik dejansko velja — odsoten urnik osebe ne pomeni »brez urnika«, ampak da podeduje privzetega
data.urnik object | null veljavna konfiguracija urnika
data.dayNormMinutes number | null dnevna norma podjetja v minutah

Napake

Pri REST (/v1) je telo napake vedno { "error": "koda" } z ustreznim HTTP statusom. Prek MCP se ista napaka vrne kot rezultat orodja z isError: true in besedilom (koda je v besedilu).

HTTPKodaPomen
401 unauthorized ključ manjka, je napačen ali preklican
403 plan_without_api paket organizacije ne vključuje API-ja (Nalog MAX / Podjetje / Računovodstvo)
403 browser_blocked zahteva je prišla iz brskalnika (glave Sec-Fetch/Origin) — ključ je razkrit v javni kodi; zahteva je zavrnjena, ključ pa v aplikaciji označen za zamenjavo
400 company_required organizacija ima več podjetij — dodaj ?company=
404 company_not_found podjetje ne obstaja ali ne pripada tvoji organizaciji
400 bad_date / bad_month datum ni YYYY-MM-DD oziroma mesec ni YYYY-MM
400 member_required orodje/pot zahteva &member=, a ga ni
404 member_not_found oseba ni član tega podjetja
404 not_found zapis ne obstaja (ali pripada drugi organizaciji — namerno ista koda)
429 rate_limited več kot 120 zahtev/min na ključ (ali zaščita pred navalom po IP); glej glavo Retry-After
403 key_is_read_only ključ nima obsega pisanja — izdaj ključ z obsegom »write«
403 module_locked organizacija ali oseba nima modula, ki ga pisanje zahteva (Nalogi / Razpored)
403 forbidden avtor ključa nima vloge za to dejanje (npr. razporeja lahko le vodja+)
403 trip_limit presežena mesečna kvota nalogov paketa
400 invalid_input: <polje> telo ne prestane validacije — sporočilo poimenuje polje (npr. legs.0.from, role)
409 day_already_assigned oseba je tisti dan že razporejena; obstoječega se ne prepiše
404 site_not_found delovišče (siteId) ne obstaja v tem podjetju

Varnost ključev

  • Ključ vidiš samo enkrat. Pri nas je shranjen izključno kot SHA-256 — nihče (niti mi) ga ne more prebrati nazaj. Izgubljen ključ prekličeš in ustvariš novega.
  • Zaščita pred razkritjem v brskalniku. Brskalniki vsaki zahtevi samodejno dodajo glave Sec-Fetch-* (JavaScript jih ne more odstraniti) in Origin. Če katera od njih prispe na /v1, ključ očitno živi v javni kodi — zahteva je zavrnjena s browser_blocked, ključ pa v aplikaciji označen z opozorilom za zamenjavo. Strežniških integracij (curl, Node, Python …) to nikoli ne prizadene.
  • Zaščito je mogoče izklopiti (Nastavitve podjetja → API za razvijalce) — z dvojno potrditvijo, ker je smiselna le za interne kioske ali Electron aplikacije. Ne priporočamo.
  • Vsaka uporaba pušča sled — čas zadnje uporabe je viden ob vsakem ključu.

Pošteno o omejitvah

  • Pisanje samo ustvarja. S ključem z obsegom write nastanejo nalog (kot osnutek), delovišče, povabilo in razpored na prost dan. Urejanje, izdaja, potrjevanje in brisanje ostanejo v aplikaciji, prav tako vpisovanje ur in odsotnosti — če to potrebuješ, se oglasi, gradimo po dejanskih potrebah.
  • Brez webhookov (zaenkrat). Spremembe pridobivaš s poizvedovanjem; za mesečne obračune zadošča en klic na mesec.
  • 120 zahtev/min na ključ. Pri prekoračitvi dobiš 429 z glavo Retry-After; trajna prekoračitev ne vodi v blokado, samo v upočasnitev.
  • Do 10 aktivnih ključev na organizacijo; vsak se prekliče z enim klikom in neha veljati takoj.
  • Seznami so straničeni (privzeto in največ: nalogi 500, ure/odsotnosti/razpored 2000 na stran) — odgovor nosi hasMore, naslednjo stran vzameš z &limit in &offset.

Manjka končna točka?

API širimo po potrebah strank — napiši nam, kaj integriraš, in povemo, kdaj (ali zakaj ne).

Piši razvojni ekipi