AI-powered meta title and description generation. PRO only.
POST /rankforge/v1/meta/generate
Generate AI-powered meta title and description for a post. Consumes one AI credit per call.
curl -X POST -u "admin:ABCD 1234 EFGH 5678 IJKL 9012" \
-H "Content-Type: application/json" \
-d '{"post_id": 42}' \
https://example.com/wp-json/rankforge/v1/meta/generate{
"title": "Complete WordPress SEO Guide 2024 | MyBlog",
"description": "Learn the essential WordPress SEO techniques to boost your rankings. Step-by-step guide covering on-page optimization, schema markup, and more."
}titleis 50-60 characters (inclusive)descriptionis 140-160 characters (inclusive)- If the post has a focus keyword, it appears verbatim (case-insensitive) in both
titleanddescription - If the AI gives no usable answer (the call fails or the text still misses these limits after the retries), Rank Forge falls back to a rule-based title or description that can be outside these limits. A site that is not connected or is out of credits gets an error instead.
Credits live in a single account-level pool, and the packs you buy do not expire. A site that pays with an active Pro license key gets the error credits_exhausted when the pool is empty. A site that pays with its connected Avakode account gets:
{
"success": false,
"error": "credits_account_exhausted",
"message": "Your Avakode account has no credits left.",
"link": "https://avakode.com/dashboard/credits/",
"remaining": 0
}{
"code": "rest_forbidden",
"message": "This feature requires a PRO license.",
"data": { "status": 403 }
}POST /rankforge/v1/brief/generate
Generate an AI content brief for a target keyword. PRO only.
curl -X POST -u "admin:ABCD 1234 EFGH 5678 IJKL 9012" \
-H "Content-Type: application/json" \
-d '{"keyword": "wordpress seo tips"}' \
https://example.com/wp-json/rankforge/v1/brief/generateThe response is the brief the AI wrote, as JSON. The AI is asked for title_suggestions, h2_structure, key_points, questions_to_answer, word_count and related_keywords, and the response keeps what it sent. For the Content Brief screen Rank Forge adds headings (from h2_structure) and target_word_count (from word_count) when those hold a value. As of 2026-04 (SF-123) the response also carries history_id — the ID of the saved copy in the user’s brief history — which the client uses to link the freshly-generated result in the /brief/history list.
GET /rankforge/v1/brief/history
List the current user’s saved briefs. PRO only. Credits are not consumed by this endpoint.
curl -u "admin:ABCD ..." https://example.com/wp-json/rankforge/v1/brief/history{
"briefs": [
{ "id": "a1b2c3d4e5f6", "keyword": "wordpress seo", "created_at": 1776961649 },
{ "id": "f6e5d4c3b2a1", "keyword": "schema markup", "created_at": 1776875249 }
],
"max": 50
}GET /rankforge/v1/brief/history/{id}
Return the full result payload of a saved brief — always free (the original generation already paid for it).
curl -u "admin:ABCD ..." https://example.com/wp-json/rankforge/v1/brief/history/a1b2c3d4e5f6{
"id": "a1b2c3d4e5f6",
"keyword": "wordpress seo",
"created_at": 1776961649,
"result": {
"title_suggestions": ["..."],
"h2_structure": ["..."],
"key_points": ["..."],
"questions_to_answer": ["..."],
"word_count": 1200,
"related_keywords": ["..."],
"headings": ["..."],
"target_word_count": 1200
}
}Returns 404 { "code": "not_found", "message": "Brief not found" } if the ID does not belong to the current user.
DELETE /rankforge/v1/brief/history/{id}
Permanently remove a saved brief. Prompt the user for confirmation before calling this — the paid-for result is unrecoverable.
curl -X DELETE -u "admin:ABCD ..." https://example.com/wp-json/rankforge/v1/brief/history/a1b2c3d4e5f6{ "success": true }POST /rankforge/v1/meta/preview
Generate an AI suggestion for a Meta Title / Description / Focus Keyword without persisting it. Consumes credits (same cost as /meta/generate) but returns the current stored value plus the fresh AI output so the client can render a side-by-side review UI (used by SF-121’s drawer in Site Audit).
curl -X POST -u "admin:ABCD ..." \
-H "Content-Type: application/json" \
-d '{"post_id": 42, "type": "title"}' \
https://example.com/wp-json/rankforge/v1/meta/previewtype must be one of title / description / keyword.
Response (200 OK):
{
"success": true,
"post_id": 42,
"type": "title",
"current": "About Us",
"suggestion": "About Our Team — 25 Years of Honest Work | Example"
}On credits exhausted the endpoint returns the standard credits-exhausted envelope (same as /meta/generate).
POST /rankforge/v1/meta/apply
Persist a user-reviewed value (possibly edited after preview) to the matching post meta key. No credits consumed. Re-runs the rule-based analyzer so the metabox score reflects the change immediately.
curl -X POST -u "admin:ABCD ..." \
-H "Content-Type: application/json" \
-d '{"post_id": 42, "type": "description", "value": "Final hand-edited description"}' \
https://example.com/wp-json/rankforge/v1/meta/apply{
"success": true,
"post_id": 42,
"type": "description",
"value": "Final hand-edited description"
}POST /rankforge/v1/fix/{post_id}
AI-powered auto-fix for a specific SEO issue, applied immediately. PRO only. Used by the legacy in-place flow; the drawer-aware flow below is preferred for new clients because the user gets to review the rewrite first.
curl -X POST -u "admin:ABCD 1234 EFGH 5678 IJKL 9012" \
-H "Content-Type: application/json" \
-d '{"issue_message": "No headings (H2-H6) found in content"}' \
https://example.com/wp-json/rankforge/v1/fix/42{
"success": true,
"message": "Issue fixed and content updated.",
"new_score": 78
}POST /rankforge/v1/fix/preview
Generate an AI rewrite for a content-rewrite issue (thin content, duplicate titles, no internal links, missing H1, missing alt text — anything that operates on the post body) without persisting it. Mirror of /meta/preview but for post_content instead of meta fields. Spends a credit. Returns the current content plus the AI rewrite so the client can render the side-by-side review drawer used by SF-121’s content mode.
curl -X POST -u "admin:ABCD ..." \
-H "Content-Type: application/json" \
-d '{"post_id": 42, "issue_message": "Thin content (under 300 words)", "issue_type": "thin_content"}' \
https://example.com/wp-json/rankforge/v1/fix/previewissue_type is the canonical issue code (thin_content, no_internal_links, missing_h1, missing_alt, duplicate_titles). Optional, but the drawer passes it through so the cache prune in /fix/apply can scope to the matching issue group.
Response (200 OK):
{
"success": true,
"post_id": 42,
"type": "content",
"issue_type": "thin_content",
"current": "Original post body here…",
"suggestion": "Rewritten post body with added depth, examples, and structure…"
}If the AI returns an empty string or the same content as the original, the response is { "success": false, "error": "AI could not improve this issue further. Edit the content manually or try a different fix." } — the client should keep the row in the audit list and let the user edit manually.
POST /rankforge/v1/fix/apply
Persist a user-reviewed (and possibly edited) content rewrite. No credits consumed. Re-runs the rule-based analyzer so the metabox score updates immediately, and surgically prunes the cached site audit (only the matching issue group is touched, the rest of the audit stays put).
curl -X POST -u "admin:ABCD ..." \
-H "Content-Type: application/json" \
-d '{"post_id": 42, "value": "Final reviewed post body…", "issue_type": "thin_content"}' \
https://example.com/wp-json/rankforge/v1/fix/apply{
"success": true,
"post_id": 42,
"new_score": 81
}issue_type is optional but recommended — if omitted, the cache prune walks every issue group looking for the post id (still correct, just more work).
—