werepost API docs

API version 2026-08-21

Publish once.
Ship everywhere.

The Werepost API creates immediate and scheduled social posts for one isolated profile, with durable idempotency, status refresh, retry, and deletion controls.

Base URL https://werepost.ai/api/v1

Authentication and scope

Create an API key in Settings → API keys. The complete key is copied and shown once. Store it in a server-side secret manager.

Authorization: Bearer wrp_live_your_key
Content-Type: application/json

Keys are stored as one-way hashes, can be deleted from Settings, and are never accepted for a profile belonging to another Werepost account. Every API-key request is scoped with a profile_id. A key owned by an account can address that account's profiles, but it cannot cross account ownership.

Keep keys off the browser.

Do not put a live API key in front-end JavaScript, a mobile binary, a public repository, a URL, or logs. If a key is exposed, delete it in Settings and create a replacement.

Connection-management endpoints use a signed-in Werepost user access token, not an API key. For a normal server integration, connect destinations in the Werepost app and use the API key only for post operations.

Quickstart

  1. Sign in to Werepost and create or select a profile.
  2. Connect every destination from the profile's Connections page. Finish page or channel selection where required.
  3. Create an API key in Settings and save the one-time value.
  4. Host the video at a fetchable public HTTPS CDN URL.
  5. Send a create request with a unique Idempotency-Key.
curl https://werepost.ai/api/v1/posts \
  --request POST \
  --header "Authorization: Bearer $WEREPOST_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: product-launch-2026-08-21" \
  --data '{
    "profile_id": "4a40c92d-68af-4f10-b1cc-881591b575fd",
    "title": "Product launch",
    "caption": "A first look at what we built.",
    "media_url": "https://cdn.example.com/video/launch.mp4",
    "platforms": ["tiktok", "instagram", "youtube"]
  }'

A new request returns 201. A replay that resolves to an existing post returns 200 with "idempotent": true.

Media and CDN flow

API clients supply media by URL. Werepost validates the URL, prepares the remote media for publishing, and passes the resulting media reference into the selected platform jobs.

RequirementContract
Schemehttps:// only for API clients; embedded URL credentials are rejected.
HostUse a publicly resolvable CDN host. localhost and literal private IP addresses are rejected.
AvailabilityThe object must remain fetchable while the create request is processed. Avoid short-lived signed URLs that may expire during transfer.
LengthThe media URL may be at most 4,096 characters.
Request sizeJSON bodies are limited to 1,000,000 bytes. Do not base64-encode media into JSON.

There is no public multipart upload endpoint in /api/v1. The Werepost web app uploads files to its private media bucket and uses an internal storage://scheduled-videos/… reference. That form is reserved for app-managed uploads; external API clients should use a public HTTPS CDN URL.

Deleting a post removes app-managed private media associated with that record. Werepost does not delete an object from your public CDN.

Create a post

POST/api/v1/posts
FieldTypeDescription
profile_id requiredUUIDOwned Werepost profile.
media_url requiredstringPublic HTTPS CDN URL. video_url is accepted as an alias.
platforms requiredstring[]At least one supported, connected platform key. Duplicates are removed.
captionstringText adapted to the selected platforms, up to 20,000 characters. text and description are accepted aliases.
titlestringInternal title, truncated to 180 characters. Werepost derives a fallback when omitted.
scheduled_atISO-8601Future publication time. Omit for immediate publication. publish_at and post_date are accepted aliases.
platform_optionsobjectOptional per-platform controls described below.

Immediate publishing

Omit scheduled_at. Werepost places the job shortly ahead so the remote media can be prepared safely. “Immediate” is asynchronous: use the returned post ID to check delivery.

Scheduled publishing

{
  "profile_id": "4a40c92d-68af-4f10-b1cc-881591b575fd",
  "caption": "Publishing Tuesday at 16:30 Paris time.",
  "media_url": "https://cdn.example.com/video/tuesday.mp4",
  "platforms": ["facebook", "linkedin"],
  "scheduled_at": "2026-08-25T14:30:00Z"
}

Send a timezone-aware timestamp. UTC with a trailing Z is recommended. A timestamp materially in the past returns 400 invalid_schedule.

Supported platform keys

tiktok, instagram, facebook, youtube, x, linkedin, pinterest, reddit, bluesky, threads, googlebusiness, and discord. Use GET /api/v1/platforms as the live source of truth.

Platform options

Keys under platform_options match the Werepost platform key. Omitted booleans default to false unless stated otherwise.

Three destinations require an option.

pinterest.board_name, reddit.subreddit, and discord.channel_id are mandatory whenever their platform is selected. A missing value returns 400 platform_option_required.

PlatformSupported option fields
tiktokprivacy (default PUBLIC_TO_EVERYONE), disable_comments, disable_duet, disable_stitch, is_brand_content, is_organic_brand_content, is_ai_generated
instagramtype (default REEL), share_to_feed (default true), is_paid_partnership, is_ai_generated
facebooktype (default REEL)
youtubetype (default SHORT), title (100 characters), privacy (default PUBLIC), made_for_kids, contains_synthetic_media, has_paid_product_placement
xis_ai_generated. Caption is capped at 280 characters by Werepost.
linkedindisable_reshare
pinterestboard_name required, title, link, alt_text, is_ai_generated
redditsubreddit required, title, nsfw, flair_id
discordchannel_id required
googlebusinesstopic_type (default STANDARD)
threadstopic_tag
blueskytags as an array of strings
{
  "platforms": ["pinterest", "reddit", "discord"],
  "platform_options": {
    "pinterest": { "board_name": "Product launches", "alt_text": "Product demo" },
    "reddit": { "subreddit": "r/SideProject", "title": "What we shipped" },
    "discord": { "channel_id": "123456789012345678" }
  }
}

Platform policies can impose additional requirements that depend on the connected account or content. Those rejections are returned as safe Werepost errors or appear in the post's error field after refresh.

Idempotency

Every create request requires an Idempotency-Key header containing 8–128 letters, digits, dots, underscores, colons, or dashes.

  • Generate one key for one intended post and reuse it for every retry of that same intent.
  • The key is combined with profile_id, so the same literal key in two different profiles does not identify the same post.
  • A confirmed new post returns 201 and idempotent: false.
  • A replay that already has a publishing job returns 200 and the existing post with idempotent: true.
  • Do not reuse a key with different content. Werepost compares a stable request fingerprint and returns 409 idempotency_conflict when the same key is used for a different request.

If a request times out or the connection drops, retry the exact request with the same key. For 429, 502, or 503, use exponential backoff and preserve the key.

For clients that cannot set headers, idempotency_key in the JSON body is accepted as a compatibility fallback. The header is the production recommendation.

Status and refresh

GET/api/v1/posts/{post_id}

Without a query parameter, this endpoint returns the last state stored by Werepost. Add ?refresh=true to synchronise the publishing job before responding.

curl "https://werepost.ai/api/v1/posts/4cf807c9-5e93-4c98-9077-586b5ce0e20e?refresh=true" \
  --header "Authorization: Bearer $WEREPOST_API_KEY"
pending

Accepted and waiting for the scheduled time or next processing stage.

processing

Media transfer, publication, retry, or review is in progress.

delivered

The publishing job reported success. The destination may still process or review content.

failed

The job reported an error or deletion. Inspect provider_status and error.

provider_status gives the detailed state when available, including UPLOADING, SCHEDULED, PROCESSING, RETRYING, REVIEW, POSTED, ERROR, and DELETED.

Per-platform deliveries

Every post response also includes deliveries, an array with one entry per destination. This is the best field for partial success: the overall post can finish while a specific platform reports its own result.

{
  "platform": "youtube",
  "status": "delivered",
  "external_id": "video_123",
  "external_url": "https://www.youtube.com/watch?v=video_123",
  "error": null,
  "delivered_at": "2026-08-25T14:31:08.000Z"
}

Delivery status is one of pending, uploading, delivered, or failed. external_id and external_url are present only when the destination returns them. Errors and URLs are sanitised before Werepost exposes them.

Polling pattern

Poll the normal endpoint for local state and periodically request refresh=true while a post is pending or processing. Use increasing intervals, stop on delivered or failed, and back off on 429 or dependency errors.

GET/api/v1/posts?profile_id={uuid}&limit=100

Lists posts in descending scheduled order. API keys must include profile_id. limit defaults to 100 and is clamped from 1 to 200.

Retry and delete

POST/api/v1/posts/{post_id}/retry

Retries an existing failed publishing job, immediately refreshes it, and returns { "data": post }. If the original create failed before a publishing job existed, Werepost returns 409 resubmit_required. Resend the original POST /posts request with the same Idempotency-Key.

DELETE/api/v1/posts/{post_id}

Attempts to cancel the job, removes app-managed private media if applicable, and deletes the Werepost post record. It returns:

{
  "deleted": true,
  "id": "4cf807c9-5e93-4c98-9077-586b5ce0e20e"
}
Deletion is not a universal social delete.

A job may already be processing or delivered. Content already published on a destination may remain there; manage it with that platform's controls. Public CDN media also remains under your control.

Connection flow

Connection routes are used by the Werepost web application and require a signed-in user access token. They reject wrp_live_… API keys. This prevents a leaked publishing key from authorising or disconnecting social accounts.

  1. Provision the owned profile with POST /profiles/{profile_id}/provision.
  2. Request a direct platform URL with GET /connect/{platform}?profile_id={uuid}.
  3. Navigate the browser to the returned url. It is a fresh provider authorisation URL; do not store it.
  4. After the browser returns to Werepost, call GET /connections?profile_id={uuid}.
  5. If the connection says needs_channel_selection: true, present its channels and submit one selection.
GET/api/v1/connect/{platform}?profile_id={uuid}&choose_account=true

choose_account defaults to true so providers ask which account to use where supported. The response is { "url": "https://…", "platform": "tiktok" }.

GET/api/v1/connections?profile_id={uuid}

Returns account display data, connection status, and available destinations. Valid status values are connected, action_required, and disconnected.

DELETE/api/v1/connections/{platform}?profile_id={uuid}

Disconnects the platform for this profile. It does not delete existing posts from the destination.

Channel selection

Facebook, YouTube, LinkedIn, and Google Business may return pages, channels, organisations, or locations that require a selection. Use the exact channel id returned in connections[].channels.

POST/api/v1/connections/channel
{
  "profile_id": "4a40c92d-68af-4f10-b1cc-881591b575fd",
  "platform": "youtube",
  "channel_id": "UC123456789"
}

Werepost verifies that the channel belongs to the profile's connection and refreshes the available channel list once if necessary. Publishing returns 409 channel_selection_required until setup is complete.

Endpoint reference

MethodPathCredentialPurpose
GET/api/v1PublicAPI version and implemented routes.
GET/api/v1/healthPublicConfiguration health.
GET/api/v1/platformsPublicSupported platform metadata.
POST/api/v1/profiles/{id}/provisionUser sessionPrepare a profile publishing workspace.
GET/api/v1/connectionsUser sessionList profile connections.
GET/api/v1/connect/{platform}User sessionCreate a direct authorisation URL.
POST/api/v1/connections/channelUser sessionSelect a page or channel.
DELETE/api/v1/connections/{platform}User sessionDisconnect a platform.
POST/api/v1/postsAPI key or user sessionCreate an immediate or scheduled post.
GET/api/v1/postsAPI key or user sessionList posts.
GET/api/v1/posts/{id}API key or user sessionRead or refresh one post.
POST/api/v1/posts/{id}/retryAPI key or user sessionRetry a failed publishing job.
DELETE/api/v1/posts/{id}API key or user sessionCancel and delete a Werepost post.

The authoritative request and response schemas are available as OpenAPI 3.1 JSON.

Errors

Every error is JSON. The request_id also appears in the X-Request-Id response header.

{
  "error": "platform_not_connected",
  "message": "Connect every selected platform before publishing.",
  "details": {
    "missing": ["tiktok"],
    "needs_channel": []
  },
  "request_id": "b4805362-5580-4eb0-b4e3-d95b30235b2b"
}
StatusMeaningTypical codes
400Invalid JSON, field, platform, media URL, schedule, option, or channel selection.invalid_json, platforms_required, media_url_required, invalid_schedule, platform_option_required
401Missing, invalid, revoked, wrong-type, or profile-mismatched credential.unauthorized, user_session_required
404Endpoint, profile, or post not found or not visible to the caller.not_found
409Publishing precondition, idempotency, or resubmission conflict.platform_not_connected, channel_selection_required, idempotency_conflict, resubmit_required
413JSON body exceeds 1,000,000 bytes.payload_too_large
429A publishing dependency applied a rate limit.rate_limited
500Unexpected Werepost error. Public message is intentionally generic.internal_error
502Connection, media, database, or publishing dependency failed.social_provider_error, social_provider_timeout, social_provider_unavailable
503A required service is unavailable or not configured.social_provider_not_configured

For status codes below 500, message describes the problem. For 5xx errors it is deliberately generic; record the request ID. Structured details may identify missing platforms, destinations awaiting channel selection, or safe validation issues.

Production checklist

  • Keep the API key in a server-side secret manager and rotate it after any suspected exposure.
  • Persist the Werepost profile_id and post id; never infer profile ownership client-side.
  • Generate and persist an idempotency key before the first create attempt.
  • Use a durable HTTPS CDN URL and keep it available until the post is accepted.
  • Supply required Pinterest, Reddit, and Discord options when those destinations are selected.
  • Use refresh=true with backoff until a post reaches delivered or failed.
  • Handle 409 resubmit_required by replaying the original create request with the original idempotency key.
  • Log X-Request-Id with your request metadata, but never log Bearer credentials or sensitive authorisation URLs.
  • Expect platform-specific rejection and review. A successful API response means the job was accepted, not that every destination has published it.

Questions or a reproducible failure? Email info@sofuto.uk with the request ID, endpoint, timestamp, and post ID. Do not include your API key.