Developer Docs
Attach an OmniEditor receiver to your blog.
OmniEditor POSTs a finished article as JSON to an endpoint you control. Build a receiver in PHP, Node, or Python, validate the key, create the post, and return its public URL. Then share your endpoint + key + auth type with the OmniEditor team.
Overview
- 01Build a receiver endpoint on your blog that accepts a JSON POST request.
- 02Choose an auth method — an API Key sent in the
X-API-Keyheader, or a Bearer token. - 03Create or update the post in your CMS, then return the post’s public URL.
- 04Share your endpoint URL, key, and auth type with the OmniEditor team using the form below.
Authentication
Pick one method, configure your receiver to check it, and share the same secret and auth type back to the team.
X-API-Key Header
Send the key in a custom header.
X-API-Key: omni_8f3c2a1b9e7dBearer Token
Send the token in the standard Authorization header.
Authorization: Bearer omni_8f3c2a1b9e7dRequest payload
OmniEditor sends a JSON POST to your endpoint. action is "publish" for new posts or "update" for existing ones (then include remote_id).
{
"action": "publish",
"external_id": "art_8f3c2a",
"remote_id": null,
"article": {
"title": "How Signal Tracking Shapes Weekly SEO Strategy",
"slug": "signal-tracking-seo-strategy",
"excerpt": "Why market signals deserve a seat in your editorial calendar.",
"body_html": "<h2>...</h2><p>...</p>",
"meta_description": "Use market signals to plan weekly SEO content.",
"category": "SEO",
"tags": ["seo", "content", "research"],
"sources": ["https://example.com/source"],
"featured_image_url": "https://cdn.../cover.png",
"cta_text": "Request Access",
"cta_url": "https://omni-editor.com/#pricing"
}
}Payload shape
{
"action": "publish" | "update",
"external_id": "<article id>",
"remote_id": "<remote id if updating>",
"article": {
"title", "slug", "excerpt",
"body_html", "meta_description",
"category", "tags", "sources",
"featured_image_url", "cta_text", "cta_url"
}
}Receiver examples
Drop-in receivers that authenticate the request, upsert the post, and always return the public URL. Switch languages below.
<?php
// OmniEditor receiver — always returns the post public URL.
header('Content-Type: application/json');
// 1. Authenticate. Pick one method, store the secret server-side,
// and share the same value + auth type with the OmniEditor team.
$apiKey = getenv('OMNI_API_KEY');
$xKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
$bearer = preg_replace('/^Bearer\s+/i', '', $_SERVER['HTTP_AUTHORIZATION'] ?? '');
if ($xKey !== $apiKey && $bearer !== $apiKey) {
http_response_code(401);
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
// 2. Read the article payload.
$payload = json_decode(file_get_contents('php://input'), true);
$article = $payload['article'];
$action = $payload['action']; // "publish" | "update"
$slug = $article['slug'];
// 3. Create or update the post in your CMS (replace with your logic).
$postId = upsert_post($article, $payload['remote_id'] ?? null);
// 4. ALWAYS return the public URL so OmniEditor can confirm delivery.
$url = 'https://yourblog.com/' . $slug;
echo json_encode([
'success' => true,
'remote_id' => (string) $postId,
'url' => $url,
]);
function upsert_post($article, $remoteId) {
/* ...your CMS insert / update... */
return $remoteId ?? uniqid();
}The receiver must return the post’s public URL whenever the post is reachable — that’s how OmniEditor confirms delivery.
Response
Respond with JSON. Include url (the public post URL) and remote_id (your internal post id, so later updates target the same post).
{
"success": true,
"remote_id": "12345",
"url": "https://yourblog.com/signal-tracking-seo-strategy"
}On a bad key, return { "success": false, "error": "Unauthorized" } with a 401 status.

Your next issue is waiting