Skip to content

Authentication

Every request carries a bearer credential:

Authorization: Bearer <API key or OAuth access token>

The API and MCP server never read cookies, so there is no browser session to hijack and no CORS setup to get wrong. A credential that is wrong, revoked or expired is rejected with INVALID_CREDENTIAL; it never falls back to anonymous access. A Xholic sign-in session is not an API credential either: it is refused, so a session copied out of a browser can’t drive the API.

Every connection starts with as little as it needs, and gets more only when you say so:

  • Read and Write are on; Publish (posting, sending, changing what goes out) starts off. The first time your AI needs it, the call answers SCOPE_MISSING with a link; you allow it in one click and the AI tries again.
  • One X account (your own) unless you tick more. A connection can’t see or act on accounts you leave unticked.
  • Unused connections switch off. A key or app that hasn’t made a call in 90 days stops working; create a new key or connect the app again.

For scripts, servers, CI and MCP clients without OAuth.

  • Create them in Settings → API / MCP / CLI. A key looks like xhk_… and is shown once; Xholic stores only a hash and shows its last four characters afterwards.
  • Give each key a name, the scopes and X accounts it needs and, if you like, an expiry date. Up to 10 keys per user.
  • Revoking a key takes effect within seconds. The Last used time shows which keys are still in use.

Keep keys out of code and client-side apps. Anyone with a key can act as you within its scopes.

For MCP clients such as Claude, ChatGPT, Claude Code and Cursor, and for the CLI’s xholic login. You never handle a token yourself.

  1. The client calls https://api.xholic.ai/mcp without a token and gets 401 with a WWW-Authenticate header pointing to /.well-known/oauth-protected-resource.
  2. That document names Xholic’s authorization server. The client reads its metadata (/.well-known/oauth-authorization-server), registers itself (dynamic client registration) and starts an OAuth 2.1 authorization code flow with PKCE.
  3. You sign in to Xholic and see the consent screen: the app’s name, the scopes (Read and Write ticked, Publish off), the X accounts it can use and its default account.
  4. The client receives an access token and a refresh token and uses them from then on. Each refresh token works once: refreshing returns a new pair and the old one stops working.

The consent screen is shown on every new authorization, even when a client asks to skip it. Connected apps are listed next to your API keys, and revoking one ends its access.

Read, Write and Publish are chosen on the consent screen, not as OAuth scopes; the authorization server issues openid, profile and offline_access.

xholic login prints a short code such as K7QM-2XPD, and the consent screen shows the same code. Approve only if they match: a different code (or one you didn’t start) means the request in your browser isn’t the one your terminal is waiting for.

Scope Allows Examples
read Reading data. Never changes anything. get_me, get_queue, get_analytics, search_x
write Changing data in Xholic. save_draft, remember, create_worker, add_to_contact_list
publish Acting on X: posts, replies, DMs, follows. schedule_post, publish_now, send_dms

Each action needs exactly the scope of its kind; the reference lists it. A call without the scope fails with SCOPE_MISSING, and error.details.allowUrl is the one-click page to allow it. MCP clients still see those tools, so the AI can hand you that link. You can change a connection’s scopes and accounts later in Settings.

When an MCP app can show a confirmation (MCP elicitation), Publish actions also wait for your yes in the app before they run; see Confirm before posting.

A connection covers the X accounts you chose for it, out of the ones your Xholic login can use: your own, accounts you added to your plan, and accounts shared with you.

  • list_accounts (accounts.list) returns them, each marked as your own, added or shared.
  • Actions act on the connection’s default account unless you pass account with an @handle:
{ "account": "@brandaccount", "text": "…", "scheduledAt": "2026-11-03T09:00", "timezone": "UTC" }
  • On shared accounts your role applies exactly as in the app. An Editor can write and schedule but not send DMs or change settings; such calls fail with ROLE_NOT_PERMITTED. The account’s owner sees what your connections did on it in their Settings.
  • Account-wide actions (settings, connections) take no account.

API, MCP and CLI access is part of every plan, including the trial. Plan gates are the app’s own: Workers, Signals, DMs and Articles need the plan that includes them (FEATURE_NOT_INCLUDED otherwise).

If a subscription lapses, keys and connected apps are kept, and calls return SUBSCRIPTION_REQUIRED until it is active again. Connections stay visible and revocable in Settings throughout.

https://api.xholic.ai/mcp/free needs no credential at all. See Free tools.