{"openapi":"3.1.0","info":{"title":"Shager API","version":"1.0.0","description":"Distribute content to many social accounts and measure clicks per account. Built for AI agents: the same operations are MCP tools at /api/mcp. Errors are `{ error: { code, message } }`.","contact":{"url":"https://shager.ai/agents"}},"servers":[{"url":"https://app.shager.ai/api/v1"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"API key: shgr_live_…"}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}}}}}}}},"paths":{"/me":{"get":{"operationId":"whoami","summary":"Who am I","description":"The organization this key belongs to, whether it is still an unclaimed sandbox, and what the key may do.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/workspaces":{"get":{"operationId":"list_workspaces","summary":"List workspaces","description":"Workspaces are clients (or brands). Every channel, post and link lives in one.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"create_workspace","summary":"Create a workspace","description":"Create a workspace for a new client or brand.","security":[{"bearer":[]}],"x-scope":"write","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"timezone":{"description":"IANA zone, default Asia/Jerusalem","type":"string","maxLength":60},"approval_required":{"description":"Require client approval before scheduling (default false for agents).","type":"boolean"}},"required":["name"]}}}}}},"/workspaces/{workspace_id}/channels":{"get":{"operationId":"list_channels","summary":"List connected accounts","description":"Social accounts connected to a workspace, with network, status and supported formats.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}}]}},"/workspaces/{workspace_id}/connect-links":{"post":{"operationId":"create_connect_link","summary":"Create a client connect link","description":"A link to send the account owner (your client or your human). They open it, sign in to Facebook/Instagram or YouTube and pick their accounts — no Shager account needed. The accounts then appear in list_channels.\n\nNot available in an unclaimed sandbox.","security":[{"bearer":[]}],"x-scope":"write","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"description":"Who the link is for (shown to the agency only).","type":"string","maxLength":80}},"required":[]}}}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}}]}},"/workspaces/{workspace_id}/groups":{"get":{"operationId":"list_groups","summary":"List account groups","description":"Groups of channels (by client, region, campaign…). Target a group to post to all its accounts.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}}]},"post":{"operationId":"create_group","summary":"Create an account group","description":"Group channels so a post can target all of them at once.","security":[{"bearer":[]}],"x-scope":"write","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60},"channel_ids":{"default":[],"maxItems":1000,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}}},"required":["name"]}}}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}}]}},"/workspaces/{workspace_id}/media":{"post":{"operationId":"upload_media_from_url","summary":"Upload media from a URL","description":"Downloads a public image, video or PDF into the workspace. For Reels/Shorts/Stories validation pass width, height and duration_ms when you know them.","security":[{"bearer":[]}],"x-scope":"write","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri"},"file_name":{"type":"string","maxLength":200},"width":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"height":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"duration_ms":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["url"]}}}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}}]}},"/workspaces/{workspace_id}/posts":{"post":{"operationId":"create_post","summary":"Create a post","description":"Create a post for many accounts at once. Without schedule_at it is saved as a draft (preview it, send it for approval, or schedule it later). With schedule_at it is validated and scheduled; each account then publishes at its staggered time.","security":[{"bearer":[]}],"x-scope":"write","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"caption":{"type":"string","maxLength":70000,"description":"Post text. Shown on every channel unless overridden per channel."},"channel_ids":{"description":"Channels to publish to (from list_channels).","maxItems":1000,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"group_ids":{"description":"Account groups — every active channel in them is added.","maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"media_ids":{"description":"Media from upload_media_from_url, in order.","maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":64}},"first_comment":{"description":"Posted as the first comment right after publishing (carry the lead link here).","type":"string","maxLength":5000},"cta_url":{"description":"Link to track: each channel gets its own short link + UTM tags.","type":"string","maxLength":2000,"format":"uri"},"cta_text":{"type":"string","maxLength":120},"label":{"description":"Internal name for the post.","type":"string","maxLength":120},"campaign":{"description":"utm_campaign value.","type":"string","maxLength":120},"format":{"description":"Force a format where the network supports it; default is chosen per network.","type":"string","enum":["FEED","REEL","STORY","SHORT","VIDEO"]},"youtube_title":{"description":"YouTube video title (default: first line of the caption).","type":"string","maxLength":100},"youtube_privacy":{"type":"string","enum":["public","unlisted","private"]},"youtube_made_for_kids":{"description":"YouTube's made-for-kids declaration (COPPA). Default false; set true only if the video is made for children.","type":"boolean"},"per_channel":{"maxItems":1000,"type":"array","items":{"type":"object","properties":{"channel_id":{"type":"string","minLength":1,"maxLength":64},"caption":{"description":"Override the caption for this account (recommended: vary wording per account).","type":"string","maxLength":70000},"first_comment":{"type":"string","maxLength":5000},"format":{"type":"string","enum":["FEED","REEL","STORY","SHORT","VIDEO"]}},"required":["channel_id"]}},"stagger_seconds":{"description":"Random pause [min, max] seconds between accounts of the same network (default [30, 90]).","type":"array","prefixItems":[{"type":"integer","minimum":0,"maximum":3600},{"type":"integer","minimum":0,"maximum":3600}],"items":false,"minItems":2,"maxItems":2},"schedule_at":{"description":"ISO 8601 with offset, e.g. 2026-10-20T09:00:00+03:00","type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["caption"]}}}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}}]},"get":{"operationId":"list_posts","summary":"List posts","description":"Posts in a workspace, newest first, optionally filtered by status.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["DRAFT","IN_REVIEW","CHANGES_REQUESTED","APPROVED","SCHEDULED","PUBLISHING","PUBLISHED","PARTIALLY_PUBLISHED","FAILED","CANCELED"]}},{"name":"limit","in":"query","required":false,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}}]}},"/workspaces/{workspace_id}/posts/{post_id}/schedule":{"post":{"operationId":"schedule_post","summary":"Schedule a post","description":"Schedule an existing draft or approved post for a time. Fails with a clear reason if any account would reject it or client approval is missing.","security":[{"bearer":[]}],"x-scope":"publish","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"schedule_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}},"required":["schedule_at"]}}}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}},{"name":"post_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64}}]}},"/workspaces/{workspace_id}/posts/{post_id}/approval":{"post":{"operationId":"request_approval","summary":"Send a post for client approval","description":"Creates an approval link for the client reviewer (no login needed). Returns the link to send; optionally emails it.\n\nNot available in an unclaimed sandbox.","security":[{"bearer":[]}],"x-scope":"write","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reviewer_name":{"type":"string","minLength":1,"maxLength":80},"reviewer_email":{"type":"string","maxLength":200,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"reviewer_phone":{"type":"string","maxLength":30},"send_email":{"default":false,"type":"boolean"}},"required":["reviewer_name"]}}}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}},{"name":"post_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64}}]}},"/workspaces/{workspace_id}/posts/{post_id}":{"get":{"operationId":"get_post","summary":"Get a post","description":"Status of a post and of every account it goes to: state, publish time, live URL or error.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}},{"name":"post_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64}}]}},"/workspaces/{workspace_id}/posts/{post_id}/cancel":{"post":{"operationId":"cancel_post","summary":"Cancel a scheduled post","description":"Unschedules a post that has not started publishing (it stays as an approved draft).","security":[{"bearer":[]}],"x-scope":"write","responses":{"201":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}},{"name":"post_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64}}]}},"/workspaces/{workspace_id}/analytics":{"get":{"operationId":"get_analytics","summary":"Clicks and leads by account","description":"Clicks on Shager's tracked links per account and per post in a period — which page, branch or video brought traffic. Pair with utm_content in your analytics/CRM for leads.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"description":"Workspace (client) id from list_workspaces"}},{"name":"from","in":"query","required":false,"schema":{"description":"Date (2026-10-01) or ISO datetime. Default: 30 days ago","anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}]}},{"name":"to","in":"query","required":false,"schema":{"description":"Date (2026-10-31, inclusive) or ISO datetime. Default: now","anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"},{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"}]}}]}},"/holidays":{"get":{"operationId":"get_holidays","summary":"Holidays and posting guidance","description":"Holidays of every major tradition (Jewish/Israeli, Muslim, Christian, Orthodox, Druze, Bahá'í, Hindu, Buddhist, Sikh, Jain, Chinese, Persian, international and commercial days) with advice per day: avoid (no promotional posts to that audience), sensitive (respectful only), opportunity (greeting or themed post), normal. Check this before scheduling, and match the traditions to the audience of each account.","security":[{"bearer":[]}],"x-scope":"read","responses":{"200":{"description":"OK — the result is in `data`."},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}},"parameters":[{"name":"from","in":"query","required":false,"schema":{"description":"First day, YYYY-MM-DD (default: today)","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"schema":{"description":"Last day, YYYY-MM-DD (default: from + 60 days, max 400 days)","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"traditions","in":"query","required":false,"schema":{"description":"Limit to some traditions: jewish, muslim, christian, orthodox, druze, bahai, hindu, buddhist, sikh, jain, chinese, persian, international (array, or comma separated in a query string)","anyOf":[{"type":"array","items":{"type":"string","enum":["jewish","muslim","christian","orthodox","druze","bahai","hindu","buddhist","sikh","jain","chinese","persian","international"]}},{"type":"string"}]}},{"name":"language","in":"query","required":false,"schema":{"default":"en","type":"string","enum":["en","he"]}}]}},"/agent/signup":{"post":{"operationId":"agent_signup","summary":"Open a sandbox (no human needed)","description":"Creates an organization in sandbox mode and returns an API key plus a claim link for your human. In the sandbox you can create workspaces, upload media and draft posts. Publishing, account connections and approvals unlock after a human opens the claim link. Unclaimed sandboxes expire after 7 days.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agent_name"],"properties":{"agent_name":{"type":"string","maxLength":80,"description":"Who is signing up, e.g. 'Acme marketing agent (Claude)'"},"contact_email":{"type":"string","format":"email","description":"The human you work for — they get the claim link."},"organization_name":{"type":"string","maxLength":80},"purpose":{"type":"string","maxLength":500}}}}}},"responses":{"201":{"description":"Sandbox created: api_key (shown once), claim_url, mcp_url."},"429":{"$ref":"#/components/responses/Error"}}}}}}