Wahlu API

Content Items

Create and manage reusable content items.

Content items are the core reusable content entity in Wahlu. Each content item stores per-platform settings (text, media, and options) that define what gets published. Set the platform settings for each platform you want to publish to — leave a platform as null to skip it.

All endpoints use /content-items.

List content items

GET/v1/brands/:brand_id/content-items

Returns content items for a brand. Requires posts:read.

Query parameters

ParameterTypeDescription
pageintegerPage number. Defaults to 1.
limitintegerItems per page. Defaults to 50, max 100.
sort_bystringField to sort by. One of: created_at, updated_at, name. Defaults to created_at.
sort_dirstringSort direction. One of: asc, desc. Defaults to desc.
curl
curl "https://api.wahlu.com/v1/brands/brand_abc123/content-items?limit=10" \
  -H "Authorization: Bearer wahlu_live_your_api_key_here"
Response
{
  "success": true,
  "data": [
    {
      "id": "content_item_xyz789",
      "name": "Product Launch Announcement",
      "brand_id": "brand_abc123",
      "label_ids": ["label_promo"],
      "created_by": "user_abc",
      "thumbnail_timestamp": 0,
      "instagram_settings": {
        "description": "Excited to share our latest update! #launch",
        "media_ids": ["media_img1"],
        "post_type": "GRID_POST"
      },
      "tiktok_settings": null,
      "facebook_settings": null,
      "youtube_settings": null,
      "linkedin_settings": null,
      "created_at": "2026-02-10T09:00:00Z",
      "updated_at": "2026-02-10T09:00:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "has_more": false
  }
}

Get a content item

GET/v1/brands/:brand_id/content-items/:content_item_id

Returns a single content item. Requires posts:read.

Create a content item

POST/v1/brands/:brand_id/content-items

Creates a new content item. Requires posts:write.

Request body

ParameterTypeDescription
name*stringContent item name/title. Max 500 characters.
label_idsstring[]Label IDs to attach. Max 50 items.
thumbnail_timestampnumberVideo thumbnail timestamp in seconds.
instagram_settingsobject | nullInstagram post configuration. See platform settings below.
tiktok_settingsobject | nullTikTok post configuration. See platform settings below.
facebook_settingsobject | nullFacebook post configuration. See platform settings below.
youtube_settingsobject | nullYouTube post configuration. See platform settings below.
linkedin_settingsobject | nullLinkedIn post configuration. See platform settings below.
curl
curl -X POST https://api.wahlu.com/v1/brands/brand_abc123/content-items \
  -H "Authorization: Bearer wahlu_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Product Launch Announcement",
    "instagram_settings": {
      "description": "Excited to share our latest update! #launch",
      "media_ids": ["media_img1"],
      "post_type": "GRID_POST"
    },
    "linkedin_settings": {
      "description": "We are thrilled to announce our latest product launch.",
      "media_ids": ["media_img1"],
      "post_type": "LI_IMAGE",
      "visibility": "PUBLIC"
    }
  }'

Platform settings

Each platform has its own settings object. All fields within a platform settings object are optional — sensible defaults are applied. Set a platform to null (or omit it) to skip publishing to that platform. Media IDs reference files uploaded via the Media API — media must reach completed status before being used.

instagram_settings

ParameterTypeDescription
descriptionstringPost caption.
media_idsstring[]Media IDs to attach. Upload media first via the Media API.
post_typestringOne of: GRID_POST, STORY, REEL. Defaults to REEL.
Example
{
  "description": "Check out our new product! #launch",
  "media_ids": ["media_abc123"],
  "post_type": "REEL"
}

tiktok_settings

ParameterTypeDescription
descriptionstringPost caption.
media_idsstring[]Media IDs to attach.
post_typestringOne of: VIDEO, IMAGE, CAROUSEL.
privacy_levelstring | nullOne of: PUBLIC_TO_EVERYONE, FOLLOWER_OF_CREATOR, MUTUAL_FOLLOW_FRIENDS, SELF_ONLY.
agreed_to_termsbooleanMust be true to publish. Defaults to false.
is_aigcbooleanWhether the content is AI-generated. Defaults to false.
is_commercial_contentbooleanWhether this is commercial content. Defaults to false.
commercial_typesstring[]Required when is_commercial_content is true. Values: YOUR_BRAND, BRANDED_CONTENT.
allow_commentbooleanWhether comments are allowed.
allow_duetbooleanWhether duets are allowed.
allow_stitchbooleanWhether stitches are allowed.
auto_add_musicbooleanWhether to auto-add music.
Example
{
  "description": "New product demo #fyp",
  "media_ids": ["media_video1"],
  "post_type": "VIDEO",
  "privacy_level": "PUBLIC_TO_EVERYONE",
  "agreed_to_terms": true,
  "is_aigc": false
}

facebook_settings

ParameterTypeDescription
descriptionstringPost caption.
media_idsstring[]Media IDs to attach.
post_typestringOne of: FB_POST, FB_STORY, FB_REEL, FB_TEXT. Defaults to FB_REEL.
Example
{
  "description": "Exciting news from us today!",
  "media_ids": ["media_img1", "media_img2"],
  "post_type": "FB_POST"
}

youtube_settings

ParameterTypeDescription
titlestringVideo title.
descriptionstringVideo description.
media_idsstring[]Media IDs to attach.
post_typestringOne of: YT_SHORT, YT_VIDEO. Defaults to YT_SHORT.
privacy_levelstringOne of: PUBLIC, UNLISTED, PRIVATE. Defaults to PUBLIC.
tagsstring[]Video tags for discoverability.
notify_subscribersbooleanWhether to notify subscribers. Defaults to false.
made_for_kidsbooleanWhether the video is made for kids. Defaults to false.
Example
{
  "title": "Product Demo - Quick Overview",
  "description": "A 60-second look at our new features.",
  "media_ids": ["media_video1"],
  "post_type": "YT_SHORT",
  "privacy_level": "PUBLIC",
  "tags": ["product", "demo", "launch"],
  "notify_subscribers": true
}

linkedin_settings

ParameterTypeDescription
descriptionstringPost text.
media_idsstring[]Media IDs to attach.
post_typestringOne of: LI_TEXT, LI_IMAGE, LI_VIDEO, LI_ARTICLE. Defaults to LI_TEXT.
visibilitystringOne of: PUBLIC, CONNECTIONS. Defaults to PUBLIC.
titlestringArticle title. Used with LI_ARTICLE post type.
original_urlstringArticle URL. Used with LI_ARTICLE post type.
Example
{
  "description": "Thrilled to announce our latest product launch.",
  "media_ids": ["media_img1"],
  "post_type": "LI_IMAGE",
  "visibility": "PUBLIC"
}

Full example: create and schedule

This example uploads media, creates a content item for Instagram and LinkedIn, then schedules it via a publish run.

JavaScript
const API = "https://api.wahlu.com/v1";
const headers = {
  Authorization: "Bearer wahlu_live_your_api_key_here",
  "Content-Type": "application/json",
};

// 1. Upload media (see Media API for full details)
const uploadRes = await fetch(`${API}/brands/${brandId}/media/upload-url`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    filename: "product-hero.jpg",
    content_type: "image/jpeg",
  }),
});
const { data: upload } = await uploadRes.json();

await fetch(upload.upload_url, {
  method: "PUT",
  headers: { "Content-Type": "image/jpeg" },
  body: imageBuffer,
});

await fetch(`${API}/brands/${brandId}/media/${upload.id}`, {
  method: "PATCH",
  headers,
  body: JSON.stringify({ status: "ready_for_processing" }),
});

// Wait for media processing to complete
// (poll GET /media/:id until status === "completed")

// 2. Create the content item
const itemRes = await fetch(`${API}/brands/${brandId}/content-items`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    name: "Product Launch",
    instagram_settings: {
      description: "Our new product is here! #launch",
      media_ids: [upload.id],
      post_type: "GRID_POST",
    },
    linkedin_settings: {
      description: "We are excited to announce our latest product.",
      media_ids: [upload.id],
      post_type: "LI_IMAGE",
      visibility: "PUBLIC",
    },
  }),
});
const { data: item } = await itemRes.json();

// 3. Schedule a publish run
await fetch(`${API}/brands/${brandId}/publish-runs`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    content_item_id: item.id,
    scheduled_at: "2026-02-20T09:00:00Z",
    integration_ids: ["int_instagram_123", "int_linkedin_456"],
  }),
});

Update a content item

PATCH/v1/brands/:brand_id/content-items/:content_item_id

Updates a content item. Only provided fields are changed. Requires posts:write.

Delete a content item

DELETE/v1/brands/:brand_id/content-items/:content_item_id

Deletes a content item. Requires posts:write.

curl
curl -X DELETE https://api.wahlu.com/v1/brands/brand_abc123/content-items/content_item_xyz789 \
  -H "Authorization: Bearer wahlu_live_your_api_key_here"