# wavpost — LLM Reference Unified social media API. Publish to LinkedIn, X (Twitter), YouTube, and TikTok from a single call. Automate likes, follows, DMs, and more. **API base URL:** https://api.wavpost.com All paths below are relative to that base (e.g. `POST /api/v1/posts` → `https://api.wavpost.com/api/v1/posts`). --- ## Authentication Pass your API key as a Bearer token on every request: ``` Authorization: Bearer sk_live_your_key_here ``` Create keys via `POST /api/keys` or from the dashboard. The `rawKey` is shown only once — store it immediately. --- ## Plans | Plan | Price/mo | Posts/mo | Social accounts | |---------|----------|-----------|-----------------| | Free | $0 | 20 | 2 | | Starter | $19 | 120 | 10 | | Creator | $49 | Unlimited | 50 | | Pro | $999 | Unlimited | Unlimited | --- ## Credits | Action | Credits | Plan | |--------|---------|------| | Post to LinkedIn / YouTube / TikTok | 1 each | Any | | Post to Twitter/X | 3 | Paid (Starter+) | | Twitter: like, unlike, follow, unfollow, bookmark, remove, delete, hide reply | 1 each | Paid | | Twitter: send DM | 2 | Paid | | LinkedIn: delete post, reshare | 1 each | Any | | Twitter: read timeline, look up user | 0 (free) | Any | | All GET reads (posts, logs, usage, status…) | 0 (free) | Any | Check balance: `GET /api/usage` --- ## Workflow for AI agents 1. Check connections: `GET /api/connect/status` 2. Publish: `POST /api/v1/posts` with `text`, `platforms`, optional `mediaUrls`, `profile` 3. Take platform actions: use the Twitter/LinkedIn endpoints below 4. Audit: `GET /api/logs` or `GET /api/v1/posts` --- ## Posts Publish and list posts across all connected platforms ### GET /api/v1/posts **List posts** **Response 200:** { posts: [...] } — array of post records with per-platform results **Errors:** 401 ### POST /api/v1/posts **Publish a post** Publish to one or more platforms simultaneously. Credits charged only for platforms that succeed. Twitter/X requires a paid plan. **Body (JSON):** - `text` — Post content. Twitter: max 280 chars. - `platforms` — Platforms to publish to - `mediaUrls` — Public media URLs. LinkedIn: images (up to 9). YouTube/TikTok: video URL. Twitter: ignored (text-only). - `scheduledFor` — ISO 8601 datetime — stored on post record; platforms are published immediately - `profile` — Profile slug (uses default profile if omitted) - `meta` — Platform-specific metadata. Example: { "youtube": { "title": "My Video", "tags": ["ai", "tech"], "categoryId": "28", "privacyStatus": "public" } } **Response 201:** Post object with id, status, platformResults map per platform (ok, platformPostId or error) **Errors:** 400, 401, 402, 403, 404 --- ## Twitter Actions Twitter/X-specific actions: like, follow, bookmark, DM, delete tweet, hide reply, timeline, user lookup. Write actions require a paid plan. ### POST /api/v1/twitter/bookmark **Bookmark a tweet** **Body (JSON):** - `tweet_id` — Tweet ID to bookmark - `profile` — Profile slug **Response 201:** { ok: true, bookmarked: true } **Errors:** 400, 401, 402, 403 ### DELETE /api/v1/twitter/bookmark **Remove a bookmark** **Body (JSON):** - `tweet_id` — Tweet ID to remove from bookmarks - `profile` — Profile slug **Response 200:** { ok: true, bookmarkDeleted: true } **Errors:** 400, 401, 402, 403 ### POST /api/v1/twitter/dm **Send a direct message** Send a DM to a user. The recipient must allow DMs from your account. **Body (JSON):** - `recipient_id` — Numeric Twitter user ID of the recipient - `text` — Message text - `profile` — Profile slug **Response 201:** { ok: true, dmConversationId: '...', dmEventId: '...' } **Errors:** 400, 401, 402, 403 ### POST /api/v1/twitter/follow **Follow a Twitter user** **Body (JSON):** - `target_user_id` — Numeric Twitter user ID to follow - `profile` — Profile slug **Response 201:** { ok: true, following: true, pendingFollow: false } **Errors:** 400, 401, 402, 403 ### DELETE /api/v1/twitter/follow **Unfollow a Twitter user** **Body (JSON):** - `target_user_id` — Numeric Twitter user ID to unfollow - `profile` — Profile slug **Response 200:** { ok: true, following: false } **Errors:** 400, 401, 402, 403 ### POST /api/v1/twitter/like **Like a tweet** **Body (JSON):** - `tweet_id` — Tweet ID to like - `profile` — Profile slug **Response 201:** { ok: true, liked: true } **Errors:** 400, 401, 402, 403 ### DELETE /api/v1/twitter/like **Unlike a tweet** **Body (JSON):** - `tweet_id` — Tweet ID to unlike - `profile` — Profile slug **Response 200:** { ok: true, unliked: true } **Errors:** 400, 401, 402, 403 ### PUT /api/v1/twitter/reply/hide **Hide or unhide a reply** Hide or unhide a reply on one of your own tweets. You cannot hide replies on other users' tweets. **Body (JSON):** - `tweet_id` — Tweet ID of the reply to hide/unhide - `hidden` — true to hide, false to unhide (defaults to true) - `profile` — Profile slug **Response 200:** { ok: true, hidden: true } **Errors:** 400, 401, 402, 403 ### GET /api/v1/twitter/timeline **Get home timeline** Fetch recent tweets from the authenticated user's home timeline. Free — does not consume credits. **Query parameters:** - `max_results` — Number of tweets to return (default: 10) - `profile` — Profile slug **Response 200:** { ok: true, tweets: [...], count: N } **Errors:** 400, 401 ### DELETE /api/v1/twitter/tweet **Delete a tweet** **Body (JSON):** - `tweet_id` — Tweet ID to delete - `profile` — Profile slug **Response 200:** { ok: true, deleted: true } **Errors:** 400, 401, 402, 403 ### GET /api/v1/twitter/user **Look up a Twitter user by username** Get a user's public profile by @username. Free — does not consume credits. **Query parameters:** - `username` *(required)* — Twitter username without the @ symbol - `profile` — Profile slug **Response 200:** { ok: true, user: { id, name, username } } **Errors:** 400, 401 --- ## LinkedIn Actions LinkedIn-specific actions: delete post, reshare. Available on any plan. Reactions and comments require LinkedIn Partnership (not available). ### DELETE /api/v1/linkedin/post **Delete a LinkedIn post** **Body (JSON):** - `post_urn` — LinkedIn post URN, e.g. urn:li:share:1234 or urn:li:ugcPost:1234 - `profile` — Profile slug **Response 200:** { ok: true, deleted: true, postUrn: '...' } **Errors:** 400, 401, 402 ### POST /api/v1/linkedin/reshare **Reshare a LinkedIn post** **Body (JSON):** - `post_urn` — LinkedIn post URN to reshare - `commentary` — Optional text to add to the reshare - `profile` — Profile slug **Response 201:** { ok: true, reshareId: 'urn:li:share:...' } **Errors:** 400, 401, 402 --- ## Billing Plan info, credit balance, and transaction history ### GET /api/usage **Get plan, credit balance, and recent transactions** **Response 200:** { plan: { id, label, price }, credits: { balance, monthlyAllowance, used, resetAt }, recentTransactions: [...] } **Errors:** 401 --- ## Profiles Manage workspace profiles (group connections by brand/client) ### GET /api/profiles **List profiles** **Response 200:** { profiles: [...] } **Errors:** 401 ### POST /api/profiles **Create a profile** **Body (JSON):** - `name` — Profile display name **Response 201:** { profile: { id, name, slug, isDefault, createdAt } } **Errors:** 400, 401 ### PATCH /api/profiles/{profileId} **Update a profile** **Body (JSON):** - `name` — New display name - `isDefault` — Set as default profile **Response 200:** Updated profile object **Errors:** 401 ### DELETE /api/profiles/{profileId} **Delete a profile** **Response 200:** { ok: true } **Errors:** 401 --- ## Logs Activity and audit logs ### GET /api/logs **Get activity logs** **Query parameters:** - `limit` — Number of logs to return (max 200) (default: 50) - `offset` — Pagination offset (default: 0) **Response 200:** { logs: [...], total, limit, offset } **Errors:** 401 --- ## API Keys Create and revoke API keys for programmatic access ### GET /api/keys **List API keys** **Response 200:** { keys: [{ id, name, keyPreview, createdAt, lastUsedAt }] } **Errors:** 401 ### POST /api/keys **Create an API key** Creates a new API key. The rawKey value is returned only once — store it securely immediately. **Body (JSON):** - `name` — Label for the key **Response 201:** { key: { id, name, keyPreview, createdAt }, rawKey: 'sk_live_...' } **Errors:** 401 ### DELETE /api/keys/{keyId} **Revoke an API key** **Response 200:** { ok: true } **Errors:** 401 --- ## Connections Connect and manage social platform OAuth accounts ### GET /api/auth/{platform} **Start OAuth flow (browser redirect)** Browser-only. Redirects to the OAuth provider. platform ∈ linkedin | twitter | youtube | tiktok *Auth: not required (browser/OAuth flow)* **Query parameters:** - `profileId` — Optional profile UUID **Response 200:** 302 redirect to OAuth provider **Errors:** 404 ### POST /api/connect/{platform}/confirm **Confirm OAuth account selection** Saves the chosen account as a platform connection. Requires dashboard session cookie (not API key). **Body (JSON):** - `option` — One option object from GET /options - `profileId` — Profile UUID (default profile if omitted) **Response 201:** { ok: true, redirect: '/dashboard/connections' } **Errors:** 400, 401, 404 ### POST /api/connect/{platform}/disconnect **Disconnect a platform** **Body (JSON):** - `profileId` — Profile UUID (default profile if omitted) **Response 201:** { ok: true } **Errors:** 401 ### GET /api/connect/{platform}/options **List OAuth account options after callback** Requires temp session cookie set by the OAuth callback. Returns selectable accounts (personal + orgs). *Auth: not required (browser/OAuth flow)* **Response 200:** { options: [{ accountId, name, description, type, picture?, accountUrn? }] } **Errors:** 401, 502 ### GET /api/connect/status **Get connection status for all platforms** **Query parameters:** - `profileId` — Profile ID (uses default profile if omitted) **Response 200:** { linkedin: { connected: true, displayName: "Jane" }, twitter: { connected: false } } **Errors:** 401 --- ## Webhooks ### POST /api/webhooks/incoming **Receive content and auto-publish to social media** Accepts article/blog content payloads (e.g. from ClyroAI or similar SEO tools) and publishes them to the specified social platforms. Authenticate with Authorization: Bearer or X-API-Key header. Use ?test=true or set body.test=true for a dry-run without posting. **Query parameters:** - `platforms` — Comma-separated platform list (default: linkedin,twitter) - `profile` — Profile slug (uses default if omitted) **Body (JSON):** - `title` — Article title — prepended to post text - `body` — Article body / content - `keyword` — Primary keyword — appended as a hashtag - `status` — Set to 'test' for a dry-run - `timestamp` — ISO 8601 publish datetime (stored as scheduledFor) - `test` — true for a dry-run (no post created) **Response 201:** { ok: true, postId: '...', platforms: { linkedin: { ok, platformPostId }, ... } } **Errors:** 400, 401, 402, 403, 404 --- ## Error format ```json { "error": "Human-readable message" } ``` Common status codes: 200 OK, 201 Created, 400 Bad request, 401 Unauthorized, 402 Insufficient credits, 403 Forbidden (plan restriction), 404 Not found, 502 Upstream provider error. --- ## Machine-readable spec OpenAPI 3.0: https://api.wavpost.com/openapi.json