Přeskočit na obsah
Pro vývojáře

API

Přes API čtete konverzace, kontakty, reklamace a statistiky, zapisujete katalog a znalosti a děláte to, co tlačítka v panelu.

API klíče

V panelu otevřete Nastavení, část Propojení, řádek API a klikněte na Vytvořit klíč. Klíč pojmenujte podle systému, který ho bude používat, a vyberte, co smí. Klíč posílejte v každém požadavku v hlavičce Authorization: Bearer <klíč>.

Karta API v nastavení panelu Otta se seznamem klíčů
API klíče v Nastavení, část Propojení.
OprávněníCo klíč smí
readČíst konverzace, kontakty, reklamace, nejisté otázky, produkty, znalosti a statistiky. Všechny GET kromě webhooků.
writeAkce jako tlačítka v panelu a přidávání a mazání znalostí.
catalogueZapisovat a mazat produkty v katalogu.
webhooksZobrazit doručení webhooků, poslat je znovu a poslat zkušební událost.

Každý systém má mít vlastní klíč jen s tím, co potřebuje. Účetnictví stačí read, skladu catalogue. Které oprávnění adresa potřebuje, uvidíte u každé v části Reference API. Bez něj vrátí 403 s errcode insufficient_scope.

Klíč je tajný: kdo ho má, jedná za vás. Patří jen na váš server, nikdy ne do kódu webu ani mobilní aplikace. Celý ho ukážeme jen jednou, u nás zůstává jen jeho otisk. Když unikne, klíč v panelu zrušte. Ten systém hned ztratí přístup a ostatní klíče fungují dál.

API a webhooky jsou součástí plánu Na míru. Zápis katalogu přes API funguje na každém plánu.

První požadavek

curl
curl https://ottoai.sk/api/v1/me \
  -H "Authorization: Bearer $OTTO_API_KEY"
Node.js
const r = await fetch("https://ottoai.sk/api/v1/conversations?status=human&limit=20", {
  headers: { Authorization: "Bearer " + process.env.OTTO_API_KEY },
});
if (!r.ok) throw new Error((await r.json()).errcode);
const { conversations, nextBefore } = await r.json();
PHP
$ch = curl_init("https://ottoai.sk/api/v1/leads?since=2026-10-01T00:00:00Z");
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("OTTO_API_KEY")],
  CURLOPT_RETURNTRANSFER => true,
]);
$kontakty = json_decode(curl_exec($ch), true)["leads"];

Formát

Stránkování

Seznamy vracejí nextBefore. Pošlete ho zpět jako before=, dokud není null. Je to neprůhledný řetězec, neskládejte ho sami. Počet řádků na straně vám konec neřekne.

let pred = null;
do {
  const r = await fetch("https://ottoai.sk/api/v1/leads?limit=100" + (pred ? "&before=" + pred : ""), { headers });
  const d = await r.json();
  for (const kontakt of d.leads) zpracuj(kontakt);
  pred = d.nextBefore;
} while (pred);

Filtry

Chyby

Každá chyba má { error, errcode, requestId }. errcode je stabilní a anglicky, podle něj se rozhodujte v kódu. error je věta pro člověka. U špatného parametru přibude errors s přesnou cestou.

{
  "error": "Neplatný parameter.",
  "errcode": "invalid_param",
  "errors": [{ "path": "status", "message": "Použite bot, human alebo resolved." }],
  "requestId": "1f0c6a7e-3b9a-4f0e-9c1d-2a7b8e5d4c3f"
}
KódVýznam
400Chybný požadavek, errors řekne co přesně.
401Neplatný nebo chybějící klíč.
403Funkce není ve vašem plánu (api_not_in_plan, webhooks_not_in_plan) nebo klíč nemá oprávnění (insufficient_scope).
404Záznam neexistuje nebo není váš. Cizí záznamy vracejí 404, ne 403.
409Akce v tomto stavu nejde, třeba převzít vyřešenou konverzaci (conv_resolved).
429Příliš mnoho požadavků, hlavička Retry-After řekne, za kolik sekund to zkusit znovu.

Texty v error jsou zatím slovensky. Každá odpověď má hlavičku x-request-id. Když pošlete vlastní, vrátíme ji a uvidíme ji i my v záznamech.

Limity

Limit je 120 požadavků za minutu na firmu. Hlavičky RateLimit-Limit, RateLimit-Remaining a RateLimit-Reset v každé odpovědi řeknou, kolik zbývá a za kolik sekund se limit uvolní. Celý katalog přes snapshot pošlete nejvýš 12× za hodinu.

Akce

To, co dělají tlačítka v panelu, umí i API. Akce posílají stejné události webhooků jako panel.

AdresaCo dělá
POST /conversations/<id>/messagesOdpoví zákazníkovi jako kolega. Otto v konverzaci zmlkne, zákazník mimo web dostane odpověď e-mailem.
POST /conversations/<id>/notesInterní poznámka, zákazník ji nevidí.
POST /conversations/<id>/takeoverPřevezme konverzaci. Bez operatorId zůstane dosavadní přiřazení.
POST /conversations/<id>/releaseVrátí konverzaci Ottovi.
POST /conversations/<id>/resolve, /reopenVyřeší konverzaci, případně ji otevře znovu.
PATCH /leads/<id>Označí kontakt jako vyřízený: { "handled": true }.
PATCH /returns/<id>Rozhodne o reklamaci, notify: true pošle zákazníkovi e-mail.
POST /unanswered/<id>/dismissSkryje nejistou otázku ze seznamu.
curl -X POST https://ottoai.sk/api/v1/conversations/$ID/messages \
  -H "Authorization: Bearer $OTTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Dobrý den, objednávka odešla dnes ráno.", "operatorId": "$OPERATOR" }'

Id kolegů najdete v GET /api/v1/operators. Bez operatorId se jako autor v panelu ukáže API.

Výsledek konverzace a statistiky

Každá konverzace má outcome:

GET /api/v1/stats vrátí počty za období i řadu po dnech, týdnech nebo měsících ve zvoleném časovém pásmu:

GET /api/v1/stats?since=2026-10-01T00:00:00Z&interval=week
{
  "conversationsTotal": 1824,
  "conversationsMonth": 212,
  "products": 236,
  "range": {
    "since": "2026-10-01T00:00:00.000Z",
    "until": "2026-10-10T16:00:00.000Z",
    "interval": "week",
    "timezone": "Europe/Bratislava",
    "totals": { "conversations": 64, "resolvedByOtto": 49, "unanswered": 6, "handedOff": 8, "missed": 1,
                "ratingUp": 11, "ratingDown": 1, "leads": 7, "returns": 2 },
    "series": [
      { "date": "2026-09-28", "conversations": 31, "resolvedByOtto": 24, "unanswered": 3, "handedOff": 4, "missed": 0, "ratingUp": 6, "ratingDown": 0 },
      { "date": "2026-10-05", "conversations": 33, "resolvedByOtto": 25, "unanswered": 3, "handedOff": 4, "missed": 1, "ratingUp": 5, "ratingDown": 1 }
    ]
  }
}