/ Developers guide
Publishing via API
on any website.
How to build your own endpoint so Orova can publish finished articles to a site that does not run WordPress.
Orova publishes finished articles to WordPress out of the box. If your website is not WordPress — a custom CMS, a headless setup, a static site, or your own backend — you can still let Orova publish automatically by accepting articles over a small API. You write one HTTP endpoint; Orova calls it every time it finishes an article. This guide is for a developer and describes the full request contract.
/ Overview
How it works
When Orova finishes writing an article for a keyword, it sends a single HTTP POST request to the endpoint URL you registered. The request body is JSON and contains the whole article. Your endpoint creates the post on your side and replies with the final, public URL of the article. Orova saves that URL as the published link, just as it would for a WordPress post. Use this when you want hands-off publishing on a site that is not WordPress, or when you prefer to keep full control of how posts are stored.
/ Setup
Setting it up — five steps
- 1
Turn on “Connect via API” in your project. Open your project (Projects → your project → Connections). Next to the WordPress card you will find a “Connect via API” option. Enable it and Orova shows you two things: the endpoint URL field — where you paste your own URL — and a generated secret. Keep that secret safe; you will need it in step 3.
- 2
Build an endpoint that accepts POST. On your own site or server, create a route that listens for HTTP POST with a JSON body. This is the URL you paste back into the project Connections screen. Orova calls it once for every article it finishes.
- 3
Verify the Bearer token on every request. Every request from Orova carries an Authorization header in the form “Bearer <secret>”, using the exact secret shown in your project. Compare it against your stored copy and reject anything that does not match — this is what stops anyone else from posting to your site.
- 4
Create the article from the payload. Read the JSON body and create a post in your CMS or database: use title, slug and content_html for the article itself, excerpt as the meta description, featured_image_url as the cover image, and keyword / lang / published_at as metadata.
- 5
Return the live URL of the article. Respond with HTTP 200 or 201 and a JSON body of { "url": "https://yoursite.com/the-new-article" }. Orova stores that URL as the published link for the article. If you return a non-2xx status, or omit the url field, Orova treats the publish as failed.
/ Contract
The request Orova sends
Each finished article arrives as one request shaped like this:
POST <your endpoint URL>
Headers:
Content-Type: application/json
Authorization: Bearer <secret> # the secret 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:00Z" # ISO 8601 UTC
}/ Reference
Payload fields
Every field below is present in the JSON body of each request.
| Field | Type | Description |
|---|---|---|
| title | string | The article headline. |
| slug | string | URL-friendly identifier suggested for the post. |
| content_html | string | The full article body as ready-to-publish HTML. |
| excerpt | string | A short summary, intended for the meta description. |
| featured_image_url | string | null | URL of the cover image, or null when there is none. |
| keyword | string | The target SEO keyword the article was written for. |
| lang | string | Language as an ISO code, e.g. "en" or "vi". |
| published_at | string | Intended publish time, ISO 8601 in UTC. |
/ Contract
The response you must return
Once you have created the post, reply with an HTTP 200 or 201 status and this JSON body:
HTTP 200 (or 201)
Content-Type: application/json
{
"url": "https://yoursite.com/published-article"
}Orova stores that url as the published link for the article. If your endpoint returns any non-2xx status, or a body without a url field, Orova treats the publish as failed and marks the article accordingly so you can retry it.
/ Example
Code example
A minimal receiving endpoint in Node.js with Express. The same four steps — verify the token, read the payload, create the post, return the URL — apply in any language or 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. Read the payload Orova sent.
const {
title, slug, content_html, excerpt,
featured_image_url, keyword, lang, published_at,
} = req.body;
// 3. 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,
});
// 4. Return 200/201 with the live URL.
return res.status(201).json({
url: "https://yoursite.com/" + post.slug,
});
});
app.listen(3000);/ Security
Security notes
- Always verify the Bearer token. Your endpoint is a public URL — anyone could call it. The Authorization header is the only thing that proves a request really came from Orova, so reject every request whose token does not exactly match your stored secret.
- Serve the endpoint over HTTPS. The secret travels in a header. HTTPS keeps it from being read in transit.
- Keep the secret out of your code. Store it in an environment variable or a secrets manager, never hard-coded in a file you commit. If it is ever exposed, regenerate it from Project → Connections.
- Treat content_html as content, not as trusted markup. Store and render it the same careful way you would any article body in your CMS.
/ Wrapping up
That is the whole contract
With the endpoint live and registered in your project, Orova publishes to your site automatically — exactly as it does for WordPress users. Each article it finishes lands on your server, becomes a post, and its public URL flows back into Reports and Analysis so you can track how it performs.
/ Need a hand?
Stuck wiring up your endpoint? Open the Support section inside your workspace, or send us a message.