Publish RankOps AI articles to your own website
RankOps AI generates and reviews articles. Save your publishing URL and security key in Website Setup so approved articles can be sent to your website.
1. How publishing works
① RankOps AI ② Your site
───────────────────── ──────────────────────────────────
Find keyword opportunities
Generate article
Review and approve
Send approved article ─────► Receive article
Save article
Track live URL ◄───── Return article URLEverything before the arrow happens in RankOps AI. Your site only needs to receive the article and return the live URL.
2. Prepare two things
Prepare one URL that can receive articles, then save that publishing connection in RankOps AI.
Prepare a website receiving URL
Ask the developer responsible for your website to provide an HTTPS receiving URL for RankOps AI articles.
Save the publishing connection
In RankOps AI Website Setup, enter the Publish URL and Security key, then click Test connection.
3. Website receiving URL
Audience: the developer responsible for your website receiving URL.
Your receiving URL accepts one approved RankOps AI article per HTTP POST. It saves the article on your site and returns the live URL so RankOps AI can track where the article was published.
3.1 Endpoint contract
Method and path are up to you, but the request shape is fixed. Default suggestion: POST /api/seo-content/publish
Authorization: Bearer SEO_CONTENT_PUBLISH_TOKEN3.2 Required fields
sourceArticleIdRankOps AI article ID. Your site must store it and use it as the idempotency key when the same article is sent again.titleArticle title. Save it as the post title on your site.slugURL slug for the post. Return 409 if your site already has this slug for a different article.contentFull article body in Markdown. Save it without truncation, then render Markdown or convert it to safe HTML before public display. Do not show raw ## headings to readers.languageArticle language code, e.g. en or zh.statusPublish status. Normal publishing sends 'published'.3.3 Optional fields
descriptionSEO meta description. Empty string is allowed.authorNameDisplay name for the article author.authorImageURL to the author avatar.categoriesArray of category names. RankOps AI first uses the existing categories returned by your website during Test connection. If your website does not return a category list, RankOps AI asks you to fix the target dryRun response and fetch categories and tags again.tagsArray of tag names. RankOps AI first matches existing tags from your website. It only adds new keyword tags when your website allows tag creation. If you want clickable tag archive pages, save tags into your native tag system instead of storing them as plain text on the post.dryRunWhen true, validate the token and return a test response without saving any article.3.4 Example request body
{
"sourceArticleId": "rankops-article-id",
"title": "Article title",
"slug": "article-url-slug",
"description": "Meta description",
"content": "## Markdown article body\n\nParagraph text with links, lists, and section headings.",
"language": "en",
"authorName": "RankOps AI",
"authorImage": "https://example.com/avatar.png",
"categories": ["SEO", "Content Marketing"],
"tags": ["keyword research", "content strategy"],
"status": "published"
}3.5 Example success response
{
"targetPostId": "post-id-from-your-site",
"publishedUrl": "https://example.com/blog/article-url-slug",
"status": "published",
"slug": "article-url-slug"
}3.6 Connection test (dryRun)
Why dryRun exists: when a user clicks 'Test connection' in RankOps AI, we don't want to create a real article on your site just to check the connection. Instead, we send a dryRun request. Your receiving URL should validate the security key, then return { ok: true, dryRun: true } without writing anything.
Your receiving URL gets this body during a test. Validate the token only, return success, do not save an article.
{
"dryRun": true,
"source": "rankops",
"purpose": "connection_test"
}3.7 Connection test success response
{
"ok": true,
"dryRun": true,
"settings": {
"autoCreateCategories": false,
"autoCreateTags": true
},
"taxonomies": {
"categories": [
{ "title": "Payroll and Benefits", "slug": "payroll" }
],
"tags": [
{ "title": "payroll calculator", "slug": "payroll-calculator" }
]
}
}3.8 Security checklist (must do)
- Validate the Authorization: Bearer <token> header before reading the request body.
- Store the token in server-side environment variables. Never put it in frontend code or commit it to git.
- Use HTTPS for the receiving URL. RankOps AI refuses to call plain http endpoints.
- Return 401 (not 200) when the token does not match.
- If the receiving URL is public, add basic rate limiting to prevent abuse.
- After the article is stored and public, failures in post-publish hooks such as cache refresh, IndexNow, webhooks, or analytics must still return success. Log hook failures separately instead of returning 500 for an article that was already written.
4. Save the connection in RankOps AI
Open RankOps AI Console → Website Setup → choose the site you want to publish to, then fill in the matching fields:
Target type → Choose your website receiving method
Publish URL → Your website receiving URL
Security key → The same security key your receiving URL validates
Save settings → Click Save
Test connection → Click Test connection and confirm the connection is verifiedAfter you click 'Test connection and fetch categories and tags' and the connection is verified, RankOps AI reads your website's existing categories and tags. For the first article, keep publishing manual, manually send one approved article, then check title, body, categories, tags and slug.
You do not need to fill categories or tags in RankOps AI. Your website should return existing categories and tags in the Test connection response. If RankOps AI says the target site did not return categories or tags, create them on the target site or update dryRun to return taxonomies, then click 'Refresh categories and tags' in RankOps AI.
5. Pre-launch test (do these in order)
1Test the connection
In RankOps AI Website Setup, click 'Test connection' next to the saved publish details.
Success: your receiving URL gets requests and the security key matches.Failed: jump to Troubleshooting below.2Manually publish one article
After RankOps AI generates and approves one article, trigger publish manually.
Success: the article appears in your site's content list.Failed: open the article in RankOps AI, the failure reason is shown on the article page.3Inspect the article on your site
Open the article in your site admin. Confirm the title, body, categories, tags and slug all look right.
Success: content matches what you reviewed in RankOps AI.Failed: usually a field mapping issue, see Troubleshooting.4Turn on automation after the first article looks right
After the first article is correct, enable your publish plan or switch article handling to automatic after quality check.
Success: the URL returns a public article page.Failed: see 'Published URL returns 404' in Troubleshooting.
6. Troubleshooting
401 Unauthorized
Symptom · Test connection fails with 401, or articles never reach your site.
Why · The security key saved in RankOps AI does not match the token your receiving URL is reading.
How to fix · Re-copy the key from your receiving URL environment variable. Paste into RankOps AI → Website Setup → Security key. Save, then click Test connection again.
400 Bad Request
Symptom · RankOps AI marks the article as 'publish failed' with a 400 error.
Why · A required field is missing or invalid. Most often title, slug, content, language or status.
How to fix · Open the article in RankOps AI. Check Title and SEO metadata are not empty. Re-save and trigger publish again.
409 Conflict
Symptom · 'Slug already exists' error when publishing.
Why · Your site already has a post using the same URL slug. A dryRun connection test can still pass because dryRun does not create or check a real article slug.
How to fix · Use sourceArticleId for idempotency. If the same sourceArticleId was already published, return the existing targetPostId, publishedUrl, status and slug instead of 409. If the slug belongs to a different article, keep returning 409 and change the new article slug before re-sending.
429 Too Many Requests
Symptom · Publishing fails with too_many_requests.
Why · Your receiving URL has rate limiting and received multiple requests in a short window.
How to fix · Wait a few seconds, then retry publishing the article in RankOps AI. If your site adds basic rate limiting, allow normal RankOps publish requests through and return Retry-After so the wait time is clear.
Test connection passes but articles never arrive
Symptom · Test connection shows ✓ Connection verified, but no article appears on your site.
Why · Your receiving URL may handle dryRun correctly but fail on real publish requests. Common causes: the content body being stripped, category mapping crashing, or write permission missing.
How to fix · Check your server logs for the failed request body. Focus on whether the body is truncated, categories and tags can be saved, and the current account has permission to create articles.
Real publish returns post_create_failed
Symptom · Test connection and taxonomy fetching succeed, but manually publishing an article returns 500 or post_create_failed.
Why · dryRun only validates the connection, token, and taxonomy response. A real publish also creates the post, maps categories, and matches or creates tags. A common cause is treating categories and tags as if they share the same schema, then querying a tag model with a category-only field.
How to fix · Test with one real article. Query categories only by fields that exist on the category model, and tags only by fields that exist on the tag model; do not use category-only fields such as rankOpsKey when querying tags. When post creation fails, return a structured error and a safe message so RankOps AI can show the concrete cause.
Article publishes without categories
Symptom · The article appears on the target site, but no category is attached.
Why · Usually the target site did not return categories during Test connection, or the receiving URL did not save the categories RankOps AI sent.
How to fix · 1. Confirm categories exist on the target site. 2. Ask the target-site developer to return taxonomies.categories in the dryRun response and save categories during real publish. 3. Go back to RankOps AI → Website Setup and click Refresh categories and tags. 4. Manually publish one more article and check whether the category attaches. 5. For articles already published without categories, add the category in the target site admin.
Raw ## headings appear in the article
Symptom · The article publishes, but section headings such as ## Common Problems show inside a paragraph, or the whole body looks like one large text block.
Why · RankOps AI sends the custom-site content field as Markdown. If your target site saves it as plain text and prints it directly, Markdown headings, lists, links, and spacing will not render.
How to fix · Render Markdown on the article page, or convert the Markdown body to safe HTML before saving/displaying it. Support at least h2/h3 headings, paragraphs, ordered and unordered lists, links, blockquotes, code blocks, and normal line breaks. After implementation, manually publish one article and compare the public page with the RankOps AI article preview.
Published URL returns 404
Symptom · RankOps AI shows the article as published, but opening the returned URL shows a 404.
Why · Your site's permalink cache may not have refreshed, or the article is still in a review queue.
How to fix · Refresh your site's permalink/cache settings. Check whether the article is pending review. Confirm the returned publishedUrl is the public article URL.
Article is public but RankOps AI shows publish failed
Symptom · The public article opens successfully, but RankOps AI still shows a target 500 or publish failed.
Why · The target saved the article first, then a post-publish hook such as cache refresh, IndexNow, or a webhook failed. The receiving endpoint incorrectly turned that secondary failure into a failed publish response.
How to fix · Return 200/201 and publishedUrl as soon as the article is stored successfully. Log post-publish hook failures separately. Until the endpoint is fixed, paste the real public URL on the RankOps AI article page and confirm it is already live instead of creating a duplicate.
Article stuck at ready_to_publish
Symptom · Article stays at 'ready to publish' status in RankOps AI and is never sent.
Why · The publish connection in Website Setup is missing or not verified, or the article hasn't been approved yet.
How to fix · Open Website Setup and confirm you see ✓ Connection verified. Open the article and approve it. Trigger publish from the article detail page.
7. Prompt for an AI coding assistantAdvanced
Paste this prompt into Cursor, Claude Code, Codex or another AI coding assistant inside your website project to scaffold the receiving URL with tests.
Add an SEO content receiving endpoint to my website project.
Goal: receive reviewed articles from RankOps AI and create posts on my own website.
Endpoint requirements:
1. Add POST /api/seo-content/publish. The path can be replaced with /api/rankops/publish or any project route.
2. Read Authorization: Bearer <SEO_CONTENT_PUBLISH_TOKEN> from the request headers.
3. If the token does not match, return 401 before reading the body or writing anything.
4. If the body is { dryRun: true, source: "rankops", purpose: "connection_test" }, validate the token only, do not save an article, and return { ok: true, dryRun: true, settings: { autoCreateCategories: false, autoCreateTags: true }, taxonomies: { categories: [{ title: "Payroll and Benefits", slug: "payroll" }], tags: [{ title: "payroll calculator", slug: "payroll-calculator" }] } }.
5. For normal publish requests, read sourceArticleId, title, slug, description, content, language, authorName, authorImage, categories, tags, status.
6. Required: sourceArticleId, title, slug, content, language, status. Optional: description, authorName, authorImage, categories, tags. Normal publishing sends status as 'published'.
7. Treat content as Markdown. Store it without truncation and render Markdown on the article page, or convert it to safe HTML before saving/displaying it. Support h2/h3 headings, paragraphs, ordered and unordered lists, links, blockquotes, code blocks, and normal line breaks; do not display raw ## headings to readers.
8. Store sourceArticleId and use it as the idempotency key. If the same sourceArticleId was already accepted, return the existing targetPostId, publishedUrl, status and slug instead of creating a duplicate or returning 409.
9. If the slug already exists for a different article or the sourceArticleId is unknown, return 409 with a clear message.
10. Save the article in the website content system. Map categories to existing category IDs. Keep autoCreateCategories false if you do not want RankOps AI to expand your category library.
11. If the site supports clickable tag archive pages, save tags into the native tag table or tag model and link post tags to their archive pages. Do not store tags only as plain text. Return autoCreateTags true only when new tags may be created safely. Query categories and tags against their own model/schema; do not use category-only fields such as rankOpsKey when querying tags.
12. publishedUrl must be a public HTTPS URL when status is 'published'.
13. Keep the token on the server only. Use environment variables. Do not hardcode it in frontend code or commit it to git.
14. Use HTTPS for the endpoint. Reject plain http requests.
15. Treat durable article storage as the publish success boundary. Once the article is stored and public, return 200/201 with targetPostId, publishedUrl, status, and slug.
16. Keep cache refresh, IndexNow, webhooks, analytics, and other post-publish hooks separate from the article write. If a hook fails, log the safe error without replacing the successful response with 500.
17. If the same sourceArticleId already exists, return the existing successful response before running optional post-publish hooks. A hook failure must not block the idempotent response.
18. Add tests covering: dryRun success with category and tag lists, 401 on bad token, 400 on missing required field, idempotent duplicate sourceArticleId, 409 on different article duplicate slug, successful publish with categories and clickable tags, category and tag lookups using their own schemas, Markdown content rendering to safe HTML without raw ## headings, successful publish without optional fields; also simulate a post-publish hook failure and confirm the endpoint still returns success, creates one article only, and returns the existing live URL for the same sourceArticleId.Need help? Email [email protected].