Instagram RapidAPI Proxy — OfficeX App
Production is live and should always be used.
App ID (Production): 'b472aaf3-9b17-4d8c-b818-a6f8e2152eb5'
Single-vendor RapidAPI proxy wrapping 'instagram-social.p.rapidapi.com' as an OfficeX app. Serverless, AWS-native, scale-to-zero. See TEMPLATE_ARCHITECTURE.md for the full generic template this project implements.
Instagram API Reference
See .claude/skills/rapidapi-instagram/references/api_reference.md for full endpoint docs with parameters and response schemas.
Quick Reference
| Endpoint |
Path |
Required Param |
Paginated |
| 'search' |
'/search' |
'search' |
no |
| 'users-search' |
'/users/search' |
'search' |
no |
| 'hashtags-search' |
'/hashtags/search' |
'search' |
no |
| 'profile' |
'/profile' |
'username' |
no |
| 'followers' |
'/followers' |
'username' |
yes |
| 'following' |
'/following' |
'username' |
yes |
| 'posts' |
'/posts' |
'username' |
yes |
| 'highlights' |
'/highlights' |
'username' |
no |
| 'info' |
'/info' |
'code' (shortcode) |
no |
| 'comments' |
'/comments' |
'code' (shortcode) |
yes |
| 'likes' |
'/likes' |
'code' (shortcode) |
yes |
Authentication
'''
Headers:
X-RapidAPI-Key: {RAPID_API_KEY from .env}
X-RapidAPI-Host: instagram-social.p.rapidapi.com
Base URL: https://instagram-social.p.rapidapi.com/api/v1/instagram
Method: GET (all endpoints)
'''
Response Format
'''json
{
"meta": { "version": "v1.0", "status": 200, "pagination_token": "..." | null },
"body": [ ... ] // array for list endpoints, object for /profile, /info
}
'''
Pagination: pass 'pagination_token' as query param for next page. 'null' = no more pages.
Direct Usage
'''javascript
import 'dotenv/config';
const BASE = 'https://instagram-social.p.rapidapi.com/api/v1/instagram';
const headers = {
'x-rapidapi-key': process.env.RAPID_API_KEY,
'x-rapidapi-host': 'instagram-social.p.rapidapi.com'
};
const res = await fetch('{BASE}/profile?username=mrbeast', { headers });
const data = await res.json(); // data.meta, data.body
'''
REST API (This App's Endpoints)
Auth for all job/status endpoints: 'x-officex-install-id' + 'x-officex-install-secret' headers.
Submit Job
'''
POST /api/v1/jobs
// Single (quick queue):
{ "endpoint": "profile", "params": { "username": "mrbeast" }, "prompt_filter": "optional AI filter" }
// Batch (bulk queue):
{ "endpoint": "posts", "params": [{ "username": "a" }, { "username": "b" }], "max_records": 100 }
// Response (202):
{ "job_id": "...", "status": "queued", "total_tasks": 1, "credits_reserved": 1.01, "poll_url": "/api/v1/jobs/..." }
'''
Poll & Results
'''
GET /api/v1/jobs/{job_id} — Job progress + cost breakdown
GET /api/v1/jobs/{job_id}/results — Paginated results (preview + match_score + S3 URLs)
GET /api/v1/jobs — List user's jobs
PATCH /api/v1/jobs/{job_id} — Cancel: { "status": "cancelled" }
'''
Result Items & Bookmarks
'''
GET /api/v1/jobs/{job_id}/results/{task_index}/items/{item_index}
PATCH /api/v1/jobs/{job_id}/results/{task_index}/items/{item_index} — { "user_bookmarked": true, "user_notes": "..." }
GET /api/v1/jobs/{job_id}/result-rows — All bookmarks/notes for a job
'''
Auth & Webhooks
'''
POST /auth/register — { email, password } → { api_key, install_id }
POST /auth/login — { email, password } → { api_key, install_id }
POST /auth/officex-login — { officex_customer_id, install_id, install_secret } → { api_key }
POST /webhooks/officex — INSTALL / UNINSTALL / RATE_LIMIT_CHANGE events
POST /api/v1/webhooks/nocodb — NocoDB 2-way sync (bookmark/notes)
GET / — Frontend HTML
GET /docs — API documentation
'''
Architecture
'''
POST /api/v1/jobs → Ingress Lambda (validate + reserve credits + queue)
↓
┌──────────┴──────────┐
Quick Queue (80%) Bulk Queue (20%)
↓ ↓
Quick Dispatcher Bulk Dispatcher
└──────────┬──────────┘
Worker Lambda 1. Call Instagram API 2. Save to S3 (public URL, 90d) 3. Extract preview → DynamoDB 4. AI filter (Gemini) → match_score 5. Sip/Settle OfficeX credits 6. NocoDB sync (fire-and-forget) 7. Inbox notification on completion
'''
Vendor Config
'''typescript
// infrastructure/lib/vendors.config.ts
{ id: "instagram", rateLimitMax: 20, rateLimitWindowSecs: 5 } // 4 req/sec safe margin
'''
Pricing
- Base: 1.01 credits/task (~$0.0101)
- With AI filter: 1.03 credits/task (~$0.0103)
- Billing: Reserve → Sip → Settle pattern (see '/officex-developer' skill)
Key Handlers
| File |
Purpose |
| 'src/handlers/ingress.ts' |
API Gateway entry: auth, webhooks, job submission, credit reserve |
| 'src/handlers/worker.ts' |
API call, S3 storage, preview, AI filter, billing, pagination |
| 'src/handlers/dispatcher.ts' |
Rate budget check, async worker invoke (same code, 2 deployments) |
| 'src/handlers/status.ts' |
Job listing, results, cancel, frontend, NocoDB webhook |
| 'src/handlers/auth.ts' |
Register, login, officex-login |
| 'src/handlers/frontend.ts' |
HTML frontend renderer |
Key Libraries
| File |
Purpose |
| 'src/lib/instagram-client.ts' |
Endpoint map, param validation, 'callInstagramApi()', 'RateLimitError' |
| 'src/lib/dynamo.ts' |
CRUD for Jobs, TaskResults, Users, RateBudget, ResultRows tables |
| 'src/lib/s3.ts' |
'writeResult()', 'writeResultItems()' → public S3 URLs |
| 'src/lib/officex-billing.ts' |
'reserveCredits', 'sipCredits', 'settleCredits', 'cancelReservation', 'sendInboxMessage' |
| 'src/lib/gemini-filter.ts' |
AI scoring: Gemini 2.5 Flash Lite → '{ match_score: 0-100, ai_notes }' |
| 'src/lib/preview-extractor.ts' |
Endpoint-specific flat preview extraction for DynamoDB |
| 'src/lib/nocodb.ts' |
'onInstall', 'onJobCreated', 'onTaskCompleted', 'onJobCompleted' |
| 'src/lib/rate-budget.ts' |
Sliding window rate limit tracker |
| 'src/lib/progressive-delay.ts' |
Backoff schedule: 30s → 12h over 10+ retries |
DynamoDB Tables
| Table |
Key |
TTL |
| 'rapi-ig-{stage}-jobs' |
PK: 'job_id' |
90d |
| 'rapi-ig-{stage}-task-results' |
PK: 'job_id', SK: 'task_index' |
90d |
| 'rapi-ig-{stage}-result-rows' |
PK: 'job_id', SK: '{task_index}#{item_index}' |
90d |
| 'rapi-ig-{stage}-rate-budget' |
PK: 'vendor_id' |
none |
| 'rapi-ig-{stage}-users' |
PK: 'install_id' |
none |
S3
Bucket: 'rapi-ig-{stage}-results-{account}' — public read, 90-day lifecycle, CORS enabled.
Objects: '{job_id}/{task_index}.json' (full response), '{job_id}/{task_index}/{item_index}.json' (individual items).
NocoDB Results Tables
| Table |
Endpoints |
| Results — Profiles |
profile |
| Results — Posts |
posts, info, search |
| Results — Users |
users-search, followers, following, likes, hashtags-search |
| Results — Comments |
comments |
Preview Extractor Fields (by endpoint)
- profile: username, full_name, is_verified, is_private, is_business, biography, followers, following, posts, category, external_url
- posts/info: shortcode, media_type, product_type, caption, like_count, comment_count, play_count, permalink, taken_at
- followers/following: result_count, username, full_name, is_verified, is_private
- comments: result_count, text, username
- likes: result_count, username, full_name, is_verified
- highlights: result_count, title, media_count
- users-search: result_count, username, full_name, is_verified, is_private
- hashtags-search: result_count, name, media_count
Infrastructure (CDK)
'''
infrastructure/bin/app.ts — CDK app entry
infrastructure/lib/rapi-stack.ts — Main stack (all resources)
infrastructure/lib/app.config.ts — PROJECT_TAG = "rapidapi-proxy"
infrastructure/lib/vendors.config.ts — Single vendor: instagram
'''
Deploy
'''bash
Production (default — always use production)
npm run deploy:prod
Register OfficeX app (production)
STAGE=production API_URL=https://instagram-lead-gen-production.cloud.zoomgtm.com npm run register:prod
Staging (for development only)
npm run deploy:staging
npm run register:staging
'''
Resources Created
4 Lambdas (ingress 256MB/30s, worker 512MB/60s, status 256MB/30s, 2× dispatcher 128MB/30s), 4 SQS FIFO queues + 4 DLQs, 5 DynamoDB tables, 1 S3 bucket, 1 CloudFront distribution, 1 HTTP API Gateway.
All tagged: 'app=rapi-ig-{stage}', 'project=rapidapi-proxy', 'vendor=instagram'.
Environment Variables
'''env
Required
RAPID_API_KEY= # RapidAPI key for instagram-social
GEMINI_API_KEY= # Gemini AI filter
AWS_ACCESS_KEY_ID= # AWS auth (use .env, not aws cli)
AWS_SECRET_ACCESS_KEY=
AWS_REGION=
OfficeX
OFFICEX_USER_ID= # For app registration
OFFICEX_API_KEY= # For app registration
NocoDB (optional — graceful degradation if missing)
NOCODBHOST_URL=
NOCODB_TOKEN=
NOCODB_BASE=
NOCODB_TABLE_INSTALLS=
NOCODB_TABLE_JOBS=
NOCODB_TABLE_RESULTS_PROFILES=
NOCODB_TABLE_RESULTS_POSTS=
NOCODB_TABLE_RESULTS_USERS=
NOCODB_TABLE_RESULTS_COMMENTS=
NOCODB_FIELD*= # Link field IDs for views/filters
NOCODB_WEBHOOK_SECRET=
'''
Auto-Pagination
Paginated endpoints (followers, following, posts, comments, likes) auto-follow cursors. User sets 'max_records' (default 100, max 1000). Worker queues follow-up tasks with incremented 'task_index' via atomic 'incrementTotalTasks()'. Credits reserved upfront for estimated total; final settle refunds unused.
Job Lifecycle
'queued → processing → completed | failed | cancelled'
Also supports: 'processing → paused → processing (resume)'. Dispatcher and worker check status; paused tasks requeue with 60s delay.
Error Handling
- Rate limit (429): Progressive backoff requeue (30s → 12h), new dedup ID per retry
- Real errors: SQS natural retry (3 attempts), then DLQ (14-day retention)
- Billing errors during sip/settle: Logged, not fatal — result already saved
- NocoDB errors: Fire-and-forget, logged silently — AWS is source of truth
1---2name: instagram-lead-gen3description: Instagram data access via RapidAPI (instagram-social API). Use when querying Instagram for user profiles, followers, following lists, user posts, story highlights, post/reel/story details, comments, likes, searching users, hashtags, or general content. Also use when building, deploying, debugging, or extending this OfficeX app — understanding its REST API, AWS serverless architecture, OfficeX billing integration, NocoDB visual layer, or CDK infrastructure. Triggers on: instagram api, instagram search, instagram profile, instagram followers, instagram posts, instagram comments, instagram likes, instagram hashtags, instagram highlights, rapidapi instagram, instagram lead gen, instagram proxy, instagram worker, instagram dispatcher.4---56# Instagram RapidAPI Proxy — OfficeX App78**Production is live and should always be used.**910| Environment | Base URL | OfficeX API |11| ----------- | ------------------------------------------------- | ------------------------------------ |12| Production | https://instagram-lead-gen-production.cloud.zoomgtm.com | https://cloud.officex.app/v1 |13| Staging | https://instagram-lead-gen-staging.cloud.zoomgtm.com | https://staging-backend.cloud.officex.app/v1 |1415App ID (Production): 'b472aaf3-9b17-4d8c-b818-a6f8e2152eb5'1617Single-vendor RapidAPI proxy wrapping 'instagram-social.p.rapidapi.com' as an OfficeX app. Serverless, AWS-native, scale-to-zero. See [TEMPLATE_ARCHITECTURE.md](TEMPLATE_ARCHITECTURE.md) for the full generic template this project implements.1819## Instagram API Reference2021See [.claude/skills/rapidapi-instagram/references/api_reference.md](.claude/skills/rapidapi-instagram/references/api_reference.md) for full endpoint docs with parameters and response schemas.2223### Quick Reference2425| Endpoint | Path | Required Param | Paginated |26| ----------------- | ------------------ | ------------------ | --------- |27| 'search' | '/search' | 'search' | no |28| 'users-search' | '/users/search' | 'search' | no |29| 'hashtags-search' | '/hashtags/search' | 'search' | no |30| 'profile' | '/profile' | 'username' | no |31| 'followers' | '/followers' | 'username' | yes |32| 'following' | '/following' | 'username' | yes |33| 'posts' | '/posts' | 'username' | yes |34| 'highlights' | '/highlights' | 'username' | no |35| 'info' | '/info' | 'code' (shortcode) | no |36| 'comments' | '/comments' | 'code' (shortcode) | yes |37| 'likes' | '/likes' | 'code' (shortcode) | yes |3839### Authentication4041'''42Headers:43X-RapidAPI-Key: {RAPID_API_KEY from .env}44X-RapidAPI-Host: instagram-social.p.rapidapi.com4546Base URL: https://instagram-social.p.rapidapi.com/api/v1/instagram47Method: GET (all endpoints)48'''4950### Response Format5152'''json53{54"meta": { "version": "v1.0", "status": 200, "pagination_token": "..." | null },55"body": [ ... ] // array for list endpoints, object for /profile, /info56}57'''5859Pagination: pass 'pagination_token' as query param for next page. 'null' = no more pages.6061### Direct Usage6263'''javascript64import 'dotenv/config';65const BASE = 'https://instagram-social.p.rapidapi.com/api/v1/instagram';66const headers = {67'x-rapidapi-key': process.env.RAPID_API_KEY,68'x-rapidapi-host': 'instagram-social.p.rapidapi.com'69};70const res = await fetch('{BASE}/profile?username=mrbeast', { headers });71const data = await res.json(); // data.meta, data.body72'''7374## REST API (This App's Endpoints)7576Auth for all job/status endpoints: 'x-officex-install-id' + 'x-officex-install-secret' headers.7778### Submit Job7980'''81POST /api/v1/jobs8283// Single (quick queue):84{ "endpoint": "profile", "params": { "username": "mrbeast" }, "prompt_filter": "optional AI filter" }8586// Batch (bulk queue):87{ "endpoint": "posts", "params": [{ "username": "a" }, { "username": "b" }], "max_records": 100 }8889// Response (202):90{ "job_id": "...", "status": "queued", "total_tasks": 1, "credits_reserved": 1.01, "poll_url": "/api/v1/jobs/..." }91'''9293### Poll & Results9495'''96GET /api/v1/jobs/{job_id} — Job progress + cost breakdown97GET /api/v1/jobs/{job_id}/results — Paginated results (preview + match_score + S3 URLs)98GET /api/v1/jobs — List user's jobs99PATCH /api/v1/jobs/{job_id} — Cancel: { "status": "cancelled" }100'''101102### Result Items & Bookmarks103104'''105GET /api/v1/jobs/{job_id}/results/{task_index}/items/{item_index}106PATCH /api/v1/jobs/{job_id}/results/{task_index}/items/{item_index} — { "user_bookmarked": true, "user_notes": "..." }107GET /api/v1/jobs/{job_id}/result-rows — All bookmarks/notes for a job108'''109110### Auth & Webhooks111112'''113POST /auth/register — { email, password } → { api_key, install_id }114POST /auth/login — { email, password } → { api_key, install_id }115POST /auth/officex-login — { officex_customer_id, install_id, install_secret } → { api_key }116POST /webhooks/officex — INSTALL / UNINSTALL / RATE_LIMIT_CHANGE events117POST /api/v1/webhooks/nocodb — NocoDB 2-way sync (bookmark/notes)118GET / — Frontend HTML119GET /docs — API documentation120'''121122## Architecture123124'''125POST /api/v1/jobs → Ingress Lambda (validate + reserve credits + queue)126↓127┌──────────┴──────────┐128Quick Queue (80%) Bulk Queue (20%)129↓ ↓130Quick Dispatcher Bulk Dispatcher131└──────────┬──────────┘132Worker Lambda 1. Call Instagram API 2. Save to S3 (public URL, 90d) 3. Extract preview → DynamoDB 4. AI filter (Gemini) → match_score 5. Sip/Settle OfficeX credits 6. NocoDB sync (fire-and-forget) 7. Inbox notification on completion133'''134135### Vendor Config136137'''typescript138// infrastructure/lib/vendors.config.ts139{ id: "instagram", rateLimitMax: 20, rateLimitWindowSecs: 5 } // 4 req/sec safe margin140'''141142### Pricing143144- Base: **1.01 credits/task** (~$0.0101)145- With AI filter: **1.03 credits/task** (~$0.0103)146- Billing: Reserve → Sip → Settle pattern (see '/officex-developer' skill)147148### Key Handlers149150| File | Purpose |151| ---------------------------- | ----------------------------------------------------------------- |152| 'src/handlers/ingress.ts' | API Gateway entry: auth, webhooks, job submission, credit reserve |153| 'src/handlers/worker.ts' | API call, S3 storage, preview, AI filter, billing, pagination |154| 'src/handlers/dispatcher.ts' | Rate budget check, async worker invoke (same code, 2 deployments) |155| 'src/handlers/status.ts' | Job listing, results, cancel, frontend, NocoDB webhook |156| 'src/handlers/auth.ts' | Register, login, officex-login |157| 'src/handlers/frontend.ts' | HTML frontend renderer |158159### Key Libraries160161| File | Purpose |162| ------------------------------ | ---------------------------------------------------------------------------------------- |163| 'src/lib/instagram-client.ts' | Endpoint map, param validation, 'callInstagramApi()', 'RateLimitError' |164| 'src/lib/dynamo.ts' | CRUD for Jobs, TaskResults, Users, RateBudget, ResultRows tables |165| 'src/lib/s3.ts' | 'writeResult()', 'writeResultItems()' → public S3 URLs |166| 'src/lib/officex-billing.ts' | 'reserveCredits', 'sipCredits', 'settleCredits', 'cancelReservation', 'sendInboxMessage' |167| 'src/lib/gemini-filter.ts' | AI scoring: Gemini 2.5 Flash Lite → '{ match_score: 0-100, ai_notes }' |168| 'src/lib/preview-extractor.ts' | Endpoint-specific flat preview extraction for DynamoDB |169| 'src/lib/nocodb.ts' | 'onInstall', 'onJobCreated', 'onTaskCompleted', 'onJobCompleted' |170| 'src/lib/rate-budget.ts' | Sliding window rate limit tracker |171| 'src/lib/progressive-delay.ts' | Backoff schedule: 30s → 12h over 10+ retries |172173### DynamoDB Tables174175| Table | Key | TTL |176| ------------------------------ | --------------------------------------------- | ---- |177| 'rapi-ig-{stage}-jobs' | PK: 'job_id' | 90d |178| 'rapi-ig-{stage}-task-results' | PK: 'job_id', SK: 'task_index' | 90d |179| 'rapi-ig-{stage}-result-rows' | PK: 'job_id', SK: '{task_index}#{item_index}' | 90d |180| 'rapi-ig-{stage}-rate-budget' | PK: 'vendor_id' | none |181| 'rapi-ig-{stage}-users' | PK: 'install_id' | none |182183### S3184185Bucket: 'rapi-ig-{stage}-results-{account}' — public read, 90-day lifecycle, CORS enabled.186Objects: '{job_id}/{task_index}.json' (full response), '{job_id}/{task_index}/{item_index}.json' (individual items).187188### NocoDB Results Tables189190| Table | Endpoints |191| ------------------ | ---------------------------------------------------------- |192| Results — Profiles | profile |193| Results — Posts | posts, info, search |194| Results — Users | users-search, followers, following, likes, hashtags-search |195| Results — Comments | comments |196197### Preview Extractor Fields (by endpoint)198199- **profile**: username, full_name, is_verified, is_private, is_business, biography, followers, following, posts, category, external_url200- **posts/info**: shortcode, media_type, product_type, caption, like_count, comment_count, play_count, permalink, taken_at201- **followers/following**: result_count, username, full_name, is_verified, is_private202- **comments**: result_count, text, username203- **likes**: result_count, username, full_name, is_verified204- **highlights**: result_count, title, media_count205- **users-search**: result_count, username, full_name, is_verified, is_private206- **hashtags-search**: result_count, name, media_count207208## Infrastructure (CDK)209210'''211infrastructure/bin/app.ts — CDK app entry212infrastructure/lib/rapi-stack.ts — Main stack (all resources)213infrastructure/lib/app.config.ts — PROJECT_TAG = "rapidapi-proxy"214infrastructure/lib/vendors.config.ts — Single vendor: instagram215'''216217### Deploy218219'''bash220221# Production (default — always use production)222223npm run deploy:prod224225# Register OfficeX app (production)226227STAGE=production API_URL=https://instagram-lead-gen-production.cloud.zoomgtm.com npm run register:prod228229# Staging (for development only)230231npm run deploy:staging232npm run register:staging233'''234235### Resources Created2362374 Lambdas (ingress 256MB/30s, worker 512MB/60s, status 256MB/30s, 2× dispatcher 128MB/30s), 4 SQS FIFO queues + 4 DLQs, 5 DynamoDB tables, 1 S3 bucket, 1 CloudFront distribution, 1 HTTP API Gateway.238239All tagged: 'app=rapi-ig-{stage}', 'project=rapidapi-proxy', 'vendor=instagram'.240241## Environment Variables242243'''env244245# Required246247RAPID_API_KEY= # RapidAPI key for instagram-social248GEMINI_API_KEY= # Gemini AI filter249AWS_ACCESS_KEY_ID= # AWS auth (use .env, not aws cli)250AWS_SECRET_ACCESS_KEY=251AWS_REGION=252253# OfficeX254255OFFICEX_USER_ID= # For app registration256OFFICEX_API_KEY= # For app registration257258# NocoDB (optional — graceful degradation if missing)259260NOCODB*HOST_URL=261NOCODB_TOKEN=262NOCODB_BASE=263NOCODB_TABLE_INSTALLS=264NOCODB_TABLE_JOBS=265NOCODB_TABLE_RESULTS_PROFILES=266NOCODB_TABLE_RESULTS_POSTS=267NOCODB_TABLE_RESULTS_USERS=268NOCODB_TABLE_RESULTS_COMMENTS=269NOCODB_FIELD*\*= # Link field IDs for views/filters270NOCODB_WEBHOOK_SECRET=271'''272273## Auto-Pagination274275Paginated endpoints (followers, following, posts, comments, likes) auto-follow cursors. User sets 'max_records' (default 100, max 1000). Worker queues follow-up tasks with incremented 'task_index' via atomic 'incrementTotalTasks()'. Credits reserved upfront for estimated total; final settle refunds unused.276277## Job Lifecycle278279'queued → processing → completed | failed | cancelled'280281Also supports: 'processing → paused → processing (resume)'. Dispatcher and worker check status; paused tasks requeue with 60s delay.282283## Error Handling284285- **Rate limit (429)**: Progressive backoff requeue (30s → 12h), new dedup ID per retry286- **Real errors**: SQS natural retry (3 attempts), then DLQ (14-day retention)287- **Billing errors during sip/settle**: Logged, not fatal — result already saved288- **NocoDB errors**: Fire-and-forget, logged silently — AWS is source of truth