Developers · Account integrations
Public API, tokens and MCP
Use the Central Socials account API to manage posts, read stored engagement, work with Community conversations, and manage forms and landing pages. Call the REST API from your application or use the same operations as MCP tools in a compatible client.
This guide covers the account REST API, personal access tokens, social OAuth connection URLs, OAuth for client applications, MCP, OpenAPI schemas, pagination, rate limits and idempotency. To display published content in your own app and report hourly engagement using a connection key, use the separate Custom Posting Integration API and quickstart.
Create a token and make your first request
- Open Account Settings → Tokens and choose Create a personal token.
- Choose a name, select one or more profiles and choose an expiry: 30 days, 90 days, 1 year or Never. Then confirm your password. You need at least one accessible, active profile.
- Copy the token immediately; it is shown once. New personal tokens include all supported API actions for only the selected profiles, excluding frozen or deleted profiles. Profiles created, joined, restored or unfrozen later require a new token. Previously issued tokens keep their original limits. Tokens with no expiry remain valid until revoked or invalidated by account credential changes.
- Send the token in the
Authorizationheader. ReplaceYOUR_TOKENbelow with your personal token. Use an ID returned by the profiles request wherever the examples sayPROFILE_ID.
curl 'https://app.centralsocials.com/api/v1/profiles?limit=25' \
-H 'Authorization: Bearer YOUR_TOKEN'
REST base URL: https://app.centralsocials.com/api/v1. Send a personal token or OAuth access token on every resource request. Application cookies do not authenticate these requests. Keep credentials in secure storage, out of URLs, shared code and logs; never send them to a social network’s API.
Current profile access, roles, subscription features, provider restrictions and approval requirements still apply on every call. A token cannot grant capabilities its account lacks. Revoke tokens and connected OAuth applications in Account Settings → Tokens. Credential changes can invalidate connections. Revocation blocks future requests; work already accepted into publishing continues through its normal workflow.
Connect a social account from your application
- Request a connection URL with
GET /profiles/PROFILE_ID/channels/oauth/INSTAGRAM, using your bearer token. This read requiresprofiles:readand current access to the selected profile. - Open the returned
authorizationUrlin the user’s browser or a new tab within five minutes. Your client opens the browser; an API response cannot open a window itself. The URL contains an encrypted setup ticket bound to the authenticated API user, credential, profile and provider. The user signs into the same Central Socials account if necessary, then completes the existing social-provider consent and account/page/board selection flow. - After the browser confirms the connection in Social Links, request the returned
channelsUrlwith your bearer token and use the linked channel ID for supported publishing operations. Retrieving a URL does not mean a connection succeeded; the user can cancel or the provider can reject authorization.
curl 'https://app.centralsocials.com/api/v1/profiles/PROFILE_ID/channels/oauth/INSTAGRAM' \
-H 'Authorization: Bearer YOUR_TOKEN'
The response has provider (key, platform and label), authorizationUrl, channelsUrl, expiresAt and requiresBrowserSignIn: true. Provider keys are FACEBOOK, INSTAGRAM, LINKEDIN (personal), LINKEDIN_COMMUNITY (Business Pages), TIKTOK, SNAPCHAT, X, YOUTUBE, PINTEREST, REDDIT and THREADS. Only currently enabled/configured providers can return a usable URL. TikTok continues through its combined connection steps.
An authenticated API connection with access to that specific profile is required first. The browser entry rechecks the API credential, grant and profile access before starting OAuth, and rejects expired, revoked, modified or manually constructed requests. The browser must also be signed into that same user’s account with current profile access. Keep the setup link private; it does not contain the API bearer token and cannot sign a browser in. Provider tokens remain private to Central Socials. This read-only discovery endpoint finishes on Social Links. Use the registered connection-attempt flow below to return to your application; completion webhooks are not provided. MCP clients can request the same URL with channels_connect_url.
Return to your application after linking
This flow uses connections:write. New personal tokens include the scope; older grants retain their original permissions. OAuth applications request new consent. Existing provider callback URIs stay unchanged: Central Socials completes its existing callback and account selection, then performs the final return to your registered application URL.
- Register an exact URL with
POST /profiles/P/connection-return-destinations, an idempotency key and{"url":"https://client.example/connected"}. Saveresult.returnDestination.id. Registration belongs to this integration grant and profile; up to ten active URLs are allowed. HTTPS is required outside development loopback. GET lists registrations; DELETE the ID to revoke one. - POST
/profiles/P/connection-attemptswith an idempotency key and the body below. Saveresult.attemptIdand openresult.authorizationUrlin the same user’s browser within five minutes. The full attempt expires after fifteen minutes. Existing sign-in, provider consent, account selection and TikTok’s two connection stages still apply. - The registered return receives
connection_attempt_idand optional callerstate. Your backend verifies the result withGET /profiles/P/connection-attempts/ID; browser query parameters prove no outcome.
{"provider":"FACEBOOK","returnDestinationId":"REGISTERED_ID","clientState":"YOUR_CORRELATION"}
The status read returns attempt with id, profileId, provider, status, createdAt, expiresAt, nullable completedAt, linkedAccountIds, accounts and nullable error. Account rows include ID, platform, display name, handle and current status. States are PENDING, ACTION_REQUIRED, SUCCEEDED, CANCELLED, FAILED and EXPIRED. Explicit denial or selection Back can cancel; closing the browser may simply expire. An interrupted multi-account attempt can still report the accounts it saved. Revoked returns are never followed. At most twenty attempts may start per account per hour.
Upload media to a profile
- POST
/profiles/P/media/upload-sessionswithmedia:write, an idempotency key and{"upload":{"filename":"photo.png","mimeType":"image/png","fileSizeBytes":12345,"saveToLibrary":true}}. - Read
result.uploadUrl,uploadToken,headers,method,expiresAtand the storage-limit fields. Send the exact file bytes to the signed URL using HTTP PUT and the returned content-type header. The URL expires after fifteen minutes. Keep upload URLs and tokens private. - POST
/profiles/P/media/completewith an idempotency key and{"uploadToken":"RETURNED_TOKEN"}. Readresult.asset.idandresult.asset.status. Completion checks profile/grant ownership, exact size, type and aggregate quota. - GET
/profiles/P/media/ASSET_IDwithmedia:readuntilasset.statusisREADY. Processing can also returnPROCESSINGorFAILED. Use the ready ID inlocalMediaAssetIds.
Individual reads include file size, type, dimensions, duration, visibility, upload time, nullable failure and a short-lived absolute ready preview URL/expiry. The existing media list returns only ready, visible profile-local files. A hidden workflow file still counts toward quota. Browser and API grant upload tokens cannot be exchanged. Completion can resume after an interrupted enqueue by retrying its same key and token. Optional replaceAssetId replaces an existing profile asset. URL imports are not supported.
Wait for an asset to finish processing before replacing it. Completion errors marked RETRY_SAME_REQUEST are temporary: retry the same key and upload token. Invalid, expired or foreign upload tokens return corrective/authentication guidance with retryable:false; correct that cause before trying again.
Discover destinations and validate a post
GET /profiles/P/channels retains its social-only {data:[{id,platform,displayName,accountHandle}],nextCursor} shape. Its IDs go in socialAccountIds. For both social and custom destinations, use GET /profiles/P/destinations. Each row has a stable id, kind (SOCIAL or CUSTOM_APP), nullable platform/handle/logo, label, canPublish and health:{status,checkedAt,action}. Health is a last-known observation and may have no check timestamp.
GET /profiles/P/destinations/ID/capabilities returns text limits/counting, supported media/count/size/duration/aspect rules, required options and current creator information where applicable. Null bounds are unspecified. TikTok privacy and duration options are account-specific. Profile permissions, subscription rules and provider availability still apply.
POST /profiles/P/posts/validate accepts the normal {post:{...}} body with posts:write and no idempotency key. Its default action is publish_now; use schedule to check a schedule. It creates no post, receipt or publishing job. The response contains valid, checkedAt, issues and destination validity. Issues identify a destination or global field, code, error/warning tone and message. Validation is repeated on submission; a provider can still reject later.
Shared title/caption requests remain supported, with a 300-character title and 5,000-character caption. Add destinationContent keyed by selected destination ID for independent text. Missing fields inherit shared text; an empty string clears that field. Each social destination applies its own limit and counting rules. Custom Posting has a 300-unit title and 10,000-unit caption feed policy; consuming apps may choose smaller display limits. Text is never silently shortened for another destination.
{"post":{"action":"draft","caption":"Shared fallback","socialAccountIds":["SOCIAL_ID"],"customAppConnectionIds":["CUSTOM_ID"],"destinationContent":{"SOCIAL_ID":{"title":"","caption":"Short social text"},"CUSTOM_ID":{"caption":"Independent application text"}}}}
Omitting destinationContent on edit preserves saved overrides for destinations that remain selected. An explicit empty object removes them. Draft editing, approvals, duplication, previews, publishing and feeds retain the effective destination text. Saved overrides can be edited in the composer’s Destination text section.
Manage Custom Posting Integrations
Account credentials with connections:write and profile owner/administrator authority can GET/POST /profiles/P/custom-apps. Create with {"name":"Example app"}; the receipt returns result.connection and result.key. Save the key securely. The stable connection ID is used in customAppConnectionIds and unified destination discovery. List responses return safe metadata and never full keys or challenges. Consumer app keys retain their separate feed/test/report authority.
POST /profiles/P/custom-apps/ID/test starts the five-minute challenge. The consumer must fetch and acknowledge it with its app key through the consumer API. Poll connection verification/test metadata to see completion. POST .../ID/regenerate rotates the key and clears verification. DELETE .../ID revokes access while retaining the destination ID, published posts and metrics. Retained revoked rows count toward the existing twenty-connection limit.
Create/rotation keys are encrypted in saved receipts. An identical authenticated retry can recover the same key for fifteen minutes; operation inspection exposes no key/envelope. After SECRET_RESPONSE_EXPIRED, inspect the connection and explicitly rotate if necessary. For custom destinations, published means available in the feed, not proof that the external app fetched or displayed it.
Understand publishing outcomes
A create response is {operationId,result:{post:{id,status}},replayed}. Successful command execution can still leave publishing pending. Post reads include the social destination rows, saved destinationContent and a unified delivery array for social/custom destinations. Each delivery includes destination ID/type, nullable platform, status, provider publication ID/time, effective title/caption and nullable failure.
A failure has code, category, message, nullable retryable, action, nullable sanitized providerReference and observedAt. Actions include reconnect, grant permission, correct media/content, wait, contact support or review the outcome. Historical unclassified failures remain unknown. Preserve successful destinations when another fails; a new idempotency key can create a duplicate post.
Parent statuses include drafts/review states, SCHEDULED, PUBLISHING, PARTIALLY_PUBLISHED, PUBLISHED and FAILED. Destination statuses are DRAFT, SCHEDULED, PENDING, PUBLISHED, FAILED, SKIPPED. Command receipt status describes a separate step. The OpenAPI response schemas define every exact field, enum, null and example.
REST endpoint reference
Append the paths below to the REST base URL. P means /profiles/{profileId}; replace each brace-delimited ID with the resource ID. The OpenAPI 3.1 document contains the exact request and response fields, types, examples, error payloads, required headers and OAuth scopes for all 46 operations. The base URL also returns that document without authentication when API access is available.
| Method and path | Purpose |
|---|---|
GET /profiles | List profiles included in the connection and still accessible to the account. |
GET P/destinations[/ID/capabilities] | Unified destination discovery and effective rules. |
POST P/posts/validate | Validate intended publishing without creating a post. |
POST P/media/upload-sessions, POST P/media/complete, GET P/media/ID | Signed file upload, verified completion and processing status. |
GET/POST P/custom-apps, POST P/custom-apps/ID/test, POST P/custom-apps/ID/regenerate, DELETE P/custom-apps/ID | Owner/administrator connection management. |
GET/POST P/connection-return-destinations, DELETE P/connection-return-destinations/ID | Register and revoke exact return URLs for this grant/profile. |
POST P/connection-attempts, GET P/connection-attempts/ID | Start linking and verify its durable outcome. |
GET P/channels | List linked publishing destination IDs; provider credentials are never returned. |
GET P/channels/oauth/{provider} | Get a connection URL to open in the user’s browser; sign-in and provider consent are required. |
GET P/media | List ready local library media IDs for reuse in posts, forms and pages. |
GET P/postsGET P/posts/{postId} | List posts or read one post with destination publishing status. |
POST P/postsPATCH P/posts/{postId} | Create a draft, schedule or publish; update an editable draft. |
DELETE P/posts/{postId} | Delete the Central Socials record. Already published content stays on the social network. |
GET P/engagementGET P/engagement/posts | Read stored account snapshots or post results with their capture/poll timestamps. |
GET P/communityGET P/community/{conversationId} | List conversations or read a conversation’s paginated interactions. |
PATCH P/community/{conversationId} | Change workflow status, including archive; does not delete provider content. |
POST P/community/{conversationId}/assign-self | Assign a conversation to the current account user. |
POST P/community/{conversationId}/draftsPOST P/community/{conversationId}/replies | Save a reply draft without sending, or send a supported reply with a body field. |
DELETE P/community/{conversationId}/comment | Delete or hide a supported provider comment. Direct messages cannot be deleted this way. |
GET P/formsGET P/forms/{formId} | List form summaries or retrieve an individual definition. |
POST P/formsPATCH P/forms/{formId}DELETE P/forms/{formId} | Create an active form, update a form, or archive it and deactivate its tracking links. |
GET P/landing-pagesGET P/landing-pages/{pageId} | List page summaries or retrieve an individual document. |
POST P/landing-pagesPATCH P/landing-pages/{pageId}DELETE P/landing-pages/{pageId} | Create, replace, or archive and unpublish a page. New API pages are unpublished by default. |
POST P/landing-pages/{pageId}/restore | Restore and publish an archived page. |
GET /operations/{operationId} | Inspect this connection’s mutation receipt and outcome. |
Lists accept limit from 1 to 100 (default 25) and after. Read data and nextCursor from the JSON response; pass the returned cursor as after to retrieve the next page. A null cursor marks the end. Individual resource reads use named fields such as post, form or page.
Engagement reads use stored data and do not trigger provider polling. Missing metrics remain null. Do not add rolling 30-day snapshot values together as interval totals. Account snapshots also accept an ISO date-time since within the past year; the default is the last 30 days.
Create a draft, then check its status
curl 'https://app.centralsocials.com/api/v1/profiles/PROFILE_ID/posts' \
-X POST \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: draft-example-0001' \
--data '{"post":{"title":"Campaign draft","caption":"Draft copy","action":"draft"}}'
The JSON response contains operationId, result and replayed. The created post is in result.post. To schedule or publish, supply action: "schedule" with scheduledFor, or action: "publish_now", plus socialAccountIds from the channels endpoint and any required localMediaAssetIds from the media endpoint. Provider-specific validation and approval rules may prevent a request; API access does not bypass them.
Publishing is asynchronous. An accepted command or successful receipt does not confirm delivery. Poll GET /profiles/PROFILE_ID/posts/POST_ID and check destination statuses before showing a post as published.
Form create/update bodies use {"form":{"title":"Contact us","definition":{}}}; page create/update bodies use {"page":{"title":"Campaign","document":{},"isPublished":false}}. Definitions and documents use Central Socials’ constrained formats; read an existing form/page for its structure and consult the OpenAPI request schema. Arbitrary executable HTML is not accepted, and referenced media and resources must belong to the same profile.
Idempotency and safe retries
Every mutation requires Idempotency-Key: 8–128 characters using letters, digits, dots, underscores, colons or hyphens. Read-only post validation does not require a key. Save a unique key for each new action. After a timeout or uncertain response, retry through the same connection with the same key and identical input. Reusing a key with different input returns HTTP 409.
Completed requests return their saved result with replayed: true, after current authorization is rechecked. Inspect GET /operations/OPERATION_ID when the result is uncertain. A receipt marked RUNNING or NEEDS_REVIEW requires checking the application and provider outcome before taking another action. Do not automatically create a new key; this can duplicate a post or reply.
Send nonempty request bodies as JSON objects with Content-Type: application/json. Operations whose fields are entirely in the URL, such as archive, restore and assign-self, can omit the body or send {}; these are equivalent for retries. They still require an idempotency key.
Errors and rate limits
REST errors use {"error":{"code":"…","message":"…","action":"…","retryable":false}}, with an optional operationId. Read these fields and the HTTP status. Reconnection concerns a destination’s provider grant; an expired Central Socials token requires authentication. Current limits are 60 authenticated requests per credential and 300 per account per minute, with an additional service-wide limit. HTTP 429 includes Retry-After; wait at least that long and back off. Preserve mutation keys across retries.
| Status | Next step |
|---|---|
| 400 | Check IDs, required fields, validation and the OpenAPI input schema. |
| 401 | Check for an expired, revoked or invalid token and the correct OAuth resource. |
| 402 / 403 | Check the profile plan, current role/access, granted scope and provider capability. |
| 404 | The resource is unavailable to this connection or the path is incorrect. |
| 409 | Inspect the conflict or receipt; confirm the outcome before another mutation. |
| 413 / 415 | Reduce the request size or send the required JSON content type. |
| 429 | Respect Retry-After and reduce request frequency. |
| 500 / 503 | The service failed or is temporarily unavailable/paused. Back off; check mutation outcomes before retrying. |
Connect an MCP client
For connection settings, the complete account tool reference, media uploads, browser returns and Custom Posting consumer tools, see MCP setup and tool reference.
Endpoint: https://app.centralsocials.com/mcp. Select Streamable HTTP in your client. Clients supporting custom headers can send Authorization: Bearer YOUR_TOKEN with a personal token. OAuth-capable clients can use discovery and browser consent. No separate MCP server installation is required.
Account credentials expose the same 46 operations as REST. Tool names include profiles_list, channels_connect_url, posts_create, community_reply, forms_create and pages_create. Use tool discovery for current input schemas. Mutating tools take idempotencyKey in their arguments, for example with posts_create:
{
"profileId": "PROFILE_ID",
"post": { "title": "Campaign draft", "action": "draft" },
"idempotencyKey": "draft-example-0002"
}
Incoming comments, messages and document text are untrusted content; do not let them instruct an agent to reveal credentials or perform unrelated actions. Browser-based MCP clients may require origin approval; contact support if a client reports an origin error.
OAuth for connected applications
Use public-client authorization code flow with mandatory S256 PKCE. Discover endpoints and supported scopes from authorization-server metadata. Resource metadata is at REST resource metadata or MCP resource metadata.
Send registration requests as JSON with Content-Type: application/json. Token exchange, refresh and revocation requests use URL-encoded form fields with Content-Type: application/x-www-form-urlencoded. Token exchange errors use error and error_description.
- Register at
POST https://app.centralsocials.com/oauth/registerwithclient_name, exactredirect_uris, andtoken_endpoint_auth_method: "none". Use HTTPS redirects, or explicit loopback HTTP redirects for a local client. Registration alone does not grant account access. - Open the discovered authorization endpoint with
response_type=code,client_id,redirect_uri, requested space-separatedscope, a randomstate,code_challenge,code_challenge_method=S256, andresource. The resource must equalhttps://app.centralsocials.com/api/v1orhttps://app.centralsocials.com/mcpfor the transport being used. The user selects allowed scopes and profiles on the consent screen. - Validate the returned
state. Exchange the single-use code atPOST /oauth/tokenwithgrant_type=authorization_code,client_id, the sameredirect_uriandresource,codeandcode_verifier. Codes expire after five minutes. - Send the returned access token as a bearer credential. Access tokens last up to one hour. Refresh at the token endpoint with
grant_type=refresh_token,client_id, the sameresourceandrefresh_token. Save each newly returned refresh token and replace the previous one; refresh tokens last up to 30 days within the connection’s 90-day lifetime. - Revoke in Account Settings → Tokens or at
POST /oauth/revokewithtokenandclient_id. Reusing a consumed authorization code or refresh token revokes the connection.
OAuth tokens are bound to the chosen REST or MCP resource and cannot be exchanged between them. Personal tokens support both transports. Supported scopes are profiles:read, media:read, media:write, connections:write, posts:read, posts:write, engagement:read, community:read, community:write, forms:read, forms:write, pages:read and pages:write. This flow does not support client secrets, client-credentials/password grants or OpenID Connect.
Coverage and other integrations
The account API covers the operations above, including connection URL discovery for browser-based social OAuth. Approval submission/decisions, AI generation, advertising, CRM, billing and administration are not exposed as account commands. Existing library media can be reused. Community replies and moderation depend on the connected provider’s permissions and messaging rules.
Custom Posting Integration uses a generated connection key, its own /api/custom-apps/v1 REST base, and a separate four-tool MCP surface at the same /mcp endpoint. Connection keys cannot call account tools. Choose that API when your app needs published content and numeric engagement reporting rather than account operations.