OROVA.VN — BIZ AI AGENT

/ Návod pre vývojárov

Publikovanie cez API na akýkoľvek web.

Ako vytvoriť vlastný endpoint, aby Orova mohla publikovať hotové články na web, ktorý nebeží na WordPress.

Orova publikuje hotové články do WordPress hneď od začiatku. Ak váš web nie je WordPress — vlastný CMS, headless riešenie, statický web alebo vlastný backend — aj tak môžete nechať Orova publikovať automaticky tým, že budete články prijímať cez malé API. Napíšete jeden HTTP endpoint; Orova ho zavolá zakaždým, keď dokončí článok. Tento návod je pre vývojára a popisuje celý kontrakt požiadavky.

/ Prehľad

Ako to funguje

Keď Orova dopíše článok pre kľúčové slovo, pošle jednu HTTP požiadavku POST na URL endpointu, ktorú ste zaregistrovali. Telo požiadavky je JSON a obsahuje celý článok. Váš endpoint vytvorí príspevok na vašej strane a vráti konečnú verejnú URL článku. Orova túto URL uloží ako publikovaný odkaz, rovnako ako pri príspevku vo WordPress. Použite to, ak chcete automatické publikovanie na webe, ktorý nie je WordPress, alebo ak chcete mať plnú kontrolu nad ukladaním príspevkov.

/ Nastavenie

Nastavenie — šesť krokov

  • 1

    Zapnite „Pripojiť cez API“ v projekte. Otvorte svoj projekt (Projekty → váš projekt → Pripojenia). Vedľa karty WordPress je karta Pripojiť cez API. Zadajte do nej URL svojho endpointu. Pole tajného kľúča je voliteľné: nechajte ho prázdne a Orova kľúč vygeneruje, alebo vložte kľúč, ktorý váš web už používa. Po uložení sa kľúč zobrazí na karte s tlačidlom Kopírovať. Projekt publikuje len do jedného cieľa — pripojenie cez API zamkne tlačidlo WordPress a naopak.

  • 2

    Vytvorte endpoint, ktorý prijíma POST. Na svojom webe alebo serveri vytvorte route, ktorá počúva HTTP POST s telom JSON. Toto je URL, ktorú vložíte späť do obrazovky Pripojenia v projekte. Orova ju zavolá raz pre každý dokončený článok.

  • 3

    Overujte Bearer token pri každej požiadavke. Každá požiadavka od Orova nesie hlavičku Authorization v tvare „Bearer <secret>“ s presne tým tajným kľúčom, ktorý je zobrazený v projekte. Porovnajte ho s uloženou kópiou a odmietnite všetko, čo nesedí — práve to zabráni komukoľvek inému publikovať na váš web.

  • 4

    Vytvorte článok z payloadu. Prečítajte telo JSON a vytvorte príspevok vo svojom CMS alebo databáze: title, slug a content_html použite pre samotný článok, excerpt ako meta popis, featured_image_url ako titulný obrázok a keyword / lang / published_at ako metadáta.

  • 5

    Vráťte živú URL článku. Odpovedzte HTTP 200 alebo 201 s telom JSON { "url": "https://yoursite.com/the-new-article" }. Orova túto URL uloží ako publikovaný odkaz článku. Ak vrátite stav mimo 2xx alebo vynecháte pole url, Orova považuje publikovanie za neúspešné.

  • 6

    Spracujte požiadavky na aktualizáciu z enginu Optimalizácia. Keď telo obsahuje action = "update", nájdite existujúci príspevok podľa target_url (alebo slug) a prepíšte jeho title, content_html a excerpt na mieste — URL ponechajte bez zmeny. Odpovedzte 200 s { "url": ... } smerujúcim na ten istý príspevok. Endpointy, ktoré to ešte nespracúvajú, len spôsobia, že Orova nahlási optimalizáciu ako neúspešnú; publikovanie nových článkov funguje ďalej ako doteraz.

/ Kontrakt

Požiadavka, ktorú Orova posiela

Každý dokončený článok príde ako jedna požiadavka v tomto tvare:

POST <your endpoint URL>

Headers:
  Content-Type: application/json
  Authorization: Bearer <secret>     # the secret key shown in Project -> Connections
  User-Agent: Orova-SEO

Body (JSON):
  {
    "title": "...",                  # article headline
    "slug": "...",                   # URL-friendly identifier
    "content_html": "...",           # full article HTML
    "excerpt": "...",                # meta description
    "featured_image_url": "..." | null,
    "keyword": "...",                # target keyword
    "lang": "en",                    # ISO language code
    "published_at": "2026-05-17T09:00:00.482913",  # ISO 8601, UTC, no offset suffix
    "status": "draft"                # optional: "draft" keeps it unpublished
  }
  # Optional fields are left out of the body when empty — never sent as null.

/ Referencia

Polia payloadu

Polia požiadavky na publikovanie (nový článok). Požiadavky na zmazanie a aktualizáciu používajú ten istý endpoint s menším telom, ktoré je uvedené v ich vlastných sekciách nižšie.

PoleTypPopis
titlestringNadpis článku.
slugstringURL-friendly identifier suggested for the post.
content_htmlstringCelé telo článku ako HTML pripravené na publikovanie.
excerptstringKrátke zhrnutie určené pre meta popis.
featured_image_urlstring | nullURL titulného obrázka alebo null, ak žiadny nie je.
keywordstringCieľové kľúčové slovo SEO, pre ktoré bol článok napísaný.
langstringLanguage as an ISO code, e.g. "en" or "vi".
published_atstringOkamih, keď Orova článok odoslala, ISO 8601 v UTC, bez prípony časového pásma.
statusstring | undefinedVoliteľné. "draft" ponechá článok nepublikovaný; "publish" alebo žiadna hodnota ho publikuje.
actionstring | undefinedChýba pri nových článkoch. "delete" žiada odstrániť príspevok; "update" (posiela engine Optimalizácia) žiada prepísať existujúci príspevok na mieste.
target_urlstringLen s action = "update": živá URL príspevku na prepísanie. URL ponechajte bez zmeny.
idnumber | undefinedOnly sent when Orova knows your post id (from `list` or `get`): match on it before `target_url`.

Voliteľné polia sa z tela úplne vynechajú, keď nie je čo poslať — Orova nikdy neposiela null, preto ich čítajte obranne. Aj status je voliteľný: "draft" vytvorí článok ako koncept, "publish" alebo žiadny status ho hneď publikuje.

/ Kontrakt

Odpoveď, ktorú musíte vrátiť

Po vytvorení príspevku odpovedzte stavom HTTP 200 alebo 201 a týmto telom JSON:

HTTP 200 (or 201)
Content-Type: application/json

{
  "url": "https://yoursite.com/published-article"
}

Orova uloží túto url ako publikovaný odkaz článku. Ak váš endpoint vráti akýkoľvek stav mimo 2xx alebo telo, ktoré nie je objekt JSON s poľom url, Orova považuje publikovanie za neúspešné a článok tak označí, aby ste ho mohli zopakovať. Odpovedzte do 60 sekúnd — potom Orova požiadavku preruší (platí pre publikovanie, aktualizáciu aj mazanie).

/ Príklad

Ukážka kódu

Minimálny prijímací endpoint v Node.js s Express. Rovnaké kroky — overiť token, vetviť podľa action (update / delete), vytvoriť alebo zmeniť príspevok, vrátiť URL — platia v akomkoľvek jazyku či frameworku.

// Node.js / Express — a minimal receiving endpoint
import express from "express";

const app = express();
app.use(express.json({ limit: "5mb" }));

// The secret Orova generated for this project.
const OROVA_SECRET = process.env.OROVA_SECRET;

app.post("/orova/publish", async (req, res) => {
  // 1. Verify the Bearer token.
  const auth = req.get("authorization") || "";
  if (auth !== "Bearer " + OROVA_SECRET) {
    return res.status(401).json({ error: "unauthorized" });
  }

  // 2. Required: list your articles (duplicate check, internal links). action = "list".
  if (req.body.action === "list") {
    const posts = await listPosts(req.body.limit || 500); // newest first, 500 max
    // each post: { id, title, slug, link, date, modified, status, author, excerpt? }
    return res.status(200).json({ ok: true, posts });
  }

  // 3. Required: read one article in full (used when optimizing it). action = "get".
  if (req.body.action === "get") {
    const post = await findPost(req.body.id, req.body.target_url, req.body.slug);
    if (!post) return res.status(404).json({ ok: false, err: "not_found" });
    return res.status(200).json({ ok: true, post });
  }

  // 4. Visual Editor: store an image, answer with its absolute URL.
  if (req.body.action === "upload_image") {
    const { filename, mime, data_base64 } = req.body;
    if (!String(mime || "").startsWith("image/")) {
      return res.status(422).json({ error: "image files only" });
    }
    const bytes = Buffer.from(data_base64, "base64");
    if (bytes.length > 15 * 1024 * 1024) {
      return res.status(413).json({ error: "image too large" });
    }
    return res.status(200).json({ ok: true, url: await saveImage(filename, bytes) });
  }

  // 5. Delete requests: body carries action = "delete".
  if (req.body.action === "delete") {
    const removed = await deletePostByUrl(req.body.url, req.body.slug);
    if (!removed) return res.status(404).json({ deleted: true }); // already gone
    return res.status(200).json({ deleted: true });
  }

  // 6. Update requests: action = "update". Optional fields may be absent.
  if (req.body.action === "update") {
    const updated = await updatePost(req.body.id, req.body.target_url, {
      title: req.body.title,
      html: req.body.content_html,
      metaDescription: req.body.excerpt,
      coverImage: req.body.featured_image_url,  // optional
      status: req.body.status,                  // optional: "publish" | "draft"
    });
    if (!updated) return res.status(404).json({ error: "post not found" });
    return res.status(200).json({ url: updated.url });
  }

  // 7. New article: read the payload Orova sent.
  const {
    title, slug, content_html, excerpt,
    featured_image_url, keyword, lang, published_at, status,
  } = req.body;

  // 8. Create the article in your own CMS or database.
  const post = await createPost({
    title,
    slug,
    html: content_html,
    metaDescription: excerpt,
    coverImage: featured_image_url,
    keyword,
    lang,
    publishedAt: published_at,
    draft: status === "draft",   // status is optional; absent means publish now
  });

  // 9. Return 200/201 with the live URL.
  return res.status(201).json({
    url: "https://yoursite.com/" + post.slug,
  });
});

app.listen(3000);

/ Kontrakt — aktualizácia

Aktualizácia článkov (Optimalizácia)

Engine Optimalizácia v Orova prepisuje články, ktoré sú už zverejnené — aktualizované fakty, lepšie nadpisy, zlúčený obsah — a potom prepíše existujúci príspevok na mieste, s nezmenenou URL. Požiadavka ide na tú istú URL endpointu ako POST s rovnakým Bearer tokenom:

POST <your endpoint URL>

Headers:
  Content-Type: application/json
  Authorization: Bearer <secret>
  User-Agent: Orova-SEO

Body (JSON):
  {
    "action": "update",          # always the literal string "update"
    "id": 123,                   # optional: post id, match on this first
    "target_url": "...",         # public URL of the post to overwrite (match next)
    "title": "...",              # new headline
    "slug": "...",               # slug fallback for matching, may be empty
    "content_html": "...",       # full new article body as HTML
    "excerpt": "...",            # new meta description
    "featured_image_url": "...", # optional: new cover image
    "status": "publish"          # optional: "publish" or "draft"
  }
  # Optional fields are left out of the body when empty — never sent as null.

Nájdite príspevok podľa target_url (inak podľa slug), nahraďte jeho nadpis, telo a meta popis, URL ponechajte tak, ako je, a odpovedzte 200 s { "url": "<same post URL>" }. Akýkoľvek stav mimo 2xx alebo telo bez url spôsobí, že Orova označí optimalizáciu ako neúspešnú (nikdy nevytvorí duplicitný príspevok). Endpointy, ktoré to ešte neimplementovali, ďalej publikujú nové články bez zmeny — aktualizáciu treba implementovať, až keď začnete používať obrazovku Optimalizácia.

Od 29. augusta môže telo aktualizácie obsahovať aj id (porovnajte ho pred target_url), featured_image_url pre nový titulný obrázok a status s hodnotou "publish" alebo "draft". Všetky tri sú voliteľné; ak sú prázdne, z tela sa vynechajú, nikdy sa neposielajú ako null.

/ Kontrakt — Visual Editor

Čítanie článkov (povinné)

Orova potrebuje čítať články, ktoré už na vašom webe sú — aby sa vyhla duplicitným témam, pridala interné odkazy a optimalizovala staršie príspevky. Pridajte ďalšie dve akcie na tej istej URL endpointu s rovnakým Bearer tokenom: list vráti vaše články, get vráti jeden z nich celý.

POST <your endpoint URL>     # same endpoint, same Bearer secret

Body (JSON):
  {
    "action": "list",            # always the literal string "list"
    "limit": 500                 # newest article first, 500 maximum
  }

Response — HTTP 200:
  {
    "ok": true,
    "posts": [
      {
        "id": 123,               # your own post id, reused by "get" and "update"
        "title": "...",
        "slug": "...",
        "link": "https://yoursite.com/the-article",
        "date": "2026-08-29",    # published date, YYYY-MM-DD
        "modified": "2026-08-29",
        "status": "publish",     # "publish" or "draft"
        "author": "...",
        "excerpt": "..."         # optional: short summary, 300 characters max
      }
    ]
  }
  # Required: Orova reads this list to avoid duplicate topics,
  # add internal links and analyze the whole site.
POST <your endpoint URL>

Body (JSON):
  {
    "action": "get",             # always the literal string "get"
    "id": 123,                   # match on this first
    "target_url": "...",         # then the public URL
    "slug": "..."                # then the slug
  }

Response — HTTP 200:
  {
    "ok": true,
    "post": {
      "id": 123,
      "title": "...",
      "slug": "...",
      "link": "https://yoursite.com/the-article",
      "content_html": "...",     # full article body as HTML
      "excerpt": "...",
      "featured_image_url": "...",
      "status": "publish"        # "publish" or "draft"
    }
  }

No such post — HTTP 404:
  { "ok": false, "err": "not_found" }

limit je obmedzený na 500 a najnovší článok je prvý. Pri get Orova posiela id, target_url a slug naraz — porovnajte podľa toho, ktorý rozpoznáte, v tomto poradí. Ak sa nič nezhoduje, odpovedzte 404 s { "ok": false, "err": "not_found" }. excerpt v list je voliteľný (najviac 300 znakov). Povinné: Orova volá list, aby zistila, ktoré články už existujú (na zabránenie duplicitám, pridanie interných odkazov a analýzu celého webu), a volá get, aby si prečítala článok pri jeho optimalizácii. Ak váš web na tieto dve akcie neodpovedá, nové články nedostanú interné odkazy a staršie články nemožno optimalizovať.

/ Kontrakt — Visual Editor

Nahrávanie obrázkov (Visual Editor)

Keď pustíte obrázok do Visual Editor, Orova ho pošle na tú istú URL endpointu ako base64 v tele JSON — bez multipart, bez druhej URL, ktorú treba zabezpečiť.

POST <your endpoint URL>

Body (JSON):
  {
    "action": "upload_image",    # always the literal string "upload_image"
    "filename": "cover.png",     # original file name, extension included
    "mime": "image/png",         # image/* only
    "data_base64": "iVBORw0KGgo..."   # file bytes, base64, 15 MB maximum
  }

Response — HTTP 200 (or 201):
  {
    "ok": true,
    "url": "https://yoursite.com/uploads/cover.png"   # absolute URL
  }

Prijímajte len image/* a odmietnite všetko nad 15 MB. Súbor uložte a odpovedzte absolútnou URL obrázka: relatívna cesta článok pokazí, hneď ako sa zobrazí inde. Táto akcia je potrebná len pre Visual Editor.

/ Kontrakt — mazanie

Mazanie článkov

Keď používateľ odstráni publikovaný článok priamo v Orova (na obrazovke Písanie alebo Prehľady), Orova požiada váš web, aby ho zmazal tiež. Požiadavka ide na tú istú URL endpointu ako POST s rovnakým Bearer tokenom — líši sa len telo:

POST <your endpoint URL>

Headers:
  Content-Type: application/json
  Authorization: Bearer <secret>
  User-Agent: Orova-SEO

Body (JSON):
  {
    "action": "delete",          # always the literal string "delete"
    "url": "...",                # public URL of the article to remove (match on this first)
    "slug": "...",               # slug fallback, may be empty
    "keyword": "..."             # the article's target keyword, for your logs
  }

Vyhľadajte príspevok podľa url (inak podľa slug), odstráňte ho alebo zrušte jeho publikovanie a odpovedzte 200 s { "deleted": true } — funguje aj samotné 204. Ak príspevok už neexistuje, odpovedzte 404 a Orova ho považuje za už zmazaný. Vrátenie { "deleted": false } oznámi Orova, že príspevok nebol odstránený. Bežné požiadavky na publikovanie nikdy neobsahujú pole action, takže existujúce endpointy fungujú ďalej bez zmeny — implementácia mazania je voliteľná, ale odporúčaná.

/ Bezpečnosť

Bezpečnostné poznámky

  • Vždy overujte Bearer token. Váš endpoint je verejná URL — môže ju zavolať ktokoľvek. Hlavička Authorization je jediné, čo dokazuje, že požiadavka naozaj prišla od Orova, preto odmietnite každú požiadavku, ktorej token presne nezodpovedá uloženému tajnému kľúču.
  • Endpoint prevádzkujte cez HTTPS. Tajný kľúč putuje v hlavičke. HTTPS zabráni jeho prečítaniu počas prenosu.
  • Tajný kľúč nedávajte do kódu. Uložte ho do premennej prostredia alebo do správcu tajomstiev, nikdy ho nezapisujte napevno do súboru, ktorý commitujete. Ak niekedy unikne, vygenerujte nový v Projekt → Pripojenia.
  • Považujte content_html za obsah, nie za dôveryhodný kód. Ukladajte a vykresľujte ho rovnako opatrne ako akékoľvek telo článku vo svojom CMS.

/ Na záver

To je celý kontrakt

Keď je endpoint spustený a zaregistrovaný v projekte, Orova publikuje na váš web automaticky — presne ako pre používateľov WordPress. Každý dokončený článok pristane na vašom serveri, stane sa príspevkom a jeho verejná URL sa vráti do Prehľadov a Analýzy, aby ste mohli sledovať jeho výkon.

← Späť do knižnice návodov

/ Potrebujete pomoc?

Nedarí sa vám pripojiť endpoint? Otvorte sekciu Podpora vo svojom pracovnom priestore, alebo nám pošlite správu.