# API reference Use accounts, capabilities, media, posts, webhooks, scopes, and usage through the REST API. Source: https://opensocial.run/docs/api Markdown: https://opensocial.run/docs/api.md Use the same service address as the dashboard, with the `/v1` path. Requests and responses use JSON, except for media byte uploads. For account and API key setup, see [Getting started](https://opensocial.run/docs/getting-started). ## Authentication and requests [#authentication-and-requests] Send your full API key in each authenticated request: ```http Authorization: Bearer sk_YOUR_API_KEY Content-Type: application/json ``` Keys belong to an organisation. Do not expose them in public browser code. Create an account through Better Auth at `/login`, verify your email, and sign in. Create the first API key at `/dashboard/keys`. Programmatic key creation uses `POST /v1/session/keys` with the verified session cookie and application `Origin` header. Keys are shown only once. `GET /v1/health` and `GET /v1/openapi` are public. The public email-only sign-up route is removed. Use the returned IDs, such as `acct_…`, `post_…`, `pub_…`, and `med_…`. Use RFC 3339 timestamps for `publish_at`. Responses use UTC timestamps. Each response includes `X-Request-Id`. Include it in a support request. For authenticated requests that change data, send an `Idempotency-Key` of 8–255 characters. Reuse that key only for the same request. A repeated request returns the stored response with `Idempotency-Replayed: true`. A different request with the same key returns `409 idempotency_key_reused`. List responses contain `data` and `has_more`. The current API does not provide cursor pagination. `GET /v1/posts` accepts `limit`. `GET /v1/events` accepts `limit`, `type`, and `after`, where `after` is a timestamp. ## Errors [#errors] An unsuccessful request returns an `error` object: ```json { "error": { "type": "validation_error", "code": "publications_required", "message": "At least one publication target is required.", "param": "publications", "retryable": false, "request_id": "req_EXAMPLE" } } ``` Additional fields can include `platform`, `docs_url`, and `details`. Check `code` and `retryable` to decide the next action. Correct validation errors before you retry. For a failed publication, read its `error` field. | HTTP status | Meaning | | ----------- | --------------------------------------- | | 400 | Invalid request or media. | | 401 | Missing or invalid API key. | | 403 | Missing permission. | | 404 | Resource not found. | | 409 | State conflict or idempotency conflict. | | 429 | Rate limit reached. | | 500 | Service error. | | 502 | Platform error. | ## Capabilities [#capabilities] ```http GET /v1/capabilities GET /v1/capabilities?platform=bluesky ``` Read capabilities before you prepare a post. The response includes text and media limits, `requires_media`, `implemented`, `auth_kind`, and `connect_fields`. A platform can appear in the catalog without publication support. Check `implemented` before you select it. ## Accounts [#accounts] ```http GET /v1/accounts GET /v1/accounts/{id} POST /v1/accounts/{platform}/connect GET /v1/accounts/{id}/publishing-options DELETE /v1/accounts/{id} ``` For an OAuth platform, send a connect request and open the returned `authorization_url`. The user must complete sign-in and consent. Then read the account list to get the connected account ID. For Bluesky, send credentials in `values`: ```json { "values": { "handle": "you.bsky.social", "password": "YOUR_APP_PASSWORD" } } ``` Account responses include `id`, `platform`, `handle`, `display_name`, `status`, `scopes`, and `connected_at`. Reconnect accounts with status `needs_reconnect`. For TikTok, read publishing options before each post. See the [platform guide](https://opensocial.run/docs/video-platforms#set-publication-options). ## Media [#media] ```http POST /v1/media GET /v1/media GET /v1/media/{id} POST /v1/media/{id}/complete ``` 1. Initiate the upload with filename, MIME type, and size. 2. Send the file bytes to the returned `upload_url` with its method and headers. For a URL on the same service, also send your API key. Do not send the key to an external upload host. 3. Call the complete endpoint after the byte upload succeeds. 4. Use the returned media ID in the post's `media` array. ```json { "filename": "clip.mp4", "content_type": "video/mp4", "size_bytes": 184320, "duration_ms": 12000, "width": 1080, "height": 1920, "alt_text": "A short product demonstration" } ``` `duration_ms`, `width`, `height`, and `alt_text` are optional metadata. TikTok videos require `duration_ms`. Complete the upload before you create a post. The service accepts files up to 2 GiB; each platform can have a lower limit. ## Posts and publications [#posts-and-publications] ```http POST /v1/posts/validate POST /v1/posts GET /v1/posts GET /v1/posts/{id} POST /v1/posts/{id}/publish POST /v1/posts/{id}/schedule POST /v1/posts/{id}/cancel DELETE /v1/posts/{id} ``` Validate the intended request body before you create or publish the post. Validation does not create a post. It returns `valid` and a `results` array with errors and warnings for each target account. ```json { "content": { "text": "Hello from Open Social" }, "media": [], "publications": [ { "account_id": "acct_YOUR_ACCOUNT" } ] } ``` Send this body to `POST /v1/posts` to create a draft. The response includes the post ID and a `publications` array. Each publication has its own ID, account, platform, status, publication time, external post ID, external URL, and error. Use `platform_options` on each target for platform-specific fields. Add `publish_at` to the create body to schedule the post. To schedule an existing draft, send this body to `POST /v1/posts/{id}/schedule`: ```json { "publish_at": "2026-10-12T09:00:00Z" } ``` Send `POST /v1/posts/{id}/publish` to publish now. Its `202` response means the request was accepted. Check each publication status before you report success. Publish and schedule requests can include `publications`, an array of publication IDs, to select a subset. Without that field, they select all eligible publications. Cancel requests cancel targets in `draft`, `scheduled`, or `failed` states. Published targets stay on their platforms. If a target is publishing, wait for it to finish before you cancel the post. If a target is publishing or there are no targets to cancel, the API returns `400` with code `post_not_cancellable`. Post statuses include `draft`, `scheduled`, `publishing`, `published`, `partially_published`, `failed`, and `cancelled`. A `partially_published` post has different results across its publications. Read each result before you retry an unsuccessful target. ## Webhooks and events [#webhooks-and-events] ```http POST /v1/webhooks GET /v1/webhooks PATCH /v1/webhooks/{id} DELETE /v1/webhooks/{id} GET /v1/webhooks/{id}/deliveries GET /v1/events ``` Register an HTTPS endpoint for publication updates: ```json { "url": "https://your-app.example.com/hook", "event_types": ["post.published", "post.failed"], "description": "Publication updates" } ``` The create response includes a signing secret. Store it when it is shown; it is shown only once. An empty `event_types` array selects all events. `GET /v1/webhooks` returns the available event types in `available_events`. Event types include `account.connected`, `account.disconnected`, `post.created`, `post.scheduled`, `post.publishing`, `post.published`, `post.partially_published`, `post.failed`, `post.cancelled`, `media.ready`, and `media.failed`. Each event contains `id`, `type`, `created_at`, and `data`. Verify the `OpenSocial-Signature` header before you accept a delivery: ```text OpenSocial-Signature: t=,v1= ``` Compute HMAC-SHA256 with the signing secret and the exact string `.`. Use a constant-time comparison and reject signatures more than five minutes from the current time. Return a `2xx` status for an accepted delivery. Unsuccessful deliveries are retried. Use the `deliveries` endpoint to inspect attempts. ## Scopes, usage, and limits [#scopes-usage-and-limits] ```http GET /v1/me GET /v1/scopes GET /v1/keys POST /v1/keys DELETE /v1/keys/{id} GET /v1/usage?from=YYYY-MM-DD&to=YYYY-MM-DD GET /v1/organization PATCH /v1/organization ``` An empty key scope list gives full access. A restricted key must have the scope required for each operation. Missing scopes return `403 insufficient_scope`. `GET /v1/scopes` returns the scope catalog and the current key's scopes. | Scope | Operations | | ---------------------------------- | -------------------------------------------------------------------------- | | `capabilities:read` | Read platform capabilities. | | `accounts:read` / `accounts:write` | Read accounts and publishing options / connect or disconnect accounts. | | `posts:read` / `posts:write` | Read posts / validate, create, publish, schedule, cancel, or delete posts. | | `media:read` / `media:write` | Read media / upload and complete media. | | `webhooks:read` / `webhooks:write` | Read endpoints and deliveries / create, update, or delete endpoints. | | `events:read` | Read events. | | `usage:read` | Read usage. | | `keys:read` / `keys:write` | Read keys / create or revoke keys. | | `org:read` / `org:write` | Read / update the organisation and its limits. | Usage includes daily counters and month-to-date totals for posts, publication attempts, successes, failures, blocked publications, media uploads, media bytes, and `cost_micros`. `DELETE /v1/keys/{id}` revokes a key and returns `204`. The key stops working for new requests at once, including requests from CLI and MCP clients that are already running. Revocation does not cancel a publication already queued or a request already accepted. A revoked key is removed from active key lists; its record is kept for history. Repeated revocation of a key in your organisation returns `204`. A missing key or another organisation's key returns `404`. Use a key with `keys:write` to revoke keys. A full access key can revoke itself. You can also select the **Revoke API key** row action in the dashboard, or run: ```sh bun run cli -- keys revoke key_example ``` Update limits with `monthly_publication_limit` and `monthly_cost_limit_micros` in `PATCH /v1/organization`. Limits default to unlimited. A reached limit causes a publication to fail with `publication_limit_exceeded` or `spend_limit_exceeded`. ## CLI, SDK, and MCP [#cli-sdk-and-mcp] Use the [getting started guide](https://opensocial.run/docs/getting-started#use-the-cli-or-api) for CLI and REST connection instructions, and the [agent workflow](https://opensocial.run/docs/getting-started#use-an-agent) for MCP tools. The SDK provides `OpenSocial({ apiKey, baseUrl })`. Use the service address without `/v1` as `baseUrl`. Its `accounts`, `capabilities`, `media`, `posts`, `webhooks`, and `events` methods use the same REST resources. # Instagram, TikTok, and YouTube Connect accounts, attach media, and select publication options for Instagram, TikTok, and YouTube. Source: https://opensocial.run/docs/video-platforms Markdown: https://opensocial.run/docs/video-platforms.md Use the dashboard, REST API, CLI, SDK, or MCP tools to publish to these platforms. Read [Getting started](https://opensocial.run/docs/getting-started) for account and client connection. ## Connect an account [#connect-an-account] Open [Accounts](https://opensocial.run/dashboard/accounts), select **Connect an account**, and choose a platform. Complete the platform sign-in and grant the requested permissions. For REST, send `POST /v1/accounts/{platform}/connect` and open the returned `authorization_url`. Instagram requires a professional Business or Creator account. For YouTube, select a Google account with a YouTube channel. Check that the connected account is the account you intend to publish to. If the dashboard shows **Setup required**, contact the service administrator. If platform sign-in fails, check that you selected the correct account and accepted the requested permissions. ## Attach media [#attach-media] The dashboard post dialog can upload images and video. It shows a video preview and the platform options. Read `GET /v1/capabilities?platform=PLATFORM` for the supported file types and size limits before you upload. REST clients call `POST /v1/media`, upload bytes to the returned `upload_url`, then call `POST /v1/media/{id}/complete`. Include `duration_ms` for TikTok videos. Optional metadata includes `width`, `height`, and `alt_text`. See the [API media instructions](https://opensocial.run/docs/api#media). The CLI can upload a video and supply its duration: ```sh bun run cli -- media upload clip.mp4 --duration-ms 12000 ``` | Platform | Supported attachments | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Instagram | One JPEG photo, a carousel of 2–10 JPEG photos, or one MP4/MOV Reel. Photos can be up to 8 MiB each. A Reel can be up to 1 GiB and 3 seconds to 15 minutes long. | | TikTok | One MP4, MOV, or WebM video. Read current creator options for the maximum duration. | | YouTube | One MP4, MOV, or WebM video. | The service file limit is 2 GiB. Platform and account limits can be lower. Instagram video carousels and Stories are not supported. TikTok photo posts, inbox uploads, and commercial content are not supported. ## Set publication options [#set-publication-options] Set `platform_options` on each publication target. The same object is accepted by `POST /v1/posts` and `POST /v1/posts/validate`. ### YouTube [#youtube] ```json { "content": { "text": "A short product tour" }, "media": ["med_YOUR_VIDEO"], "publications": [ { "account_id": "acct_YOUR_YOUTUBE_CHANNEL", "platform_options": { "title": "Product tour", "privacy_status": "private", "made_for_kids": false } } ] } ``` YouTube requires a title of 1–100 characters without `<` or `>`. `privacy_status` can be `private` (the default), `unlisted`, or `public`. `made_for_kids` is optional. The post text becomes the video description. ### TikTok [#tiktok] Before each TikTok post, read `GET /v1/accounts/{id}/publishing-options` or call `social_account_publishing_options`. The result contains the creator identity, `privacy_level_options`, interaction settings, and `max_video_post_duration_sec`. Show these choices to the creator. Ask the creator to select a privacy level. Do not select a default privacy level for the creator. ```json { "privacy_level": "SELF_ONLY", "consent": true, "disable_comment": true, "disable_duet": true, "disable_stitch": true } ``` Use this example only if `SELF_ONLY` is available and the creator selects it. Set `consent: true` only after the creator agrees to send this video with the selected settings. This integration supports videos that do not promote a brand or business. Interaction controls default to disabled. The creator's disabled settings take priority. An unavailable privacy choice is rejected; ask the creator to choose again. ### CLI, SDK, and MCP [#cli-sdk-and-mcp] ```sh bun run cli -- accounts publishing-options acct_TIKTOK bun run cli -- posts validate --text "A short clip" --account acct_TIKTOK --media med_VIDEO --option tiktok.privacy_level=SELF_ONLY --option tiktok.consent=true bun run cli -- posts create --text "Video description" --account acct_YOUTUBE --media med_VIDEO --option youtube.title="My video" --option youtube.privacy_status=private ``` The SDK provides `accounts.publishingOptions(id)` and `media.upload({ durationMs, ... })`. The MCP upload tool accepts `duration_ms`. MCP post creation and validation accept `platform_options`. ## Check publication results [#check-publication-results] Publishing can take time while a platform processes the video. Read the post and each publication status, or use webhooks for updates. A pending publication is not a successful publication. Reconnect an account with status `needs_reconnect`. For other failures, read the publication error and correct the reported problem before you retry. If Instagram returns `instagram_publish_needs_reconciliation`, check the Instagram account for the post before you retry. The post may already exist. A private TikTok post can have no public post URL. In that case, `external_post_id` contains the TikTok publish request ID. A YouTube success means the upload was accepted and has a video ID. YouTube can continue processing and apply visibility restrictions after the upload. # Getting started Connect an account, create an API key, and publish your first post. Source: https://opensocial.run/docs/getting-started Markdown: https://opensocial.run/docs/getting-started.md Use the dashboard for account connection and post management. Use an API key to connect the API, CLI, or an agent to your organisation. ## Using an AI agent? [#using-an-ai-agent] Help me integrate Open Social with my application or AI agent. Read these documents first: - Documentation index: https://opensocial.run/llms.txt - Getting started: https://opensocial.run/docs/getting-started.md - API reference: https://opensocial.run/docs/api.md - Platform requirements: https://opensocial.run/docs/video-platforms.md - All public documentation: https://opensocial.run/llms-full.txt For a self-hosted service, replace the origin in these URLs with the service address. Use the REST API at the service address with the /v1 path, the repository CLI, or the Open Social MCP tools. Ask which client and service address to use if they are not known. Follow the connection instructions in the getting started guide. Keep API keys in environment variables. Do not put keys in source code or logs. List connected accounts and read platform capabilities before you create a post. Use returned account and media IDs. Do not guess IDs, limits, or platform options. For TikTok, read current publishing options and ask the creator to select privacy and confirm consent for each video. Validate content for all target accounts. Correct errors before publication. Create a draft unless I request publication or a schedule. Use an RFC 3339 timestamp with an explicit time zone for a schedule. Confirm the time zone if it is not known. A publish request starts an asynchronous operation. Check each publication status before you report success. Report failures and partial success. Do not repeat a publish request without checking the current post status. ## Connect an account [#connect-an-account] 1. [Sign in or create an account](https://opensocial.run/login). 2. Open [Accounts](https://opensocial.run/dashboard/accounts) and select **Connect an account**. 3. Select a platform and complete its connection steps. For OAuth platforms, sign in with the platform and grant the requested permissions. 4. Confirm that the account status is **Connected**. For Bluesky, use your handle and an app password. For Instagram, TikTok, and YouTube, see the [platform guide](https://opensocial.run/docs/video-platforms). If a platform shows **Setup required**, contact the service administrator. If an account shows **Needs reconnect**, connect that account again. ## Create your first post [#create-your-first-post] 1. Open [Posts](https://opensocial.run/dashboard/posts) and create a post. 2. Select the connected accounts that must receive the post. 3. Enter text, attach media, and set the required platform options. 4. Validate the post and correct each reported error. 5. Save a draft, publish now, or select a date and time to schedule the post. A publish request starts the publication process. Check the status of each publication before you report that the post was published. A post can succeed on one platform and fail on another. ## Create an API key [#create-an-api-key] Open [API keys](https://opensocial.run/dashboard/keys) and create a key. Copy the full key when it is shown. The key is shown only once. The prefix in the key list cannot authenticate requests. Select the permissions your client needs. An empty scope list gives full access. For the agent workflow below, a restricted key needs `accounts:read`, `capabilities:read`, `posts:read`, and `posts:write`. Add `media:write` for uploads and `events:read` to read events. Select **How to use** on the API keys page for CLI, MCP, and REST connection instructions. Keep the key private. If a key is exposed or no longer needed, select its **Revoke API key** row action and confirm. The key stops working for CLI, REST, and MCP requests. You can also run `bun run cli -- keys revoke key_example` with a full access key or a key that has `keys:write`. Replace `key_example` with the key ID from `bun run cli -- keys list`. Revocation cannot be undone. ## Use an agent [#use-an-agent] Add Open Social to your MCP client with the instructions in **How to use**. Ask the agent to list your connected accounts to check its connection. For a client that supports an MCP JSON configuration, use this template: ```json { "mcpServers": { "open-social": { "command": "bun", "args": ["--cwd", "/absolute/path/to/open-social", "run", "mcp"], "env": { "OPEN_SOCIAL_BASE_URL": "https://opensocial.run", "OPEN_SOCIAL_API_KEY": "YOUR_API_KEY" } } } } ``` Install Bun and the repository dependencies with `bun install` first. Replace the repository path and API key. For a local or self-hosted service, also replace the service address. This MCP server uses stdio. The client starts it as a local process. It does not use a remote MCP URL. Keep the configuration private. Use the client's secret storage if available. Use these tools in this order: | Step | MCP tool | Purpose | | ---- | ----------------------------------------------- | ------------------------------------------------------------- | | 1 | `social_accounts_list` | Get connected accounts and their IDs. | | 2 | `social_capabilities_get` | Read text limits, media limits, and platform requirements. | | 3 | `social_account_publishing_options` | Read current TikTok privacy choices and creator limits. | | 4 | `social_media_upload` | Upload an attachment and get its media ID, if needed. | | 5 | `social_post_validate` | Check text, attachments, and options for the target accounts. | | 6 | `social_post_create` | Create a draft, or set `publish_at` to schedule the post. | | 7 | `social_post_publish` or `social_post_schedule` | Publish a draft or set its publication time. | | 8 | `social_post_status` | Check the post and each publication result. | | 9 | `social_events_list` | Read recent events, if needed. | Pass account IDs from the account list. Use media IDs returned by the upload tool. Do not guess IDs or platform limits. For TikTok, ask the creator to choose the privacy level and confirm consent for each video. The create and validate tools apply the same `platform_options` to all target accounts. Use separate tool calls when accounts need different options. ## Use the CLI or API [#use-the-cli-or-api] The **How to use** dialog supplies the client connection instructions. After CLI setup, run these commands from the open-social repository directory: ```sh export OPEN_SOCIAL_BASE_URL="https://opensocial.run" export OPEN_SOCIAL_API_KEY="YOUR_API_KEY" bun run cli -- accounts list bun run cli -- capabilities bluesky bun run cli -- posts validate --text "Hello from Open Social" --account acct_YOUR_ACCOUNT bun run cli -- posts create --text "Hello from Open Social" --account acct_YOUR_ACCOUNT bun run cli -- posts publish post_YOUR_POST bun run cli -- posts status post_YOUR_POST ``` Replace the account ID with an ID from the account list. Replace the post ID with the ID returned by the create command. Choose a platform that matches your account. Run `bun run cli -- --help` for available commands. For a local or self-hosted service, replace `https://opensocial.run` with your service address. Set the API key in your local environment. Do not commit it to the repository. For REST requests, send your API key in the `Authorization` header. Use the same service address as the dashboard, with the `/v1` path. See the [API reference](https://opensocial.run/docs/api) for request bodies and response fields. To check a REST connection, use the same environment variables: ```sh curl --fail-with-body "$OPEN_SOCIAL_BASE_URL/v1/accounts" \ -H "Authorization: Bearer $OPEN_SOCIAL_API_KEY" ``` # Documentation Connect social accounts and publish posts with the dashboard, API, CLI, or MCP tools. Source: https://opensocial.run/docs Markdown: https://opensocial.run/docs/index.md Open Social connects social accounts to one publishing API. Use the dashboard to manage accounts, posts, API keys, webhooks, and usage. Use the API, CLI, or MCP tools to create, validate, schedule, and publish posts. ## Using an AI agent? [#using-an-ai-agent] Help me integrate Open Social with my application or AI agent. Read these documents first: - Documentation index: https://opensocial.run/llms.txt - Getting started: https://opensocial.run/docs/getting-started.md - API reference: https://opensocial.run/docs/api.md - Platform requirements: https://opensocial.run/docs/video-platforms.md - All public documentation: https://opensocial.run/llms-full.txt For a self-hosted service, replace the origin in these URLs with the service address. Use the REST API at the service address with the /v1 path, the repository CLI, or the Open Social MCP tools. Ask which client and service address to use if they are not known. Follow the connection instructions in the getting started guide. Keep API keys in environment variables. Do not put keys in source code or logs. List connected accounts and read platform capabilities before you create a post. Use returned account and media IDs. Do not guess IDs, limits, or platform options. For TikTok, read current publishing options and ask the creator to select privacy and confirm consent for each video. Validate content for all target accounts. Correct errors before publication. Create a draft unless I request publication or a schedule. Use an RFC 3339 timestamp with an explicit time zone for a schedule. Confirm the time zone if it is not known. A publish request starts an asynchronous operation. Check each publication status before you report success. Report failures and partial success. Do not repeat a publish request without checking the current post status. ## Start here [#start-here] 1. Follow [Getting started](https://opensocial.run/docs/getting-started) to connect an account and create your first post. 2. Read the [API reference](https://opensocial.run/docs/api) for requests, errors, scopes, media, and webhooks. 3. Read the [platform guide](https://opensocial.run/docs/video-platforms) for Instagram, TikTok, and YouTube publishing requirements. ## For agents [#for-agents] Read the available accounts and platform capabilities before you create content. Validate the post for each target account. Publish or schedule it when the user requests that action. Check each publication status before you report success. The [agent workflow](https://opensocial.run/docs/getting-started#use-an-agent) lists the MCP tools for these steps. The API and CLI use the same accounts and posts as the dashboard.