Docs
Quickstart
- Create an account with your email and the code we send.
- In the dashboard, connect WhatsApp (scan a QR code), or Instagram, LinkedIn, Messenger or X (sign in).
- Create an API key. It starts with
spc_live_and is shown once. - Add the MCP server to your agent, or call the REST API.
MCP server: https://api.spacesos.com/mcp · REST base URL: https://api.spacesos.com/v1 · Auth: Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx
Sign up and set up from an agent
An agent can do the whole setup over the API or MCP. Only two steps need the person: reading the code from their inbox, and opening the links to add a card and connect an account.
POST /signupwith the email (or thecreate_accounttool). We email a 6-digit code.POST /signup/verifywith the code (orverify_account). You get an API key.POST /messaging/billing/checkout(orcreate_messaging_billing_checkout) returns a link. The person adds a card to start the 14-day trial. The subscription renews automatically. Connect an account only after Checkout finishes.POST /messaging/accounts/connect-link(orcreate_messaging_connect_link) returns a link where the person scans a QR code or signs in.GET /messaging/accounts(orlist_messaging_accounts) confirms the account is live. Keys:GET,POSTandDELETE /keys.
Paste this into Claude Code, Claude Desktop or any agent that can browse and run commands.
Set me up on spacesOS so you can read and send my WhatsApp messages. Instructions: https://www.spacesos.com/llms.txtStart the trial and connect, with a key
curl -X POST https://api.spacesos.com/v1/messaging/billing/checkout \
-H "Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "success_url": "https://app.spacesos.com/dashboard", "cancel_url": "https://app.spacesos.com/dashboard" }'curl -X POST https://api.spacesos.com/v1/messaging/accounts/connect-link \
-H "Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "channel": "whatsapp" }'Connect your agent
The MCP server gives your agent tools to list accounts and chats, read messages, reply and start chats.
Run this once in your terminal. Claude Code can then read and send your messages.
claude mcp add --transport http spacesos https://api.spacesos.com/mcp --header "Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx"Which key permissions do I need?
New keys can read and send. A read-only key is enough for agents that only summarise or search your messages.
MCP tools
Two servers. https://api.spacesos.com/mcp/start needs no key and signs people up. https://api.spacesos.com/mcp takes Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx and does everything else. Each tool describes its own limits, so Claude and Grok can plan around them.
| Tool | Arguments | What it does |
|---|---|---|
create_account | email | Onboarding server, no key. Emails the person a 6-digit code. |
verify_account | signup_id, code | Onboarding server. Returns the API key and how to connect. |
list_messaging_accounts | none | Connected accounts on every channel. |
list_messaging_chats | account_id, cursor?, limit?, unread? | Chats on an account, newest first. |
list_messaging_messages | account_id, chat_id, cursor?, limit? | Messages in a chat. |
get_messaging_attachment | account_id, chat_id, message_id, attachment_id | One attachment as base64 (up to 5 MB). |
reply_in_chat | account_id, chat_id, text, idempotency_key, attachments? | Reply in an existing chat. Needs a key that can send. |
start_chat | account_id, to (phone, username or user_id), text, idempotency_key | Start a new chat. Subject to the new-chat limits. |
create_messaging_connect_link | channel or account_id | A link the person opens to connect (QR code or login), or to reconnect. |
disconnect_messaging_account | account_id | Disconnect an account; billing for it stops. |
get_messaging_billing | none | Subscription status, connected accounts and monthly total. |
create_messaging_billing_checkout | none | A link where the person starts the free trial and adds a card. |
get_profile | account_id, identifier | A profile on any channel. On LinkedIn it counts as a profile view. |
send_invitation | account_id, identifier, message?, idempotency_key | LinkedIn: invite someone to connect. |
list_invitations | account_id | LinkedIn: pending invitations you sent. |
cancel_invitation | account_id, invitation_id | LinkedIn: withdraw an invitation. |
search_linkedin | account_id, keywords, category? | LinkedIn: search people or companies. |
list_user_posts | account_id, identifier | LinkedIn: recent posts of a person or company. |
get_post | account_id, post_id | LinkedIn: one post. |
list_comments | account_id, post_id | LinkedIn: comments on a post. |
create_post | account_id, text, idempotency_key | LinkedIn: publish a post. |
comment_on_post | account_id, post_id, text, comment_id?, idempotency_key | LinkedIn: comment, or reply to a comment. |
react_to_post | account_id, post_id, reaction?, idempotency_key | LinkedIn: like, celebrate, support, love, insightful or funny. |
REST API
Every request needs your key. Account ids come from GET /messaging/accounts.
| Method | Path | What it does |
|---|---|---|
GET | /messaging/accounts | Your connected accounts |
GET | /messaging/accounts/{account_id}/chats | Chats, newest first (cursor, limit, unread) |
GET | /messaging/accounts/{account_id}/chats/{chat_id}/messages | Messages in a chat |
POST | /messaging/accounts/{account_id}/chats/{chat_id}/messages | Reply in a chat |
POST | /messaging/accounts/{account_id}/chats | Start a chat (WhatsApp: to.phone; Instagram, X, LinkedIn: to.username; Messenger: to.user_id) |
GET | /messaging/accounts/{account_id}/users/{identifier} | A profile (on LinkedIn, counts as a profile view) |
GET | /messaging/accounts/{account_id}/chats/{chat_id}/messages/{message_id}/attachments/{attachment_id} | Download an attachment |
POST | /messaging/webhooks | Get a signed POST for every new message |
GET | /messaging/usage | Sends and new chats per account against its limits |
POST | /messaging/accounts/{account_id}/invitations | LinkedIn: send an invitation { to, message? } |
GET / DELETE | /messaging/accounts/{account_id}/invitations[/{invitation_id}] | LinkedIn: sent invitations, withdraw one |
POST | /messaging/accounts/{account_id}/search | LinkedIn: search { keywords, category: people | companies } |
GET | /messaging/accounts/{account_id}/users/{identifier}/posts | LinkedIn: posts of a person or company |
GET | /messaging/accounts/{account_id}/posts/{post_id}[/comments] | LinkedIn: a post, its comments |
POST | /messaging/accounts/{account_id}/posts | LinkedIn: publish a post { text } |
POST | /messaging/accounts/{account_id}/posts/{post_id}/comments | LinkedIn: comment { text, comment_id? } |
POST | /messaging/accounts/{account_id}/posts/{post_id}/reactions | LinkedIn: react { reaction } |
GET / POST / DELETE | /keys | List, create and revoke keys |
POST | /keys/{key_id}/pause, /keys/{key_id}/resume | Switch a key off and on again |
List chats
curl "https://api.spacesos.com/v1/messaging/accounts/ACCOUNT_ID/chats?limit=20" \
-H "Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx"Reply in a chat
curl https://api.spacesos.com/v1/messaging/accounts/ACCOUNT_ID/chats/CHAT_ID/messages \
-H "Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: reply-7781" \
-d '{ "text": "Thanks, see you at 3." }'Start a WhatsApp chat
curl https://api.spacesos.com/v1/messaging/accounts/ACCOUNT_ID/chats \
-H "Authorization: Bearer spc_live_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-confirmation" \
-d '{ "to": { "phone": "+15551234567" }, "text": "Your order is ready." }'Every send needs an Idempotency-Key (8 to 128 letters, digits, dots, dashes or colons). Retrying with the same key never sends twice. If we cannot tell whether a message went out, the send is marked UNKNOWN and is not retried for you.
Limits
Every account stays inside the limits each channel allows, enforced on our side for every key and every agent, however it is prompted. New accounts start lower and warm up over their first week.
| Channel | Between messages | New chats | Messages per day | First week |
|---|---|---|---|---|
| 15 seconds | 5 an hour, 10 a day | 200 | No new chats for 24 hours after connecting, then 1 an hour and 3 a day | |
| 15 seconds | 10 an hour, 50 a day | 100 | 5 new chats an hour, 20 a day | |
| 20 seconds | 8 an hour, 30 a day | 100 | 15 new chats and 10 invitations a day | |
| Messenger | 20 seconds | 5 an hour, 15 a day | 50 | 5 new chats a day |
| X | 20 seconds | 5 an hour, 20 a day | 100 | 10 new chats a day |
LinkedIn actions
| Action | Limit per account |
|---|---|
| Invitations | 5 an hour, 20 a day, 100 a week (10 a day in the first week) |
| Profile views | 20 an hour, 80 a day |
| Searches | 10 an hour, 30 a day |
| Reading posts, comments and invitations | 30 an hour, 100 a day |
| Comments | 5 an hour, 30 a day |
| Reactions | 10 an hour, 50 a day |
| Posts | 3 a day |
Profile lookups on other channels: up to 100 a day on WhatsApp and 50 a day on Instagram, Messenger and X.
Replies in existing chats are never held back by the first-week limits. Over a limit you get 429 with a Retry-After header and retry_after_seconds in the body; nothing was sent. Agents should wait that long and try again. See your live numbers with GET /messaging/usage or on the dashboard.
Errors
| Status | Meaning |
|---|---|
401 | Missing, wrong or revoked key |
403 | The key lacks the permission for this call; KEY_SUSPENDED means the key is paused, ACCOUNT_SUSPENDED means the workspace is suspended |
404 | Account, chat or recipient not found |
409 | Idempotency key reused for a different message, or a send in progress |
429 | Over a limit; wait retry_after_seconds (also in Retry-After) |
502, 503 | The channel is unavailable right now; nothing was sent, retry later |
Pricing and channels
49 USD per connected account per month, prorated, after a 14-day trial. A card is required. The subscription renews automatically.