{"openapi":"3.1.0","info":{"title":"PlugCharge Partner API","version":"1.0.0","summary":"Čítacie API pre účtovné a ERP systémy — partneri, doklady, relácie.","description":"Rozhranie pre externé systémy, ktoré si potrebujú stiahnuť účtovné dáta operátora nabíjacích staníc (CPO).\n\n**Len čítanie.** Žiadny endpoint nič nevytvára ani nemení. Doklady sa cez toto API vystaviť nedajú — číselný rad a finančná história sú nemenné.\n\n**Rozsah dát nesie kľúč.** Každý API kľúč patrí jednému operátorovi a vracia výhradne jeho dáta. Tenant sa nikdy neurčuje parametrom požiadavky.\n\n**Dva formáty.** Každý čítací endpoint vracia JSON alebo XML (`?format=xml`). XML je zrkadlom JSON — jednoduchý tvar bez menných priestorov; polia sú obalené do elementov s rovnakými názvami, zoznamy do opakovaného elementu.\n\n**Ako začať:** kľúč (`client_id` + `client_secret`) si vytvorí správca operátora v CPO portáli (Nastavenia → Fakturácia → API kľúče). Secret sa zobrazí jedinýkrát.","contact":{"name":"PlugCharge","url":"https://plugcharge.eu","email":"hello@plugcharge.eu"}},"servers":[{"url":"https://api.plugcharge.eu/api/v1","description":"Produkcia"}],"tags":[{"name":"Autentifikácia","description":"OAuth 2.0 client_credentials. Token platí 15 minút; kľúč sa overuje raz, potom sa používa token."},{"name":"Partneri","description":"Protistrany dokladov — zákazníci (firmy aj fyzické osoby) a operátori, ktorým bol vystavený doklad."},{"name":"Doklady","description":"Vystavené faktúry vrátane položiek a rekapitulácie DPH."},{"name":"Relácie","description":"Nabíjacie relácie — podklad pre nákladové strediská."},{"name":"Dokumentácia","description":"Verejné, bez autentifikácie."}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"Vymeňte `client_id` + `client_secret` za prístupový token na `POST /oauth/token`. Token je nepriehľadný (nie JWT) a nedá sa použiť mimo tohto API.","flows":{"clientCredentials":{"tokenUrl":"https://api.plugcharge.eu/api/v1/oauth/token","scopes":{"partners:read":"Čítanie partnerov","invoices:read":"Čítanie dokladov","sessions:read":"Čítanie relácií"}}}},"bearer":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer <access_token>`"}},"schemas":{"Chyba":{"type":"object","properties":{"error":{"type":"string","description":"Kód chyby podľa RFC 6749 §5.2 alebo `not_found` / `server_error`."},"error_description":{"type":"string"}},"required":["error"]},"Token":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer","description":"Sekundy. Aktuálne 900 (15 minút)."},"scope":{"type":"string","description":"Udelené rozsahy oddelené medzerou."}},"required":["access_token","token_type","expires_in","scope"]},"Partner":{"type":"object","description":"Protistrana dokladu. Vracajú sa LEN subjekty, ktorým reálne vznikol doklad — nie celá databáza zákazníkov.","properties":{"id":{"type":"string","description":"Stabilný identifikátor s prefixom zdroja: `u:<uuid>` zákazník, `t:<uuid>` operátor (CPO).","example":"u:3f9c1e2a-…"},"typ":{"type":"string","enum":["firma","osoba","cpo"]},"nazov":{"type":["string","null"],"description":"Názov firmy, alebo meno a priezvisko pri fyzickej osobe."},"ico":{"type":["string","null"]},"dic":{"type":["string","null"],"description":"DIČ — daňové identifikačné číslo (má ho každý daňový subjekt)."},"ic_dph":{"type":["string","null"],"description":"IČ DPH — identifikátor platcu DPH (len platca)."},"ulica":{"type":["string","null"]},"psc":{"type":["string","null"]},"mesto":{"type":["string","null"]},"stat":{"type":["string","null"],"description":"ISO 3166-1 alpha-2, napr. `SK`."},"email":{"type":["string","null"],"description":"Pri operátorovi (`typ = cpo`) je null."},"posledny_doklad":{"type":"string","format":"date-time","description":"Dátum posledného dokladu — kotva pre inkrementálny sync (`?od=`)."},"pocet_dokladov":{"type":"integer"}},"required":["id","typ","posledny_doklad","pocet_dokladov"]},"Doklad":{"type":"object","description":"Vystavený doklad. Návrhy (`draft`) sa nikdy nevracajú. Sumy sú desatinné čísla s bodkou, bez ohľadu na locale.","properties":{"id":{"type":"string","format":"uuid"},"invoice_number":{"type":"string","description":"Číslo dokladu — unikátne v rámci fakturujúceho subjektu. Toto je kľúč pre `GET /invoices/{cislo}`."},"type":{"type":"string","description":"`charging` | `pausal` | `platform_fee` | …"},"status":{"type":"string","enum":["issued","paid","overdue","cancelled"],"description":"`overdue` je odvodený: `issued` po dátume splatnosti."},"issue_date":{"type":["string","null"],"format":"date"},"due_date":{"type":["string","null"],"format":"date"},"paid_at":{"type":["string","null"],"format":"date-time"},"currency":{"type":"string","example":"EUR"},"amount":{"type":"number","description":"Celková suma s DPH."},"amount_paid":{"type":"number"},"variable_symbol":{"type":["string","null"]},"vat_mode":{"type":["string","null"]},"period_from":{"type":["string","null"],"format":"date"},"period_to":{"type":["string","null"],"format":"date"},"customer_email":{"type":["string","null"]},"recipient_tenant":{"type":["string","null"],"description":"Názov operátora, ak je odberateľom CPO."},"net_total":{"type":["number","null"]},"vat_total":{"type":["number","null"]},"rounding":{"type":["number","null"]},"supplier_name":{"type":["string","null"]},"supplier_ico":{"type":["string","null"]},"supplier_vat_id":{"type":["string","null"]},"customer_name":{"type":["string","null"]},"customer_ico":{"type":["string","null"]},"customer_vat_id":{"type":["string","null"],"description":"IČ DPH odberateľa platné K DÁTUMU VYSTAVENIA (z registra DPH registrácií)."},"customer_address":{"type":["string","null"]},"cancelled_at":{"type":["string","null"],"format":"date"},"cancel_reason":{"type":["string","null"]},"pdf_key":{"type":["string","null"],"description":"Interný kľúč PDF; samotné PDF sa cez toto API nevracia."}},"required":["id","invoice_number","type","status","currency","amount","amount_paid"]},"DokladDetail":{"allOf":[{"$ref":"#/components/schemas/Doklad"},{"type":"object","properties":{"polozky":{"type":"array","items":{"$ref":"#/components/schemas/DokladPolozka"}},"rekapitulacia_dph":{"type":"array","items":{"$ref":"#/components/schemas/RekapitulaciaDph"}}},"required":["polozky","rekapitulacia_dph"]}]},"DokladPolozka":{"type":"object","properties":{"invoice_number":{"type":"string"},"sort_order":{"type":"integer"},"item_kind":{"type":"string"},"description":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":["string","null"]},"unit_price":{"type":"number"},"net_amount":{"type":"number"},"vat_rate":{"type":"number","description":"Sadzba v percentách, napr. `23`."},"vat_amount":{"type":"number"},"gross_amount":{"type":"number"}},"required":["invoice_number","sort_order","description","quantity","unit_price","net_amount","vat_rate","vat_amount","gross_amount"]},"RekapitulaciaDph":{"type":"object","description":"Jeden riadok na dvojicu (doklad, sadzba DPH) — základ a daň za každú sadzbu zvlášť, tak ako ide do priznania.","properties":{"invoice_number":{"type":"string"},"currency":{"type":"string"},"vat_rate":{"type":"number"},"net_amount":{"type":"number"},"vat_amount":{"type":"number"},"gross_amount":{"type":"number"}},"required":["invoice_number","currency","vat_rate","net_amount","vat_amount","gross_amount"]},"Relacia":{"type":"object","description":"Nabíjacia relácia — podklad pre nákladové strediská. Bez identifikátora karty: RFID UID je autentifikačný kredenciál a do účtovného exportu nepatrí.","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"kwh":{"type":["number","null"]},"final_price":{"type":["number","null"]},"currency":{"type":["string","null"]},"lokalita":{"type":["string","null"],"description":"Názov lokality (stanice)."},"mesto":{"type":["string","null"]},"partner_id":{"type":["string","null"],"description":"Odkaz na partnera (`u:<uuid>`), ak je relácia viazaná na zákazníka."}},"required":["id","status","started_at"]}}},"security":[{"bearer":[]}],"paths":{"/oauth/token":{"post":{"tags":["Autentifikácia"],"operationId":"vydajToken","summary":"Vydanie prístupového tokenu","description":"OAuth 2.0 `client_credentials`. Telo môže byť `application/json` alebo `application/x-www-form-urlencoded`. Neznámy kľúč aj zlý secret vracajú tú istú odpoveď 401 — kľúče sa nedajú vyčítavať. Limit 20 pokusov za 5 minút.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"grant_type":{"type":"string","enum":["client_credentials"]},"client_id":{"type":"string","example":"pc_9f2b…"},"client_secret":{"type":"string"}},"required":["grant_type","client_id","client_secret"]}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"grant_type":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"}}}}}},"responses":{"200":{"description":"Token. Odpoveď má `Cache-Control: no-store`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"400":{"description":"`unsupported_grant_type`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"401":{"description":"`invalid_client`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"429":{"description":"Prekročený limit požiadaviek (120/min na kľúč).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}}}}},"/partners":{"get":{"tags":["Partneri"],"operationId":"zoznamPartnerov","summary":"Zoznam partnerov","description":"Protistrany dokladov operátora, zoradené podľa posledného dokladu. Na inkrementálny sync použite `?od=` — vráti len partnerov s dokladom od daného dátumu.","security":[{"bearer":["partners:read"]}],"parameters":[{"name":"od","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Len partneri s dokladom od tohto dátumu (YYYY-MM-DD)."},{"name":"typ","in":"query","required":false,"schema":{"type":"string","enum":["firma","osoba","cpo"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","xml"]},"description":"Formát odpovede. `xml` má prednosť pred hlavičkou `Accept`. Predvolené `json`."}],"responses":{"200":{"description":"Zoznam partnerov.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Partner"}}},"application/xml":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Partner"}},"example":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<partneri>\n  <partner>…</partner>\n</partneri>"}}},"401":{"description":"Chýbajúci, neplatný, expirovaný alebo odvolaný token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"403":{"description":"Kľúč nemá potrebný rozsah (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"429":{"description":"Prekročený limit požiadaviek (120/min na kľúč).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}}}}},"/partners/{id}":{"get":{"tags":["Partneri"],"operationId":"detailPartnera","summary":"Detail partnera","security":[{"bearer":["partners:read"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Identifikátor vrátane prefixu, napr. `u:3f9c…` alebo `t:8a1d…`."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","xml"]},"description":"Formát odpovede. `xml` má prednosť pred hlavičkou `Accept`. Predvolené `json`."}],"responses":{"200":{"description":"Partner.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}},"application/xml":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"401":{"description":"Chýbajúci, neplatný, expirovaný alebo odvolaný token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"403":{"description":"Kľúč nemá potrebný rozsah (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"404":{"description":"Partner neexistuje alebo nepatrí tomuto operátorovi. Odpoveď je rovnaká v oboch prípadoch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"429":{"description":"Prekročený limit požiadaviek (120/min na kľúč).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}}}}},"/invoices":{"get":{"tags":["Doklady"],"operationId":"zoznamDokladov","summary":"Zoznam dokladov","description":"Vystavené doklady operátora. Obdobie sa filtruje podľa dátumu vystavenia. Zoznam neobsahuje položky — tie vracia detail.","security":[{"bearer":["invoices:read"]}],"parameters":[{"name":"od","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Od dátumu vystavenia (YYYY-MM-DD)."},{"name":"do","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Do dátumu vrátane (YYYY-MM-DD)."},{"name":"stav","in":"query","required":false,"schema":{"type":"string","enum":["issued","paid","overdue","cancelled"]}},{"name":"typ","in":"query","required":false,"schema":{"type":"string"},"description":"`charging` | `pausal` | `platform_fee` | …"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","xml"]},"description":"Formát odpovede. `xml` má prednosť pred hlavičkou `Accept`. Predvolené `json`."}],"responses":{"200":{"description":"Zoznam dokladov.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Doklad"}}},"application/xml":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Doklad"}},"example":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<doklady>\n  <doklad>…</doklad>\n</doklady>"}}},"401":{"description":"Chýbajúci, neplatný, expirovaný alebo odvolaný token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"403":{"description":"Kľúč nemá potrebný rozsah (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"429":{"description":"Prekročený limit požiadaviek (120/min na kľúč).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}}}}},"/invoices/{cislo}":{"get":{"tags":["Doklady"],"operationId":"detailDokladu","summary":"Detail dokladu s položkami a rekapituláciou DPH","description":"Adresuje sa ČÍSLOM dokladu, nie interným UUID — číslo je to, čo je na doklade a čo ERP pozná.","security":[{"bearer":["invoices:read"]}],"parameters":[{"name":"cislo","in":"path","required":true,"schema":{"type":"string"},"example":"PLG202500042"},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","xml"]},"description":"Formát odpovede. `xml` má prednosť pred hlavičkou `Accept`. Predvolené `json`."}],"responses":{"200":{"description":"Doklad s položkami.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DokladDetail"}},"application/xml":{"schema":{"$ref":"#/components/schemas/DokladDetail"}}}},"401":{"description":"Chýbajúci, neplatný, expirovaný alebo odvolaný token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"403":{"description":"Kľúč nemá potrebný rozsah (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"404":{"description":"Doklad neexistuje alebo nepatrí tomuto operátorovi.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"429":{"description":"Prekročený limit požiadaviek (120/min na kľúč).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}}}}},"/sessions":{"get":{"tags":["Relácie"],"operationId":"zoznamRelacii","summary":"Zoznam nabíjacích relácií","security":[{"bearer":["sessions:read"]}],"parameters":[{"name":"od","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Od začiatku relácie (YYYY-MM-DD)."},{"name":"do","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Do dátumu vrátane (YYYY-MM-DD)."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["json","xml"]},"description":"Formát odpovede. `xml` má prednosť pred hlavičkou `Accept`. Predvolené `json`."}],"responses":{"200":{"description":"Zoznam relácií.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Relacia"}}},"application/xml":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Relacia"}},"example":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<relacie>\n  <relacia>…</relacia>\n</relacie>"}}},"401":{"description":"Chýbajúci, neplatný, expirovaný alebo odvolaný token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"403":{"description":"Kľúč nemá potrebný rozsah (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}},"429":{"description":"Prekročený limit požiadaviek (120/min na kľúč).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chyba"}}}}}}},"/openapi.json":{"get":{"tags":["Dokumentácia"],"operationId":"openapi","summary":"Táto špecifikácia (OpenAPI 3.1, JSON)","security":[],"responses":{"200":{"description":"OpenAPI dokument."}}}},"/docs":{"get":{"tags":["Dokumentácia"],"operationId":"docs","summary":"Dokumentácia pre ľudí (HTML)","security":[],"responses":{"200":{"description":"HTML stránka generovaná z tejto špecifikácie."}}}},"/llms.txt":{"get":{"tags":["Dokumentácia"],"operationId":"llmsTxt","summary":"Index pre AI agentov (llms.txt)","security":[],"responses":{"200":{"description":"Textový index podľa konvencie llms.txt."}}}}}}