Partner Publish API (Hope)

Server-to-server endpoint for partner apps to publish a live article and matching post card in one call. No Kind Joe staff session required.

Status

Implemented at POST /api/partner/publish. Deploy with HOPE_PUBLISH_API_KEY set in production.

Endpoint

POST /api/partner/publish

Authentication

Same secret on Kind Joe and Hope (HOPE_PUBLISH_API_KEY). Use either:

  • Authorization: Bearer <HOPE_PUBLISH_API_KEY>
  • x-api-key: <HOPE_PUBLISH_API_KEY>

Request body

{
  "slug": "my-article-slug",
  "title": "Article title",
  "excerpt": "At least twelve words in the excerpt for validation.",
  "contentMarkdown": "# Full markdown body…",
  "coverImageUrl": "https://…",
  "category": "Local News",
  "tags": ["ventura-county"],
  "seo": {
    "title": "SEO title",
    "description": "Meta description — at least 70 characters required.",
    "sourceUrl": "https://original-source",
    "sourceArticleId": 12345,
    "sourceType": "news_rss_articles"
  },
  "postCard": {
    "imageUrl": "https://res.cloudinary.com/…/tile.jpg",
    "caption": "Optional"
  },
  "isVentura": true
}

Response (201)

{
  "success": true,
  "articleId": "…",
  "slug": "my-article-slug",
  "articleUrl": "https://www.kindjoe.com/ventura/my-article-slug",
  "destinationUrl": "https://www.kindjoe.com/ventura/my-article-slug",
  "postId": 42,
  "feed": "ventura",
  "authorId": "cms-writer-id"
}

What Kind Joe does

RuleBehavior
PublishLive article (isDraft: false, publishedAt = now)
AuthorRandom CMS Writer or Editor (not system-ai / rss-auto-writer)
Ventura/ventura/{slug}, tag ventura-county, row in ventura_posts
KindJoe/{slug}, row in posts
Post carddestinationUrl = article URL (same as admin post modal)

Hope env (your app)

KINDJOE_API_BASE_URL=https://www.kindjoe.com
HOPE_PUBLISH_API_KEY=<same secret as Kind Joe>
CLOUDINARY_CLOUD_NAME=…
CLOUDINARY_API_KEY=…
CLOUDINARY_API_SECRET=…

Quick test

curl -X POST "$KINDJOE_API_BASE_URL/api/partner/publish" \
  -H "Authorization: Bearer $HOPE_PUBLISH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug":"hope-test-…","title":"Test","excerpt":"Twelve word minimum excerpt for validation.","contentMarkdown":"# Test","seo":{"description":"Seventy character minimum meta description for publish validation on Kind Joe."},"postCard":{"imageUrl":"https://res.cloudinary.com/demo/image/upload/sample.jpg"}}'

Related

  • KindJoe post cards — feed tile model
  • Read-only RSS pool: see markdown doc docs/developers/rss-news-read-api.md in the repo

Errors

  • 401 — invalid/missing API key
  • 400 — validation (excerpt, SEO, body)
  • 409 — slug conflict