OROVA.VN — BIZ AI AGENT

/ डेवलपर गाइड

API से पब्लिश करना किसी भी वेबसाइट पर।

अपना endpoint कैसे बनाएं ताकि Orova तैयार लेख ऐसी साइट पर पब्लिश कर सके जो WordPress पर नहीं चलती।

Orova तैयार लेख सीधे WordPress पर पब्लिश करता है। अगर आपकी वेबसाइट WordPress नहीं है — कस्टम CMS, headless सेटअप, स्टैटिक साइट या आपका अपना backend — तब भी आप एक छोटे API से लेख स्वीकार करके Orova को अपने-आप पब्लिश करने दे सकते हैं। आप एक HTTP endpoint लिखते हैं; Orova हर लेख पूरा होने पर उसे कॉल करता है। यह गाइड डेवलपर के लिए है और पूरा रिक्वेस्ट कॉन्ट्रैक्ट बताती है।

/ अवलोकन

यह कैसे काम करता है

जब Orova किसी कीवर्ड के लिए लेख लिखना पूरा करता है, तो वह आपके रजिस्टर किए endpoint URL पर एक HTTP POST रिक्वेस्ट भेजता है। रिक्वेस्ट body JSON है और उसमें पूरा लेख होता है। आपका endpoint आपकी तरफ़ पोस्ट बनाता है और लेख के अंतिम, सार्वजनिक URL के साथ जवाब देता है। Orova उस URL को पब्लिश लिंक के रूप में सहेजता है, ठीक वैसे ही जैसे WordPress पोस्ट के लिए। इसका उपयोग तब करें जब आप ऐसी साइट पर बिना हाथ लगाए पब्लिश करना चाहते हैं जो WordPress नहीं है, या जब आप पोस्ट के संग्रहण पर पूरा नियंत्रण रखना चाहते हैं।

/ सेटअप

सेट अप करना — छह चरण

  • 1

    अपने प्रोजेक्ट में “Connect via API” चालू करें. अपना प्रोजेक्ट खोलें (Projects → आपका प्रोजेक्ट → Connections)। WordPress कार्ड के बगल में Connect via API कार्ड है। वहाँ अपने endpoint का URL डालें। सीक्रेट की फ़ील्ड वैकल्पिक है: खाली छोड़ें तो Orova एक बना देता है, या आपकी साइट जो की पहले से इस्तेमाल करती है उसे पेस्ट करें। सहेजने के बाद की कार्ड पर Copy बटन के साथ दिखती है। एक प्रोजेक्ट केवल एक लक्ष्य पर पब्लिश करता है — API से कनेक्ट करने पर WordPress बटन लॉक हो जाता है, और इसका उलटा भी।

  • 2

    POST स्वीकार करने वाला endpoint बनाएं. अपनी साइट या सर्वर पर एक route बनाएं जो JSON body वाले HTTP POST को सुने। यही URL आप प्रोजेक्ट की Connections स्क्रीन में पेस्ट करते हैं। Orova हर पूरे हुए लेख के लिए इसे एक बार कॉल करता है।

  • 3

    हर रिक्वेस्ट पर Bearer token सत्यापित करें. Orova की हर रिक्वेस्ट में “Bearer <secret>” रूप का Authorization हेडर होता है, जिसमें आपके प्रोजेक्ट में दिखाई गई सटीक सीक्रेट की होती है। इसे अपनी सहेजी कॉपी से मिलाएं और जो मेल न खाए उसे अस्वीकार करें — यही दूसरों को आपकी साइट पर पोस्ट करने से रोकता है।

  • 4

    Payload से लेख बनाएं. JSON body पढ़ें और अपने CMS या डेटाबेस में पोस्ट बनाएं: लेख के लिए title, slug और content_html, meta description के रूप में excerpt, कवर इमेज के रूप में featured_image_url, और मेटाडेटा के रूप में keyword / lang / published_at का उपयोग करें।

  • 5

    लेख का लाइव URL लौटाएं. HTTP 200 या 201 और { "url": "https://yoursite.com/the-new-article" } JSON body के साथ जवाब दें। Orova उस URL को लेख के पब्लिश लिंक के रूप में सहेजता है। अगर आप non-2xx स्टेटस लौटाते हैं या url फ़ील्ड छोड़ देते हैं, तो Orova पब्लिश को असफल मानता है।

  • 6

    Optimize इंजन से अपडेट रिक्वेस्ट संभालें. जब body में action = "update" हो, तो मौजूदा पोस्ट को target_url (या slug) से ढूंढें और उसका title, content_html और excerpt वहीं ओवरराइट करें — URL न बदलें। उसी पोस्ट की ओर इशारा करते { "url": ... } के साथ 200 लौटाएं। जो endpoint अभी इसे नहीं संभालते, उनके लिए Orova बस ऑप्टिमाइज़ेशन को असफल बताएगा; नए लेख पब्लिश करना पहले की तरह चलता रहेगा।

/ कॉन्ट्रैक्ट

Orova जो रिक्वेस्ट भेजता है

हर पूरा लेख इस तरह की एक रिक्वेस्ट के रूप में आता है:

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.

/ संदर्भ

Payload फ़ील्ड

पब्लिश (नया लेख) रिक्वेस्ट के फ़ील्ड। Delete और update रिक्वेस्ट उसी endpoint का उपयोग करती हैं, नीचे उनके अपने सेक्शन में दिखाई गई छोटी body के साथ।

फ़ील्डप्रकारविवरण
titlestringलेख की हेडलाइन।
slugstringURL-friendly identifier suggested for the post.
content_htmlstringपब्लिश के लिए तैयार HTML के रूप में पूरा लेख body।
excerptstringछोटा सारांश, meta description के लिए।
featured_image_urlstring | nullकवर इमेज का URL, या न होने पर null।
keywordstringलक्ष्य SEO कीवर्ड जिसके लिए लेख लिखा गया।
langstringLanguage as an ISO code, e.g. "en" or "vi".
published_atstringOrova ने लेख जिस क्षण भेजा, ISO 8601 में UTC, बिना timezone प्रत्यय के।
statusstring | undefinedवैकल्पिक। "draft" लेख को अप्रकाशित रखता है; "publish" या कोई मान न होने पर लेख पब्लिश होता है।
actionstring | undefinedनए लेखों के लिए नहीं होता। "delete" पोस्ट हटाने को कहता है; "update" (Optimize इंजन द्वारा भेजा गया) मौजूदा पोस्ट को वहीं ओवरराइट करने को कहता है।
target_urlstringकेवल action = "update" के साथ: ओवरराइट की जाने वाली पोस्ट का लाइव URL। URL न बदलें।
idnumber | undefinedOnly sent when Orova knows your post id (from `list` or `get`): match on it before `target_url`.

भेजने को कुछ न हो तो वैकल्पिक फ़ील्ड body से पूरी तरह हटा दिए जाते हैं — Orova कभी null नहीं भेजता, इसलिए उन्हें सावधानी से पढ़ें। status भी वैकल्पिक है: "draft" लेख को ड्राफ़्ट के रूप में बनाता है, जबकि "publish" या कोई status न होने पर लेख तुरंत पब्लिश होता है।

/ कॉन्ट्रैक्ट

आपको जो रिस्पॉन्स लौटाना है

पोस्ट बनाने के बाद HTTP 200 या 201 स्टेटस और यह JSON body लौटाएं:

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

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

Orova उस url को लेख के पब्लिश लिंक के रूप में सहेजता है। अगर आपका endpoint कोई non-2xx स्टेटस लौटाता है, या ऐसी body जो url फ़ील्ड वाला JSON ऑब्जेक्ट नहीं है, तो Orova पब्लिश को असफल मानता है और लेख को उसी अनुसार चिह्नित करता है ताकि आप फिर से कोशिश कर सकें। 60 seconds के भीतर जवाब दें — उसके बाद Orova रिक्वेस्ट टाइम आउट कर देता है (यह publish, update और delete सब पर लागू है)।

/ उदाहरण

कोड उदाहरण

Node.js में Express के साथ एक न्यूनतम receiving endpoint। यही चरण — token सत्यापित करें, action (update / delete) के अनुसार शाखा बनाएं, पोस्ट बनाएं या बदलें, URL लौटाएं — किसी भी भाषा या framework पर लागू होते हैं।

// 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);

/ कॉन्ट्रैक्ट — update

लेख अपडेट करना (Optimize)

Orova का Optimize इंजन पहले से लाइव लेखों को दोबारा लिखता है — ताज़ा तथ्य, बेहतर टाइटल, मर्ज किया कंटेंट — और फिर मौजूदा पोस्ट को वहीं, URL बदले बिना ओवरराइट करता है। रिक्वेस्ट उसी endpoint URL पर, उसी Bearer token के साथ POST के रूप में जाती है:

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.

पोस्ट को target_url से ढूंढें (न मिले तो slug से), उसका title, body और meta description बदलें, URL जैसा है वैसा रखें, फिर { "url": "<same post URL>" } के साथ 200 लौटाएं। कोई भी non-2xx स्टेटस, या url के बिना body, Orova से उस ऑप्टिमाइज़ेशन को असफल चिह्नित करवाती है (यह कभी डुप्लिकेट पोस्ट नहीं बनाता)। जिन endpoint ने इसे अभी लागू नहीं किया है, वे नए लेख बिना बदलाव पब्लिश करते रहते हैं — update लागू करना तभी ज़रूरी है जब आप Optimize स्क्रीन का उपयोग करें।

29 अगस्त से update body में id (target_url से पहले इसी से मिलाएं), नई कवर इमेज के लिए featured_image_url, और "publish" या "draft" वाला status भी हो सकता है। तीनों वैकल्पिक हैं; खाली होने पर body से हटा दिए जाते हैं, कभी null के रूप में नहीं भेजे जाते।

/ कॉन्ट्रैक्ट — Visual Editor

लेख पढ़ना (आवश्यक)

Orova को आपकी साइट पर पहले से मौजूद लेख पढ़ने होते हैं — डुप्लिकेट विषयों से बचने, इंटरनल लिंक जोड़ने और पुरानी पोस्ट ऑप्टिमाइज़ करने के लिए। उसी endpoint URL पर, उसी Bearer token के साथ दो और action जोड़ें: list आपके लेख लौटाता है, get उनमें से एक पूरा लौटाता है।

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 की सीमा 500 है और सबसे नया लेख पहले आता है। get के लिए Orova id, target_url और slug एक साथ भेजता है — जिसे आप पहचानें उससे मिलाएं, इसी क्रम में। कुछ मेल न खाए तो { "ok": false, "err": "not_found" } के साथ 404 लौटाएं। list में excerpt वैकल्पिक है (अधिकतम 300 वर्ण)। आवश्यक: Orova list कॉल करके जानता है कि कौन से लेख पहले से हैं (डुप्लिकेट से बचने, इंटरनल लिंक जोड़ने और पूरी साइट का विश्लेषण करने के लिए) और लेख ऑप्टिमाइज़ करते समय उसे पढ़ने के लिए get कॉल करता है। अगर आपकी साइट इन दो action का जवाब नहीं देती, तो नए लेखों को इंटरनल लिंक नहीं मिलते और पुराने लेख ऑप्टिमाइज़ नहीं हो सकते।

/ कॉन्ट्रैक्ट — Visual Editor

इमेज अपलोड करना (Visual Editor)

जब आप Visual Editor में इमेज डालते हैं, तो Orova उसे JSON body के अंदर base64 के रूप में उसी endpoint URL पर भेजता है — न multipart, न सुरक्षित करने के लिए दूसरा URL।

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
  }

केवल image/* स्वीकार करें और 15 MB से बड़ी हर चीज़ अस्वीकार करें। फ़ाइल सहेजें, फिर इमेज के absolute URL के साथ जवाब दें: relative पाथ लेख के कहीं और रेंडर होते ही उसे तोड़ देता है। यह action केवल Visual Editor के लिए ज़रूरी है।

/ कॉन्ट्रैक्ट — delete

लेख हटाना

जब कोई उपयोगकर्ता Orova के अंदर पब्लिश लेख हटाता है (Write या Reports स्क्रीन से), तो Orova आपकी साइट से भी उसे हटाने को कहता है। रिक्वेस्ट उसी endpoint URL पर, उसी Bearer token के साथ POST के रूप में जाती है — फ़र्क़ केवल body में है:

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
  }

पोस्ट को url से ढूंढें (न मिले तो slug से), उसे हटाएं या अप्रकाशित करें, फिर 200 और { "deleted": true } के साथ जवाब दें — केवल 204 भी चलता है। अगर पोस्ट अब मौजूद नहीं है, तो 404 लौटाएं और Orova उसे पहले से हटाया हुआ मानता है। { "deleted": false } लौटाने का मतलब है कि पोस्ट नहीं हटी। सामान्य पब्लिश रिक्वेस्ट में कभी action फ़ील्ड नहीं होता, इसलिए मौजूदा endpoint बिना बदलाव काम करते रहते हैं — delete लागू करना वैकल्पिक है पर सुझाया जाता है।

/ सुरक्षा

सुरक्षा नोट

  • हमेशा Bearer token सत्यापित करें. आपका endpoint एक सार्वजनिक URL है — कोई भी इसे कॉल कर सकता है। Authorization हेडर ही एकमात्र चीज़ है जो साबित करती है कि रिक्वेस्ट सच में Orova से आई है, इसलिए हर उस रिक्वेस्ट को अस्वीकार करें जिसका token आपकी सहेजी सीक्रेट से बिल्कुल मेल नहीं खाता।
  • Endpoint को HTTPS पर चलाएं. सीक्रेट हेडर में जाती है। HTTPS रास्ते में उसे पढ़े जाने से बचाता है।
  • सीक्रेट को अपने कोड से बाहर रखें. इसे environment variable या secrets manager में रखें, कभी भी commit की जाने वाली फ़ाइल में hard-code न करें। अगर यह कभी उजागर हो जाए, तो Project → Connections से नई बनाएं।
  • content_html को कंटेंट मानें, भरोसेमंद मार्कअप नहीं. इसे उसी सावधानी से सहेजें और रेंडर करें जैसे आप अपने CMS में किसी भी लेख body को करते हैं।

/ समापन

यही पूरा कॉन्ट्रैक्ट है

जब endpoint लाइव हो और आपके प्रोजेक्ट में रजिस्टर हो, तो Orova आपकी साइट पर अपने-आप पब्लिश करता है — ठीक वैसे ही जैसे WordPress उपयोगकर्ताओं के लिए। हर पूरा लेख आपके सर्वर पर पहुँचता है, पोस्ट बनता है, और उसका सार्वजनिक URL रिपोर्ट और विश्लेषण में वापस आता है ताकि आप उसका प्रदर्शन ट्रैक कर सकें।

← गाइड लाइब्रेरी पर वापस जाएं

/ मदद चाहिए?

Endpoint जोड़ने में अटक गए? अपने वर्कस्पेस में सहायता सेक्शन खोलें, या हमें संदेश भेजें।