{"version":1,"resources":["https://stableinfluencer.dev/api/campaigns/{id}/video-slots","https://stableinfluencer.dev/api/campaigns","https://stableinfluencer.dev/api/campaigns/{id}","https://stableinfluencer.dev/api/campaigns/{id}/account","PUT https://stableinfluencer.dev/api/campaigns/{id}/account","https://stableinfluencer.dev/api/campaigns/{id}/account/corrections","https://stableinfluencer.dev/api/campaigns/{id}/account/finalize","https://stableinfluencer.dev/api/campaigns/{id}/edit-slots","https://stableinfluencer.dev/api/campaigns/{id}/media/image-from-url","https://stableinfluencer.dev/api/campaigns/{id}/media/image-upload-url","https://stableinfluencer.dev/api/campaigns/{id}/media/video-upload-url","https://stableinfluencer.dev/api/campaigns/{id}/publish","https://stableinfluencer.dev/api/campaigns/{id}/unpublish","https://stableinfluencer.dev/api/campaigns/{id}/videos","PUT https://stableinfluencer.dev/api/campaigns/{id}/videos","https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}/corrections","https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}/finalize","https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}/fix-download","https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}/publish","https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}/reset","https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}","PUT https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}","PATCH https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}","https://stableinfluencer.dev/api/campaigns/{id}/videos/{position}/unschedule","https://stableinfluencer.dev/api/campaigns/{id}/videos/publish-all","https://stableinfluencer.dev/api/accounts","https://stableinfluencer.dev/api/accounts/{id}/analytics","https://stableinfluencer.dev/api/accounts/{id}/analytics/can-refresh","https://stableinfluencer.dev/api/accounts/{id}/analytics/videos","https://stableinfluencer.dev/api/accounts/{id}/bundles","https://stableinfluencer.dev/api/accounts/{id}/edit-request","https://stableinfluencer.dev/api/comments","https://stableinfluencer.dev/api/comments/{id}/approve","https://stableinfluencer.dev/api/comments/{id}/dispute","https://stableinfluencer.dev/api/comments/{id}","DELETE https://stableinfluencer.dev/api/comments/{id}","https://stableinfluencer.dev/api/comments/{id}/verifications"],"mppResources":["https://stableinfluencer.dev/api/campaigns/{id}/video-slots","https://stableinfluencer.dev/api/campaigns","https://stableinfluencer.dev/api/campaigns/{id}/edit-slots","https://stableinfluencer.dev/api/accounts/{id}/edit-request","https://stableinfluencer.dev/api/comments"],"description":"Agent-oriented social campaign API backed by TokPortal. Create localized TikTok/Instagram account campaigns, publish videos, and schedule outbound comments.","instructions":"# StableInfluencer API\n\n> Agent-oriented TokPortal lifecycle API for TikTok/Instagram account campaigns, video slots, delivered accounts, analytics, and outbound comments.\n\n## Base URL\n\nhttps://stableinfluencer.dev\n\n## Upstream TokPortal Docs\n\n- Agent/tool inventory: https://developers.tokportal.com/mcp\n- Overview and auth model: https://developers.tokportal.com/getting-started/overview\n- Bundles lifecycle: https://developers.tokportal.com/bundles/bundles\n- Account configuration/actions: https://developers.tokportal.com/account-config/account-configuration and https://developers.tokportal.com/account-config/account-actions\n- Video configuration/actions: https://developers.tokportal.com/videos/configure-videos\n- Media upload: https://developers.tokportal.com/media-upload/media-upload\n- Delivered accounts: https://developers.tokportal.com/accounts/saved-accounts\n- Analytics: https://developers.tokportal.com/analytics/analytics\n- Comments: https://developers.tokportal.com/comments/comments-overview\n\n## Model\n\nA StableInfluencer campaign maps to one TokPortal bundle. Use the original campaign bundle for account setup, review, video slots, and video configuration until the account is delivered. StableInfluencer only exposes accounts that are owned by the signing wallet; account details in responses come from TokPortal. Only create a new videos_only campaign with existing_account_id after the account appears in GET /api/accounts.\n\n## Happy Path\n\n1. GET /api/campaigns with SIWX before creating anything; reuse existing wallet-owned work when possible.\n2. POST /api/campaigns (paid) to create a campaign. Include account/videos when already known. Prefer publish_mode=\"draft\".\n3. GET /api/campaigns/{id}?refresh=true to inspect TokPortal status, next_action, account, videos, and delivery state.\n4. Follow the state-to-action table below.\n\n## State To Action\n\n- next_action=configure_account: PUT /api/campaigns/{id}/account with { username, display_name, biography, profile_picture_url, link_in_bio? }.\n- next_action=configure_videos: PUT /api/campaigns/{id}/videos with { videos: [{ position, type, description, target_publish_date, video_url? or carousel_images? }], auto_publish? }.\n- next_action=publish_bundle: POST /api/campaigns/{id}/publish.\n- account status in_review and user approves: POST /api/campaigns/{id}/account/finalize. This is the dashboard \"Validate Account\" action.\n- account status in_review and user rejects: POST /api/campaigns/{id}/account/corrections with { comment, fields }.\n- account status finalized but not delivered: TokPortal controls the handoff. Poll GET /api/campaigns/{id}?refresh=true. If the user wants videos on this same account now, POST /api/campaigns/{id}/video-slots (paid) on the original bundle, then configure those slots.\n- account delivered / visible in GET /api/accounts: first GET /api/accounts/{id}/bundles. If an active non-completed video bundle exists, use its stableinfluencer_campaign.id with POST /api/campaigns/{id}/video-slots. Create a new videos_only campaign with existing_account_id only when there is no active video bundle and you are buying at least 5 video slots.\n- video status in_review and user approves: POST /api/campaigns/{id}/videos/{position}/finalize.\n- video status in_review and user rejects: POST /api/campaigns/{id}/videos/{position}/corrections with { message }.\n- scheduled/published video must be pulled back: POST /api/campaigns/{id}/videos/{position}/unschedule.\n- bad media download: POST /api/campaigns/{id}/videos/{position}/fix-download with replacement video_url or carousel_images.\n\n## Key Endpoints\n\n- Campaigns: GET/POST /api/campaigns, GET /api/campaigns/{id}, POST /api/campaigns/{id}/publish, POST /api/campaigns/{id}/unpublish.\n- Account config/review: GET/PUT /api/campaigns/{id}/account, POST /api/campaigns/{id}/account/finalize, POST /api/campaigns/{id}/account/corrections.\n- Slots: POST /api/campaigns/{id}/video-slots (paid, { quantity }), POST /api/campaigns/{id}/edit-slots (paid, { quantity }).\n- Media: POST /api/campaigns/{id}/media/video-upload-url returns upload data; use public_url as video_url. POST /api/campaigns/{id}/media/image-upload-url or image-from-url returns storage data; use storage_path for profile_picture_url or carousel_images.\n- Videos: GET/PUT /api/campaigns/{id}/videos; GET/PUT/PATCH /api/campaigns/{id}/videos/{position}; POST /publish, /finalize, /corrections, /unschedule, /reset, /fix-download under that video path; POST /api/campaigns/{id}/videos/publish-all.\n- Delivered accounts: GET /api/accounts returns wallet-owned delivered accounts with current TokPortal account details; use tokportalAccountId from that response for comments, analytics, bundles, edit requests, and eligible videos_only campaigns. For delivered-account paths, {id} is tokportalAccountId. GET /api/accounts/{id}/bundles includes stableinfluencer_campaign when the TokPortal bundle maps to a local campaign. Other endpoints: GET/POST /api/accounts/{id}/edit-request; GET/POST /api/accounts/{id}/analytics; GET /api/accounts/{id}/analytics/can-refresh; GET /api/accounts/{id}/analytics/videos.\n- Comments: POST /api/comments (paid); GET /api/comments; GET/DELETE /api/comments/{id}; POST /api/comments/{id}/approve; POST /api/comments/{id}/dispute; GET /api/comments/{id}/verifications.\n- Metadata/pricing: GET /api/countries, GET /api/platforms, GET /api/pricing.\n\n## Request Notes\n\n- POST /api/campaigns body: { platform: \"tiktok\"|\"instagram\", country, existing_account_id?, publish_mode: \"draft\"|\"publish\", title?, account?, videos?, video_slots?, options?, external_ref? }.\n- If existing_account_id is absent, country is required and TokPortal creates a new account. If existing_account_id is present, StableInfluencer creates a videos_only bundle for an already delivered account only when video_slots/videos count is at least 5 and no active video bundle already exists for that account.\n- Warming is optional. Use options.niche_warming with niche_warming_instructions only when the user asks for account warmup/niche conditioning. Use options.deep_warming only for Instagram. Do not set both.\n- Use target_publish_date at least 3 days ahead for new accounts and at least 1 day ahead for existing delivered accounts.\n- For TikTok carousel posts, include tiktok_sound_url. For Instagram, set instagram_content_type to reel or post.\n- Comments require saved_account_id, target_video_url, comment_text. Use tokportalAccountId from GET /api/accounts as saved_account_id.\n- Avoid duplicate paid campaigns, duplicate paid slots, and duplicate comments when wallet-owned usable work already exists.\n- Do not retrieve delivered account credentials or verification codes unless a product-approved endpoint exists. Logging into accounts outside TokPortal can harm reach and support eligibility.\n"}