Introduction

wavpost lets you publish to LinkedIn, Twitter, and YouTube from a single HTTP endpoint. Connect accounts once via OAuth โ€” then post everywhere with one call.

Base URL

https://api.wavpost.com

Auth

Bearer token

Format

JSON

Authentication

All endpoints require an Authorization: Bearer <token> header. Two token types are accepted:

API Key

Recommended

Generate from the dashboard. Starts with sk_live_. Never expires unless revoked.

Authorization: Bearer sk_live_your_api_key_here

Firebase ID Token

Short-lived JWT from Firebase Auth. Used by the dashboard UI.

Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...

Quickstart

From zero to publishing in 3 steps.

1

Get your API key

Go to Dashboard โ†’ API Keys โ†’ Create key.

sk_live_abc123efg456...  # store this securely, shown only once
2

Check connected platforms

curl https://api.wavpost.com/api/connect/status \
  -H "Authorization: Bearer sk_live_your_key"
3

Publish a post

curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello from the API!",
    "platforms": ["linkedin", "twitter"]
  }'

Posts

POST/api/v1/postsPublish a post

Parameters

NameTypeDescription
text*stringPost content. Max 3000 chars for LinkedIn.
platforms*string[]linkedin ยท twitter ยท youtube
mediaUrlsstring[]Public image URLs. Up to 9 for LinkedIn.
scheduledFordatetimeISO 8601 UTC. Saves post as scheduled.
profilestringProfile slug. Defaults to default profile.
curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "New feature drop!",
    "platforms": ["linkedin", "twitter"],
    "mediaUrls": ["https://your-cdn.com/image.jpg"]
  }'

Response 201

{
  "id": "a6c01b90-37da-4224-9338-e2025626b7bf",
  "text": "New feature drop!",
  "platforms": ["linkedin", "twitter"],
  "status": "published",
  "createdAt": "2025-03-19T07:19:57Z",
  "platformResults": {
    "linkedin": { "ok": true, "platformPostId": "urn:li:share:123456" },
    "twitter": { "ok": false, "error": "Twitter not connected." }
  }
}
GET/api/v1/postsList all posts
curl https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key"

Profiles

Profiles let you manage multiple brands or clients. Each profile has its own set of connected platform accounts. A default profile is created automatically on signup.

GET/api/profilesList profiles
curl https://api.wavpost.com/api/profiles \
  -H "Authorization: Bearer sk_live_your_key"
POST/api/profilesCreate a profile

Parameters

NameTypeDescription
name*stringDisplay name for the profile
curl -X POST https://api.wavpost.com/api/profiles \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Brand"}'
PATCH/api/profiles/{profileId}Update a profile

Parameters

NameTypeDescription
namestringNew display name
isDefaultbooleanSet as the default profile
DELETE/api/profiles/{profileId}Delete a profile
curl -X DELETE https://api.wavpost.com/api/profiles/profile-uuid \
  -H "Authorization: Bearer sk_live_your_key"

Connections

Connect social accounts via OAuth. Users open the connect URL in their browser โ€” no platform developer apps needed.

GET/api/connect/statusCheck platform connection status

Parameters

NameTypeDescription
profileIdstringQuery param. Uses default profile if omitted.
curl "https://api.wavpost.com/api/connect/status?profileId=uuid" \
  -H "Authorization: Bearer sk_live_your_key"

Response 200

{
  "linkedin": { "connected": true,  "displayName": "Anshu Raj Singh" },
  "twitter":  { "connected": false, "displayName": null },
  "youtube":  { "connected": false, "displayName": null }
}
GET/api/auth/{platform}Start OAuth (browser redirect)

Open this URL in a browser to start the OAuth flow. After connecting, the user is redirected to the dashboard.

# Open in browser โ€” supported platforms: linkedin, twitter, youtube
https://api.wavpost.com/api/auth/linkedin?profileId=your-profile-id
POST/api/connect/{platform}/disconnectDisconnect a platform

Parameters

NameTypeDescription
profileIdstringOptional. Uses default profile if omitted.
curl -X POST https://api.wavpost.com/api/connect/linkedin/disconnect \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"profileId": "uuid"}'

Logs

Every publish attempt, platform connection, and profile change is automatically logged.

GET/api/logsGet activity logs

Parameters

NameTypeDescription
limitintegerNumber of logs. Default 50, max 200.
offsetintegerPagination offset. Default 0.
curl "https://api.wavpost.com/api/logs?limit=20&offset=0" \
  -H "Authorization: Bearer sk_live_your_key"

Response 200

{
  "logs": [
    {
      "id": "uuid",
      "action": "post.published",
      "platform": "linkedin",
      "profileName": "Default",
      "status": "success",
      "metadata": {
        "text": "New feature drop!",
        "platformPostId": "urn:li:share:123456"
      },
      "createdAt": "2025-03-19T07:19:57Z"
    }
  ],
  "total": 42,
  "limit": 20,
  "offset": 0
}

Action types

post.publishedplatform.connectedplatform.disconnectedprofile.createdprofile.deleted

API Keys

API keys start with sk_live_ and don't expire unless revoked. The raw key is shown only once โ€” store it immediately.

GET/api/keysList API keys
curl https://api.wavpost.com/api/keys \
  -H "Authorization: Bearer sk_live_your_key"
POST/api/keysCreate an API key

Parameters

NameTypeDescription
name*stringLabel to identify this key
curl -X POST https://api.wavpost.com/api/keys \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "My agent key"}'

Response 201

{
  "key": { "id": "uuid", "name": "My agent key", "keyPreview": "...x9z2" },
  "rawKey": "sk_live_abc123..."  // shown only once
}
DELETE/api/keys/{keyId}Revoke an API key
curl -X DELETE https://api.wavpost.com/api/keys/key-uuid \
  -H "Authorization: Bearer sk_live_your_key"

Usage & Credits

Check your current plan, credit balance, and recent usage transactions.

GET/api/usageGet usage and credit balance
curl https://api.wavpost.com/api/usage \
  -H "Authorization: Bearer sk_live_your_key"

Response 200

{
  "plan": {
    "id": "free",
    "label": "Free",
    "price": 0
  },
  "credits": {
    "balance": 480,
    "monthlyAllowance": 500,
    "used": 20,
    "resetAt": "2026-04-01T00:00:00.000Z"
  },
  "recentTransactions": [
    {
      "amount": -2,
      "action": "post.published",
      "metadata": { "platforms": ["linkedin"], "breakdown": { "linkedin": 2 } },
      "createdAt": "2026-03-20T09:56:05.000Z"
    }
  ]
}

Credit costs

ActionCost
LinkedIn post (text)1 credit
LinkedIn post (with images)2 credits
Twitter/X post (text)3 credits
Twitter/X post (with images)4 credits
YouTube post1 credit
Analytics fetch2 credits
Credits resetMonthly, on plan renewal

LinkedIn

Current access

Scopes approved: openid profile email w_member_social โ€” covers personal profile identity and publishing posts as a member.

1. Connect a LinkedIn account

Open the OAuth URL in a browser. After the user grants access, they are redirected back and the account is saved to the profile.

GET/api/auth/linkedinStart LinkedIn OAuth

Parameters

NameTypeDescription
profileIdstringQuery param. Which profile to connect the account to. Uses default if omitted.
# Open in browser
https://api.wavpost.com/api/auth/linkedin?profileId=your-profile-id

2. What profile data is returned

After connecting, WavPost fetches the user's identity via the OpenID Connect /v2/userinfo endpoint.

FieldScopeDescription
subopenidUnique LinkedIn member ID
nameprofileFull name
pictureprofileProfile photo URL
emailemailPrimary email address
// Stored internally as:
{
  "id": "abc123",                        // LinkedIn member ID (sub)
  "authorUrn": "urn:li:person:abc123",   // used as post author
  "displayName": "Anshu Raj Singh",
  "picture": "https://media.licdn.com/..."
}

3. Publishing posts

Use the standard POST /api/v1/posts endpoint with "linkedin" in the platforms array.

Text post

curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Excited to share our latest update!",
    "platforms": ["linkedin"]
  }'

Single image post

curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Check out this visual!",
    "platforms": ["linkedin"],
    "mediaUrls": ["https://your-cdn.com/image.jpg"]
  }'

Multi-image post (up to 9)

curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Our product gallery:",
    "platforms": ["linkedin"],
    "mediaUrls": [
      "https://your-cdn.com/img1.jpg",
      "https://your-cdn.com/img2.jpg",
      "https://your-cdn.com/img3.jpg"
    ]
  }'

4. Response

{
  "id": "post-uuid",
  "status": "published",
  "platformResults": {
    "linkedin": {
      "ok": true,
      "platformPostId": "urn:li:share:7123456789"
    }
  }
}

The platformPostId is the LinkedIn post URN โ€” you can use this to reference the post on LinkedIn.

5. Limits & notes

ConstraintValue
Max text length3,000 characters
Max images per post9 (multi-image carousel)
Image formatJPEG, PNG, GIF (public URL required)
Post visibilityPUBLIC (feed distribution)
Post authorPersonal member only (company pages require Community Management API)
Access token expiry60 days (LinkedIn default)

Coming soon โ€” pending LinkedIn approval

  • โ€ข Post as company/organization pages โ€” requires w_organization_social
  • โ€ข Read post analytics (likes, impressions, shares) โ€” requires r_member_social
  • โ€ข Organization follower & visitor analytics โ€” requires rw_organization_admin

Twitter / X

Current access

Uses OAuth 2.0 PKCE. Scopes requested:

tweet.readtweet.writeusers.readoffline.accessmedia.writelike.readlike.writefollows.readfollows.writebookmark.readbookmark.writetweet.moderate.writedm.readdm.write

1. Connect a Twitter / X account

GET/api/auth/twitterStart Twitter OAuth (PKCE)

Parameters

NameTypeDescription
profileIdstringQuery param. Which profile to connect the account to. Uses default if omitted.
# Open in browser
https://api.wavpost.com/api/auth/twitter?profileId=your-profile-id

2. Profile data returned

FieldDescription
idUnique Twitter user ID
nameDisplay name
usernameHandle (e.g. wavpost)
pictureProfile image URL

3. Publishing tweets

Publish tweets with text. Media uploads (photos, videos) are available via the media.write scope.

POST/api/v1/postsPublish a tweet
curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Shipping social features in minutes. ๐Ÿš€",
    "platforms": ["twitter"]
  }'

Response 201

{
  "id": "post-uuid",
  "status": "published",
  "platformResults": {
    "twitter": {
      "ok": true,
      "platformPostId": "1856234567890123456"
    }
  }
}

4. Limits & notes

ConstraintValue
Max text length280 characters
Media uploadPhotos and videos (media.write)
LikesRead and write (like.read, like.write)
FollowsRead and write (follows.read, follows.write)
BookmarksRead and write (bookmark.read, bookmark.write)
Direct MessagesRead and send (dm.read, dm.write)
Hide repliesSupported (tweet.moderate.write)
Access token expiry2 hours (auto-refreshed via offline.access)
Auth methodOAuth 2.0 PKCE
Credit cost3 credits per tweet

YouTube

Current access

Scopes: youtube.upload youtube.readonly openid profile โ€” supports video uploads and community text posts.

1. Connect a YouTube channel

GET/api/auth/youtubeStart YouTube OAuth

Parameters

NameTypeDescription
profileIdstringQuery param. Which profile to connect the account to. Uses default if omitted.
# Open in browser
https://api.wavpost.com/api/auth/youtube?profileId=your-profile-id

2. Profile data returned

FieldDescription
idYouTube channel ID
displayNameChannel name
pictureChannel thumbnail URL

3. Publishing

WavPost auto-detects the post type based on mediaUrls: if a video URL is present it uploads a video; otherwise it creates a community post.

Video upload

Pass a direct video URL in mediaUrls. The first line of text becomes the video title (max 100 chars); the full text becomes the description.

curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "My video title\nFull description goes here.",
    "platforms": ["youtube"],
    "mediaUrls": ["https://your-cdn.com/video.mp4"]
  }'

Community post (text)

Requires 500+ subscribers on the connected channel.

curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Check out our latest update!",
    "platforms": ["youtube"]
  }'

Response 201

// Video upload
{
  "platformResults": {
    "youtube": {
      "ok": true,
      "platformPostId": "https://youtube.com/watch?v=dQw4w9WgXcQ"
    }
  }
}

// Community post
{
  "platformResults": {
    "youtube": {
      "ok": true,
      "platformPostId": "Ug_community_post_id"
    }
  }
}

4. Limits & notes

ConstraintValue
Video formatsmp4, mov, avi, mkv, webm, flv, wmv (public URL required)
Video titleFirst line of text, max 100 characters
Video visibilityPublic
Video categoryPeople & Blogs (categoryId: 22)
Community postsRequires 500+ subscribers
Access token expiry1 hour (refresh token issued automatically)
Auth methodOAuth 2.0 (Google)
Credit cost1 credit per post

Platforms

PlatformIDTextImagesAuth method
LinkedInlinkedinโœ“Up to 9OAuth 2.0
Twitter / Xtwitterโœ“โ€”OAuth 2.0 PKCE
YouTubeyoutubeโœ“โ€”OAuth 2.0

AI Agents

Two machine-readable formats are available for AI agents and OpenAPI toolchains.

# 1. Fetch the API reference for your agent
curl https://api.wavpost.com/llms.txt

# 2. Agent calls the API
curl -X POST https://api.wavpost.com/api/v1/posts \
  -H "Authorization: Bearer sk_live_agent_key" \
  -H "Content-Type: application/json" \
  -d '{"text": "Agent-generated post!", "platforms": ["linkedin"]}'

Errors

All errors return a JSON body with an error field.

{ "error": "Missing or invalid 'text' (string)" }
StatusMeaning
200Success
201Resource created successfully
400Bad request โ€” missing or invalid fields
401Unauthorized โ€” missing, invalid, or revoked token
404Not found โ€” profile or platform does not exist