RankForge is a production-ready API-only service that generates 5,000-6,000 word SEO + AEO + GEO optimized articles in ≤5 minutes that rank #1 on Google.
The system uses a two-step asynchronous process:
POST /api/v1/generate to queue a job.POST /api/internal/process-job for processing.GET /api/v1/jobs/[id] for status and results.graph TD
A[Client POST /api/v1/generate] --> B[Validate Input & Rate Limit]
B --> C[Create Job in Supabase]
C --> D[Enqueue to QStash]
D --> E[Return 202 + jobId]
Q[QStash Delivers] --> F[POST /api/internal/process-job]
F --> G[Run Pipeline Orchestrator]
G --> H[Phase 1: SERP DataForSEO]
H --> I[Phase 2: Crawl Bright Data]
I --> J[Phase 3: N-grams Analysis]
J --> K[Phase 4: Brief Gemini Flash]
K --> L[Phase 5: Write Sections Parallel]
L --> M[Phase 6: Fetch Images Parallel]
M --> N[Phase 7: Internal Links]
N --> O[Phase 8: Assemble HTML]
O --> P[Phase 9: QA Validation]
P --> Q[Phase 10: Finalize & Store]
Q --> R[Update Supabase Status/Result]
S[Client GET /api/v1/jobs/[id]] --> T[Fetch Status/Progress/Result from Supabase]
U[External APIs: DataForSEO, Bright Data, Gemini] -.-> G
V[Cache: Redis] -.-> G
W[DB: Supabase] -.-> C
W -.-> R
W -.-> T
X[Storage: Supabase Bucket] -.-> QNote: You will need a Mermaid diagram renderer to see the above graph.
The API has 22 strictly required fields, 14 fields with defaults, and ~11 optional fields (~47 total parameters). For comprehensive documentation including all fields, validation rules, and complete cURL examples, see:
📖 Documentation File: docs/API-REFERENCE.md
Includes: Minimal cURL Example | Full-Featured cURL Example | Complete Field Reference | Error Response Examples
POST /api/v1/generateQueues a new article generation job.
Response (202 Accepted):
{
"jobId": "uuid",
"status": "queued",
"message": "Job queued for processing. Poll /api/v1/jobs/{jobId} for status.",
"estimatedCompletionTime": "YYYY-MM-DDTHH:mm:ss.sssZ"
}GET /api/v1/jobs/[id]Gets the status and progress of a job.
Response (200 OK):
{
"jobId": "uuid",
"status": "completed",
"progress": 100,
"createdAt": "YYYY-MM-DDTHH:mm:ss.sssZ",
"updatedAt": "YYYY-MM-DDTHH:mm:ss.sssZ",
"completedAt": "YYYY-MM-DDTHH:mm:ss.sssZ"
}GET /api/v1/jobs/[id]/resultGets the result of a completed job.
Response (200 OK):
{
"jobId": "uuid",
"result": {
// Full GeneratedArticle object
},
"completedAt": "YYYY-MM-DDTHH:mm:ss.sssZ"
}The API has 22 strictly required fields (validation fails without them), 14 fields with defaults (optional to provide), and ~11 purely optional fields.
| Field | Type | Description |
|---|---|---|
| session_id | string | Unique session identifier for rate limiting |
| primaryKeyword | string | Main keyword for article generation |
| wordCount | number | Target word count (1000-15000) |
| contentType | string | Article type: guide, listicle, comparison, howto, review, pillar |
| tone | string | Writing tone: professional, casual, technical, friendly, authoritative |
| targetAudience | string | Target audience description |
| readingLevel | string | Reading level: elementary, high-school, college, professional |
| targetSearchIntent | string | Search intent: informational, commercial, transactional |
| language | string | Content language (default: en) |
| target_country | string | Target country (default: US) |
| DataForSEO_Location_Code | string | DataForSEO location code |
| DataForSEO_Language_Code | string | DataForSEO language code |
| client_name | string | Client company name |
| client_website | string | Client website URL |
| client_description | string | Client business description |
| client_icp | string | Client ideal customer profile |
| author_name | string | Article author name |
| author_title | string | Author professional title |
| schemaType | string | Schema.org type: Article, HowTo, FAQPage, Review, Product |
| brandColor | string | Brand color in hex format |
| sitemapURL | string | Client sitemap URL |
| blogRootURL | string | Client blog root URL |
| aeo | object | AEO configuration object (has internal defaults) |
| Field | Type | Description | Default |
|---|---|---|---|
| numImages | number | Number of images to include (0-50) | 0 |
| addInfographics | boolean | Include infographic images | false |
| includeFaq | boolean | Include FAQ section | false |
| includeTables | boolean | Include data tables | false |
| includeStatistics | boolean | Include statistical data | false |
| includeExpertQuotes | boolean | Include expert quotations | false |
| includeReferences | boolean | Include references section | false |
| addYoutubeVideo | boolean | Include YouTube videos | false |
| addEmojis | boolean | Include emojis in content | false |
| addCTA | boolean | Include call-to-action | false |
| ctaPlacement | string | CTA placement: top, bottom, both, inline, multiple, none | none |
| addExternalLink | boolean | Include external links | false |
| externalLinksCount | number | Number of external links (0-100) | 0 |
| internalLinksNumber | number | Number of internal links (0-100) | 3 |
| tocPlacement | string | Table of contents placement: top, sidebar, floating, none | none |
| Field | Type | Description | Default |
|---|---|---|---|
| seedKeyword | string | Secondary keyword for SERP research | - |
| longTailKeyword | string | Long-tail keyword variation | - |
| focusKeyphrases | string[] | Additional keyphrases to target | - |
| subTopics | string[] | Article subtopics (auto-derived if omitted) | - |
| author_bio | string | Author biography (boosts E-A-T) | - |
| author_credentials | string | Author credentials | - |
| imageStyle | string | Image style description | - |
| youtubeVideoUrl | string | Specific YouTube video URL | - |
| youtubeSearchQuery | string | YouTube search query | - |
| youtubeVideoCount | number | Number of YouTube videos (1-10) | - |
| emojiDensity | string | Emoji density: light, moderate, heavy | - |
| ctaText | string | CTA button text | - |
| ctaUrl | string | CTA destination URL | - |
| externalLinkDomains | string[] | Preferred external domains | - |
| externalLink | string | Specific external link URL | - |
| mustIncludeSections | string[] | Required section titles | - |
| excludeTopics | string[] | Topics to avoid | - |
| metaDescriptionGuidelines | string | Meta description instructions | - |
| globalArticleInstructions | string | General writing instructions | - |
| bestArticleExampleOne | string | Example article URL 1 | - |
| bestArticleExampleTwo | string | Example article URL 2 | - |
| bestArticleExampleThree | string | Example article URL 3 | - |
| competitorUrls | string[] | Competitor analysis URLs | - |
curl -X POST https://your-domain.com/api/v1/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "your-session-id",
"primaryKeyword": "your keyword",
"wordCount": 5000,
"contentType": "guide",
"tone": "professional",
"targetAudience": "business owners",
"readingLevel": "college",
"targetSearchIntent": "informational",
"language": "en",
"target_country": "US",
"DataForSEO_Location_Code": "2840",
"DataForSEO_Language_Code": "en",
"client_name": "Your Company",
"client_website": "https://yourcompany.com",
"client_description": "Your company description",
"client_icp": "Your ideal customer profile",
"author_name": "John Doe",
"author_title": "SEO Specialist",
"numImages": 5,
"tocPlacement": "top",
"schemaType": "Article",
"brandColor": "#007bff",
"sitemapURL": "https://yourcompany.com/sitemap.xml",
"blogRootURL": "https://yourcompany.com/blog"
}'curl -X POST https://your-domain.com/api/v1/generate \
-H "Content-Type: application/json" \
-d '{
"session_id": "your-session-id",
"primaryKeyword": "your keyword",
"seedKeyword": "secondary keyword",
"longTailKeyword": "long tail keyword",
"focusKeyphrases": ["keyphrase1", "keyphrase2"],
"subTopics": ["topic1", "topic2"],
"wordCount": 5000,
"contentType": "guide",
"tone": "professional",
"targetAudience": "business owners",
"readingLevel": "college",
"targetSearchIntent": "informational",
"language": "en",
"target_country": "US",
"DataForSEO_Location_Code": "2840",
"DataForSEO_Language_Code": "en",
"client_name": "Your Company",
"client_website": "https://yourcompany.com",
"client_description": "Your company description",
"client_icp": "Your ideal customer profile",
"author_name": "John Doe",
"author_title": "SEO Specialist",
"author_bio": "Author bio",
"author_credentials": "PhD in Marketing",
"numImages": 5,
"imageStyle": "professional",
"addInfographics": true,
"includeFaq": true,
"includeTables": true,
"includeStatistics": true,
"includeExpertQuotes": true,
"includeReferences": true,
"addYoutubeVideo": true,
"youtubeVideoUrl": "https://youtube.com/watch?v=123",
"youtubeSearchQuery": "your search",
"youtubeVideoCount": 2,
"addEmojis": true,
"emojiDensity": "moderate",
"addCTA": true,
"ctaText": "Contact Us",
"ctaUrl": "https://yourcompany.com/contact",
"ctaPlacement": "bottom",
"addExternalLink": true,
"externalLinksCount": 3,
"externalLinkDomains": ["example.com"],
"externalLink": "https://example.com",
"internalLinksNumber": 5,
"tocPlacement": "top",
"mustIncludeSections": ["Introduction", "Conclusion"],
"excludeTopics": ["topic to avoid"],
"schemaType": "Article",
"metaDescriptionGuidelines": "Meta description instructions",
"aeo": {
"enableAIOBox": true,
"faqCount": 5
},
"brandColor": "#007bff",
"sitemapURL": "https://yourcompany.com/sitemap.xml",
"blogRootURL": "https://yourcompany.com/blog",
"globalArticleInstructions": "General instructions",
"bestArticleExampleOne": "https://example.com/article1",
"bestArticleExampleTwo": "https://example.com/article2",
"bestArticleExampleThree": "https://example.com/article3",
"competitorUrls": ["https://competitor.com"]
}'These are the fields returned by the API that you should save in your Neon PostgreSQL database for your frontend.
| Field | Type | Description |
|---|---|---|
| slug | string | URL-friendly identifier |
| seo_title | string | 50-60 char title for H1 and title tag |
| snippet_intro | string | 40-55 words featured snippet text |
| meta_description | string | 140-160 chars for meta tag |
| article_html | text | Clean semantic HTML content |
| hero_image | jsonb | {url, width, height, alt} or null |
| author | jsonb | {name, slug, role, bio?, credentials?, social_links[]} |
| date_published | timestamp | ISO 8601 publish date |
| date_modified | timestamp | ISO 8601 last modified (optional) |
| reading_time | integer | Minutes to read |
| word_count | integer | Total word count |
| content_hash | string | For deduplication |
| schema | jsonb | Article schema.org JSON-LD |
| schema_faq | jsonb | FAQ schema.org JSON-LD (if FAQ enabled) |
| images | jsonb[] | Array of image objects |
| Field | Type | Description |
|---|---|---|
| html | text | Legacy HTML with inline styles |
| clean_html | text | Clean HTML without styles |
| plain_text | text | Plain text version |
| sections | jsonb[] | Individual section data |
| table_of_contents | jsonb[] | TOC structure |
| faq | jsonb[] | FAQ Q&A pairs |
| key_takeaways | text[] | Bullet points for snippets |
| aio_box | jsonb | AI Overview optimized content |
| videos | jsonb[] | YouTube embeds |
| internal_links | jsonb[] | Internal link data |
| external_links | jsonb[] | External link data |
| metrics | jsonb | Quality metrics object |
| processing_time | integer | Milliseconds to generate |
| generated_at | timestamp | When article was created |
POST /api/v2/generateThe v2 endpoint uses a 4-Burst Parallel Architecture that generates articles in ~2.5-3.5 minutes (vs v1's ~5-6 min). It accepts the same payload as v1 plus additional fields for EEAT, GEO, and advanced schema optimization. The Get Status tab works for both v1 and v2 jobs — they use the same Supabase job storage.
| Burst | Name | Duration | Tasks |
|---|---|---|---|
| 1 | Data Vacuum | ~45-50s | SERP + Web Crawl + Client Intel + Stat Extraction (all parallel) |
| 2 | Master Contract | ~30-40s | N-grams → Enhanced Brief (sequential) |
| 3 | Massive Fan-Out | ~60-90s | Section Writer + Media + FAQ + Links + Schema (5 parallel workers) |
| 4 | Instant Assembly | ~20-30s | Assembly → QA → Finalize |
| Field | Type | Default | Description |
|---|---|---|---|
author_linkedin_url | string (URL) | — | LinkedIn URL → sameAs in Person schema |
author_alma_mater | string | — | University → alumniOf in Person schema |
author_knows_about | string[] | — | Topics → knowsAbout in schema |
enableStatExtraction | boolean | true | Extract citeable stats (GEO pillar) |
enableEEATParagraphs | boolean | true | First-hand experience paragraphs |
enableAdvancedSchema | boolean | true | Nested @graph JSON-LD schema |
enableAIMetaTags | boolean | true | AI-generated SEO title, meta, OG tags |
organization_logo_url | string (URL) | — | Logo for Organization schema |
organization_founding_date | string | — | Founding date for Organization schema |
canonical_url | string (URL) | — | Canonical URL for the article |
| Feature | v1 | v2 |
|---|---|---|
| Pipeline | 10-phase sequential | 4-burst parallel |
| Speed | ~5-6 minutes | ~2.5-3.5 minutes |
| Schema | Single type | Nested @graph (Article + Person + Org + WebPage) |
| GEO | — | Auto-extracted citeable statistics |
| EEAT | Basic author fields | LinkedIn, alumniOf, knowsAbout in schema |
| Meta Tags | Rule-based | AI-generated (Gemini) title, description, OG |
| Result JSON | 30+ fields | All v1 + schemaGraph + ogTags + statisticsUsed |