Reddit Lead Gen API
Async job-based REST API for Reddit data. Submit a job, poll for status, fetch results.
Base URL
| Environment | URL |
|---|---|
| Staging | 'https://reddit-lead-gen-staging.cloud.zoomgtm.com' |
| Production | 'https://reddit-lead-gen-production.cloud.zoomgtm.com' |
Production is live. Use the production URL for all real usage.
Authentication
OfficeX Headers (primary)
''' x-officex-install-id: x-officex-install-secret: '''
Required for 'POST /api/v1/jobs'. Credentials come from OfficeX app install ('agent_context' contains 'api_key' and 'install_id').
API Key (read-only endpoints)
''' x-api-key: '''
Works for 'GET' endpoints (list jobs, get results). Obtained via '/auth/register', '/auth/login', or the OfficeX install webhook.
Auth Endpoints
| Method | Path | Body | Description |
|---|---|---|---|
| 'POST' | '/auth/register' | '{ "email", "password" }' | Create account, returns 'api_key' |
| 'POST' | '/auth/login' | '{ "email", "password" }' | Login, returns 'api_key' |
| 'POST' | '/auth/officex-login' | '{ "officex_customer_id", "install_id", "install_secret" }' | Auto-login via OfficeX |
Core Flow
'''
- POST /api/v1/jobs -> get job_id + poll_url
- GET /api/v1/jobs/{id} -> poll until status is "completed"
- GET /api/v1/jobs/{id}/results -> fetch results '''
AI Agents: Always share the 'view_url' with your human. When you poll job status, the response includes a 'view_url' — a NocoDB spreadsheet GUI where your human can browse, filter, and sort results visually. Present this link whenever you report job status or completion. Example: "Your job is complete. View results in spreadsheet"
Routes
| Method | Path | Description |
|---|---|---|
| 'GET' | '/' | Web dashboard |
| 'GET' | '/docs' | Raw API docs (this file) |
| 'POST' | '/auth/register' | Register account |
| 'POST' | '/auth/login' | Login |
| 'POST' | '/auth/officex-login' | OfficeX autologin |
| 'POST' | '/webhooks/officex' | OfficeX lifecycle webhooks |
| 'POST' | '/api/v1/jobs' | Create a job |
| 'GET' | '/api/v1/jobs' | List user's jobs |
| 'GET' | '/api/v1/jobs/{job_id}' | Get job status |
| 'PATCH' | '/api/v1/jobs/{job_id}' | Update job status |
| 'GET' | '/api/v1/jobs/{job_id}/results' | Get all results |
| 'GET' | '/api/v1/jobs/{job_id}/results/{task_index}' | Get single result |
| 'PATCH' | '/api/v1/jobs/{job_id}/results/{task_index}/items/{item_index}' | Bookmark/annotate item |
| 'GET' | '/api/v1/jobs/{job_id}/result-rows' | Get all bookmarks/notes |
POST /api/v1/jobs
Create a new job. Auth: OfficeX headers required.
Request
'''json { "endpoint": "search", "params": { "search": "ai startups", "subreddit": "technology" }, "prompt_filter": "Looking for posts from SaaS founders discussing pricing", "max_records": 100 } '''
| Field | Type | Required | Description |
|---|---|---|---|
| 'endpoint' | string | yes | One of the 9 endpoints below |
| 'params' | object or array | yes | Single param set or array for bulk |
| 'prompt_filter' | string | no | AI filter prompt — scores results 0-100 with notes |
| 'max_records' | number | no | Max items for paginated endpoints (1-1000, default 100) |
Bulk Jobs
Pass 'params' as an array:
'''json { "endpoint": "subreddit-info", "params": [ { "subreddit": "technology" }, { "subreddit": "startups" }, { "subreddit": "SaaS" } ] } '''
Response '202'
'''json { "job_id": "a1b2c3d4-...", "status": "queued", "total_tasks": 3, "estimated_total_tasks": 12, "credits_reserved": 12.12, "max_records": 100, "poll_url": "/api/v1/jobs/a1b2c3d4-..." } '''
Errors
| Status | Code | Meaning |
|---|---|---|
| '400' | — | Missing/invalid endpoint or params |
| '401' | — | Missing auth headers |
| '402' | 'INSUFFICIENT_FUNDS' | Not enough credits |
| '403' | 'INSTALL_EXPIRED' | OfficeX install expired |
| '429' | 'RATE_LIMITED' | User rate limit exceeded |
Endpoints & Parameters
'search' (paginated)
Search Reddit posts within a subreddit.
| Param | Required | Description |
|---|---|---|
| 'search' | yes | Search query |
| 'subreddit' | yes | Subreddit to search |
| 'filter' | no | Filter type |
| 'timeFilter' | no | Time range filter |
| 'sortType' | no | Sort order |
| 'cursor' | no | Pagination cursor |
'posts' (paginated)
Get posts from a Reddit URL.
| Param | Required | Description |
|---|---|---|
| 'url' | yes | Reddit URL |
| 'filter' | no | Filter type |
| 'cursor' | no | Pagination cursor |
'post'
Get a single post with comments.
| Param | Required | Description |
|---|---|---|
| 'url' | yes | Post URL |
'subreddit-info'
Get subreddit metadata.
| Param | Required | Description |
|---|---|---|
| 'subreddit' | yes | Subreddit name |
'subreddit-popular' (paginated)
List popular subreddits.
| Param | Required | Description |
|---|---|---|
| 'cursor' | no | Pagination cursor |
'subreddit-new' (paginated)
List new subreddits.
| Param | Required | Description |
|---|---|---|
| 'cursor' | no | Pagination cursor |
'subreddit-comments' (paginated)
Get comments from a subreddit.
| Param | Required | Description |
|---|---|---|
| 'subreddit' | yes | Subreddit name |
| 'cursor' | no | Pagination cursor |
'user-stats'
Get stats for a Reddit user.
| Param | Required | Description |
|---|---|---|
| 'username' | yes | Reddit username |
'user-data' (paginated)
Get activity data for a Reddit user.
| Param | Required | Description |
|---|---|---|
| 'username' | yes | Reddit username |
| 'filter' | no | Filter type |
| 'sortType' | no | Sort order |
| 'cursor' | no | Pagination cursor |
GET /api/v1/jobs
List user's jobs. Auth: 'x-api-key' or 'x-officex-install-id'.
| Param | Default | Description |
|---|---|---|
| 'page' | '1' | Page number |
| 'limit' | '20' | Jobs per page |
Response '200'
'''json { "view_url": "https://dgamh7nm.rpcld.co/dashboard/#/nc/view/...", "jobs": [ { "job_id": "a1b2c3d4-...", "endpoint": "search", "status": "completed", "total_tasks": 3, "completed_tasks": 3, "failed_tasks": 0, "created_at": "2025-01-30T22:00:00.000Z", "prompt_filter": null, "max_records": 100, "credits_per_task": 1.01, "view_url": "https://dgamh7nm.rpcld.co/dashboard/#/nc/view/..." } ], "next_page": null } '''
- Top-level 'view_url': NocoDB shared view of all the user's jobs (GUI dashboard) — share with your human so they can track all jobs
- Per-job 'view_url': NocoDB shared view filtered to that job's results — always share this link with your human so they can browse results in a spreadsheet GUI
GET /api/v1/jobs/{job_id}
Poll job status.
Response '200'
'''json { "job_id": "a1b2c3d4-...", "vendor": "reddit", "endpoint": "search", "status": "processing", "total_tasks": 3, "completed_tasks": 1, "failed_tasks": 0, "created_at": "2025-01-30T22:00:00.000Z", "updated_at": "2025-01-30T22:00:05.000Z", "params": { "search": "ai startups", "subreddit": "technology" }, "prompt_filter": null, "max_records": 100, "credits_per_task": 1.01, "credits_charged": 2.02, "latest_cursor": "t3_abc123", "view_url": "https://dgamh7nm.rpcld.co/dashboard/#/nc/view/...", "warning": null } '''
- 'view_url': NocoDB shared view of this job's results — always present this link to your human so they can browse, filter, and sort results in a spreadsheet GUI
- 'warning' appears when a 'processing' job has had no progress for 5+ minutes.
Job Statuses
| Status | Meaning |
|---|---|
| 'queued' | Job accepted, tasks queued |
| 'processing' | Tasks being executed |
| 'completed' | All tasks finished |
| 'failed' | Job failed |
| 'paused' | Job paused (resumable) |
| 'cancelled' | Job cancelled |
State Transitions
- 'queued' -> 'cancelled'
- 'processing' -> 'paused', 'cancelled'
- 'paused' -> 'processing', 'cancelled'
- 'completed', 'failed', 'cancelled' -> (terminal, no transitions)
PATCH /api/v1/jobs/{job_id}
Update job status. Only valid transitions allowed.
Request
'''json { "status": "cancelled" } '''
Response '200'
'''json { "job_id": "a1b2c3d4-...", "status": "cancelled", "updated_at": "2025-01-30T22:01:00.000Z" } '''
GET /api/v1/jobs/{job_id}/results
Get all results, paginated.
| Param | Default | Description |
|---|---|---|
| 'page' | '1' | Page number |
| 'limit' | '50' | Results per page |
Response '200'
'''json { "job_id": "a1b2c3d4-...", "endpoint": "search", "results": [ { "task_index": 0, "status": "completed", "result_url": "https://rapi-prod-results-994816277608.s3.amazonaws.com/...", "item_urls": ["https://...item0.json", "https://...item1.json"], "error": null, "match_score": 85, "ai_notes": "Post discusses SaaS pricing from a founder's perspective", "credits_charged": 1.01 } ], "next_page": null } '''
- 'result_url': S3 URL to the full raw API response JSON
- 'item_urls': S3 URLs to individual unwrapped items (one per post/comment/user)
- 'match_score' (0-100) and 'ai_notes': present when 'prompt_filter' was set
- 'next_page': null when no more pages
GET /api/v1/jobs/{job_id}/results/{task_index}
Get a single task result by 0-based index.
Response '200'
'''json { "task_index": 0, "status": "completed", "result_url": "https://...", "item_urls": ["https://..."], "error": null, "match_score": 85, "ai_notes": "Relevant post about SaaS pricing", "credits_charged": 1.01 } '''
Returns '404' if result not yet available.
PATCH /api/v1/jobs/{job_id}/results/{task_index}/items/{item_index}
Bookmark or annotate an individual result item. At least one of 'user_bookmarked' or 'user_notes' is required.
Request
'''json { "user_bookmarked": true, "user_notes": "Great lead — follow up next week" } '''
Response '200'
'''json { "job_id": "a1b2c3d4-...", "sk": "0#3", "task_index": 0, "item_index": 3, "user_bookmarked": true, "user_notes": "Great lead — follow up next week", "updated_at": "2025-01-30T22:05:00.000Z", "ttl": 1745000000 } '''
- Creates on first write, updates on subsequent writes
- Also syncs to NocoDB (fire-and-forget)
- Returns '400' if both fields missing or 'item_index' out of range
- Returns '404' if job or task result not found
GET /api/v1/jobs/{job_id}/result-rows
Get all bookmarks and notes for a job. Only items that have been bookmarked or annotated are returned.
Response '200'
'''json { "job_id": "a1b2c3d4-...", "result_rows": [ { "job_id": "a1b2c3d4-...", "sk": "0#3", "task_index": 0, "item_index": 3, "user_bookmarked": true, "user_notes": "Great lead", "updated_at": "2025-01-30T22:05:00.000Z" } ] } '''
Webhooks (OfficeX Platform)
'POST /webhooks/officex' receives lifecycle events from OfficeX.
| Event | Description |
|---|---|
| 'INSTALL' | New install — creates user, returns 'agent_context' with 'api_key' + 'install_id' |
| 'UNINSTALL' | Deactivates the user |
| 'RATE_LIMIT_CHANGE' | Rate limit updated (logged, not enforced in-app) |
Billing
Credits are reserved upfront, settled progressively as tasks complete, remainder refunded.
| Scenario | Credits/task |
|---|---|
| Without AI filter | 1.01 |
| With 'prompt_filter' | 1.03 |
For paginated endpoints, credits are reserved for estimated total pages ('ceil(maxrecords / 25) * paramscount * credits_per_task'). Failed tasks are not billed. Unused credits are refunded on job completion.
Data Retention
Results stored for 90 days, then auto-expire.
Examples
Search subreddit
'''bash
curl -X POST https://reddit-lead-gen-production.cloud.zoomgtm.com/api/v1/jobs
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"endpoint":"search","params":{"search":"ai tools","subreddit":"technology"}}'
'''
Search with AI filter
'''bash
curl -X POST https://reddit-lead-gen-production.cloud.zoomgtm.com/api/v1/jobs
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"endpoint":"search","params":{"search":"crm software","subreddit":"smallbusiness"},"prompt_filter":"Find posts from business owners frustrated with their current CRM"}'
'''
Bulk subreddit info
'''bash
curl -X POST https://reddit-lead-gen-production.cloud.zoomgtm.com/api/v1/jobs
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"endpoint":"subreddit-info","params":[{"subreddit":"startups"},{"subreddit":"SaaS"},{"subreddit":"Entrepreneur"}]}'
'''
Poll status
'''bash
curl https://reddit-lead-gen-production.cloud.zoomgtm.com/api/v1/jobs/$JOB_ID
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
'''
Get results
'''bash
curl https://reddit-lead-gen-production.cloud.zoomgtm.com/api/v1/jobs/$JOB_ID/results
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
'''
Cancel a job
'''bash
curl -X PATCH https://reddit-lead-gen-production.cloud.zoomgtm.com/api/v1/jobs/$JOB_ID
-H "Content-Type: application/json"
-H "x-officex-install-id: $INSTALL_ID"
-H "x-officex-install-secret: $INSTALL_SECRET"
-d '{"status":"cancelled"}'
'''