v2.0.0
OpenAPI 3.1.0

Typefully Public API

The Typefully Public API allows you to programmatically manage your social media drafts, schedule posts, and publish content across multiple platforms.

Important: X Automation Compliance

Before building with this API for X automation, please review these critical guidelines:

  • Make sure to adhere to X automation rules and general X rules when scheduling content, otherwise your X account might be banned.
  • If you plan to build an app on X that is not just for you or your company to use, you will need to use the X API with higher rate limits than Typefully's API, which is meant to create personal automations and workflows.

Authentication

All requests require a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Generate your API key from your Typefully settings.

Permissions & Access Levels

API keys inherit the same permissions as the user who created them. Your access to social sets (accounts) determines which API operations you can perform.

Rate Limiting

API requests are rate-limited on a per user and per social set basis. When you exceed the rate limit, you'll receive a 429 Too Many Requests response. All API responses include headers showing your current rate limit status:

User rate limits (applies to all endpoints, per user): X-RateLimit-User-Limit (maximum requests allowed), X-RateLimit-User-Remaining (requests remaining), X-RateLimit-User-Reset (Unix timestamp when limit resets).

Social set rate limits (applies to specific operations like draft creation, per social set): X-RateLimit-SocialSet-Limit, X-RateLimit-SocialSet-Remaining, X-RateLimit-SocialSet-Reset, X-RateLimit-SocialSet-Resource (the resource identifier, e.g., "drafts.create").

Pagination

List endpoints use limit-offset pagination for efficient data retrieval:

  • limit: Maximum items per page (default: 10, max: 50)
  • offset: Number of items to skip (default: 0)

Example request:

GET /v2/social-sets?limit=25&offset=50

Each paginated response includes:

  • results: Array of items for the current page
  • count: Total number of items available
  • limit: Items per page used for this request
  • offset: Current offset value
  • next: URL for the next page (null if on last page)
  • previous: URL for the previous page (null if on first page)
Server:https://api.typefully.com

Production server

Client Libraries

Users

Get details about the currently authenticated user.

Users Operations

Get current user

Retrieve the currently authenticated Typefully user associated with your API Key

Responses
  • application/json
  • application/json
  • application/json
Request Example for get/v2/me
curl https://api.typefully.com/v2/me \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "id": 12345,
  "name": "John Doe",
  "email": "user@example.com",
  "profile_image_url": "https://example.com/avatar.jpg",
  "signup_date": "2024-01-15T10:30:00Z",
  "api_key_label": "My Production Key"
}

Social Sets

List social sets

Retrieve all social sets (accounts) you can access. This includes accounts you own directly and accounts that belong to teams you are a member of.

Query Parameters
  • limit
    Type: integer · Limit
    min:  
    1
    max:  
    50
    nullable

    Maximum number of items to return per page

  • offset
    Type: integer · Offset
    min:  
    0

    Number of items to skip from the beginning

Responses
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets
curl https://api.typefully.com/v2/social-sets \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "results": [
    {
      "id": 12345,
      "username": "elonmusk",
      "name": "Elon Musk",
      "profile_image_url": "https://typefully-user-avatars.s3.amazonaws.com/_generic/account/537/twitter.jpeg",
      "team": {
        "id": "abc123def4567890",
        "name": "Marketing Team"
      }
    }
  ],
  "count": 1,
  "limit": 1,
  "offset": 1,
  "next": "string",
  "previous": "string"
}

Get social set details

Retrieve detailed information about a social set, including every configured social media platform (X, LinkedIn, Mastodon, Threads, Bluesky) with account details and profile information.

Required permission: READ access to the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/
curl https://api.typefully.com/v2/social-sets/1/ \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "id": 12345,
  "username": "elonmusk",
  "name": "Elon Musk",
  "profile_image_url": "https://typefully-user-avatars.s3.amazonaws.com/_generic/account/537/twitter.jpeg",
  "team": {
    "id": "abc123def4567890",
    "name": "Marketing Team"
  },
  "platforms": {
    "x": {
      "platform": "x",
      "username": "string",
      "name": "string",
      "profile_image_url": "string",
      "profile_url": "string"
    },
    "linkedin": {
      "platform": "linkedin",
      "username": "string",
      "name": "string",
      "profile_image_url": "string",
      "profile_url": "string"
    },
    "mastodon": {
      "platform": "mastodon",
      "username": "string",
      "name": "string",
      "profile_image_url": "string",
      "profile_url": "string",
      "followers_count": 1,
      "server": "string"
    },
    "threads": {
      "platform": "threads",
      "username": "string",
      "name": "string",
      "profile_image_url": "string",
      "profile_url": "string"
    },
    "bluesky": {
      "platform": "bluesky",
      "username": "string",
      "name": "string",
      "profile_image_url": "string",
      "profile_url": "string"
    },
    "substack": {
      "platform": "substack",
      "username": "string",
      "name": "string",
      "profile_image_url": "string",
      "profile_url": "string"
    }
  },
  "publishing_quota": {
    "used": 1,
    "remaining": 1,
    "resets_at": "2026-08-02T18:27:28.790Z"
  }
}

Resolve LinkedIn organization from URL

Resolve a LinkedIn company/school URL into organization metadata that can be used to build LinkedIn mention syntax in post text.

This endpoint is resolver-only and is not a general organization search endpoint.

Mention format: @[Company Name](urn:li:organization:123456)

Required permission: READ access to the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Query Parameters
  • organization_url
    Type: string · Organization Url
    required

    Public LinkedIn organization URL (company or school profile).

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/linkedin/organizations/resolve
curl 'https://api.typefully.com/v2/social-sets/1/linkedin/organizations/resolve?organization_url=https%3A%2F%2Fwww.linkedin.com%2Fcompany%2Ftypefullycom' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "id": "86779668",
  "urn": "urn:li:organization:86779668",
  "mention_text": "@[Typefully](urn:li:organization:86779668)",
  "name": "Typefully",
  "vanity_name": "typefullycom",
  "description": "Social media scheduling platform",
  "website": "https://typefully.com",
  "logo_url": "https://media.licdn.com/dms/image/....png",
  "url": "https://www.linkedin.com/company/typefullycom"
}

Analytics

Fetch social-set analytics data. Current coverage: X posts performance metrics by date range.

List analytics posts

Retrieve posts with metrics for a platform in a social set between start_date and end_date (inclusive).

Required permission: READ access to this social set.

Notes:

  • platform is a path parameter (for example: x, linkedin).
  • This endpoint is social-set scoped and platform-scoped to support analytics expansion.
  • Currently, only x is supported.
  • Replies are excluded by default. Set include_replies=true to include them.
  • Pagination defaults to limit=25 with max limit=100.
  • Date ranges larger than 366 days are rejected.
Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • platform
    Type: string · Platform
    required
Query Parameters
  • start_date
    Type: string · Start Date
    required
  • end_date
    Type: string · End Date
    required
  • include_replies
    Type: boolean · Include Replies

    Include X replies in the results. Defaults to false, which returns only non-reply posts.

  • limit
    Type: integer · Limit
    min:  
    1
    max:  
    100
    nullable

    Maximum number of items to return per page

  • offset
    Type: integer · Offset
    min:  
    0

    Number of items to skip from the beginning

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/analytics/{platform}/posts
curl 'https://api.typefully.com/v2/social-sets/1/analytics/{platform}/posts?start_date=&end_date=' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "results": [
    {
      "platform": "x",
      "post_id": "1898022122726803672",
      "created_at": "2026-02-27T12:45:00Z",
      "preview_text": "Hello from Typefully API v2 analytics!",
      "url": "https://x.com/typefully/status/1898022122726803672",
      "draft_id": 12345,
      "metrics": {
        "impressions": 1400,
        "engagement": {
          "total": 83,
          "likes": 48,
          "comments": 3,
          "shares": 12,
          "quotes": 4,
          "saves": 2,
          "profile_clicks": 9,
          "link_clicks": 5
        }
      }
    }
  ],
  "limit": 25,
  "offset": 0,
  "next": null,
  "previous": null
}

Get followers analytics

Retrieve daily follower counts for a platform in a social set between start_date and end_date (inclusive).

Required permission: READ access to this social set.

Notes:

  • platform is a path parameter (for example: x, linkedin).
  • This endpoint is social-set scoped and platform-scoped to support analytics expansion.
  • Currently, only x is supported.
  • Returns a totals-only daily follower series with the latest in-range follower count.
  • If start_date and end_date are omitted, defaults to the last 30 days.
  • Date ranges larger than 366 days are rejected.
Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • platform
    Type: string · Platform
    required
Query Parameters
  • start_date
    Type: string · Start Datenullable

    Start date for the follower series (YYYY-MM-DD). Defaults to 29 days before end_date, or before today when end_date is omitted.

  • end_date
    Type: string · End Datenullable

    End date for the follower series (YYYY-MM-DD). Defaults to today in the social set's timezone.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/analytics/{platform}/followers
curl 'https://api.typefully.com/v2/social-sets/1/analytics/{platform}/followers' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "platform": "x",
  "current_followers_count": 1450,
  "data": [
    {
      "date": "2026-02-25",
      "followers_count": 1400
    },
    {
      "date": "2026-02-26",
      "followers_count": 1425
    },
    {
      "date": "2026-02-27",
      "followers_count": 1450
    }
  ]
}

Drafts

Get all your drafts and make changes to them.

Comment-thread markers in draft text

If a draft has comment threads, draft-detail GET and PATCH responses include Typefully comment-thread markers in posts[*].text and, for X Articles, in platforms.x_article.content_markdown. Treat these markers as structural anchor metadata, not user text. Preserve them exactly when editing so a GET → modify → PATCH round-trip keeps comment anchors attached.

When you PATCH /drafts/{id}, the server compares submitted markers against the comment threads stored on the draft:

  • Markers match → request accepted; threads stay anchored to whatever text now sits inside the marker tags.
  • Marker missing (server has it, you didn't send it) → 409 COMMENTS_MARKER_MISMATCH with a per-platform missing[] list. To deliberately drop the affected threads, retry with force_overwrite_comments: true — the threads are resolved server-side and their anchors stripped.
  • Unknown marker id (you sent an id not on this draft / platform / post) → 400 COMMENTS_MARKER_UNKNOWN_ID. No force escape — fix the request.
  • Malformed marker tag400 COMMENTS_MARKER_MALFORMED with subcode in details (unbalanced, bad_uuid, bad_attr, bad_position, empty_span, mid_mention, depth_exceeded, count_exceeded).

Constraints on the marker grammar:

  • id must be a lowercase UUID. No other attributes are accepted.
  • Markers may be nested up to 16 levels deep, with at most 1000 markers per post.
  • Self-closing <typ:comment-thread id="…"/> must sit at paragraph start.
  • Span markers (<typ:comment-thread id="…">…</typ:comment-thread>) must wrap at least one character.
  • Span markers may not start or end inside a LinkedIn mention (@[Name](urn:li:organization:ID) or @[Name](urn:li:person:ID)); mentions are atomic — the marker either contains the entire mention substring or stays outside it.

Recommended edit flow:

  1. GET /v2/social-sets/{social_set_id}/drafts/{draft_id} without exclude_comment_markers.
  2. Modify draft text while preserving all comment-thread markers.
  3. PATCH /v2/social-sets/{social_set_id}/drafts/{draft_id} with force_overwrite_comments: false (the default).

Plain text for read-only flows

For display surfaces that don't round-trip — LLM context windows, CSV exports, dashboards — pass ?exclude_comment_markers=true on GET /drafts/{id} or PATCH /drafts/{id}. The response renders draft text without marker tags. The flag is render-only and does NOT affect server-side validation on the request body. Content returned with this flag set should not be PATCHed back unless you intend to resolve or remove comment anchors.

List drafts

Retrieve all drafts for a specific social set with optional filtering and sorting. Drafts are ordered by last edited date (most recent first) by default.

Required permission: READ access to this social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Query Parameters
  • status
    Type: string · Statusenumnullable
    values
    • draft
    • published
    • scheduled
    • error
    • publishing
  • tag
    Type: array string[] | null · Tagnullable
  • order_by
    Type: string · DraftOrderByenum

    Allowed order_by fields for draft listing - prevents SQL injection

    values
    • created_at
    • -created_at
    • updated_at
    • -updated_at
    • scheduled_date
    • -scheduled_date
    • published_at
    • -published_at
  • limit
    Type: integer · Limit
    min:  
    1
    max:  
    50
    nullable

    Maximum number of items to return per page

  • offset
    Type: integer · Offset
    min:  
    0

    Number of items to skip from the beginning

Responses
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/drafts
curl https://api.typefully.com/v2/social-sets/1/drafts \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "results": [
    {
      "id": 12345,
      "preview": "Hello world",
      "scheduled_date": "2025-01-20T14:00:00Z",
      "draft_title": "My launch thread",
      "mastodon_post_enabled": true,
      "social_set_id": 67890,
      "share_url": "https://typefully.com/share/abc123",
      "private_url": "https://typefully.com/?d=12345&a=67890",
      "status": "string",
      "tags": [
        "marketing",
        "product"
      ],
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-16T09:15:00Z",
      "published_at": "2025-01-20T14:00:05Z",
      "mastodon_post_published_at": "2025-01-20T14:00:05Z",
      "linkedin_post_published_at": "2025-01-20T14:00:05Z",
      "threads_post_published_at": "2025-01-20T14:00:05Z",
      "bluesky_post_published_at": "2025-01-20T14:00:05Z",
      "substack_post_published_at": "2025-01-20T14:00:05Z",
      "x_post_published_at": "2025-01-20T14:00:05Z",
      "x_post_enabled": true,
      "linkedin_post_enabled": true,
      "threads_post_enabled": true,
      "bluesky_post_enabled": true,
      "substack_post_enabled": true,
      "x_published_url": "https://x.com/username/status/1234567890",
      "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
      "mastodon_published_url": "https://mastodon.social/@username/1234567890",
      "threads_published_url": "https://www.threads.net/@username/post/ABC123",
      "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
      "substack_published_url": "https://substack.com/@username/note/c-123456789"
    }
  ],
  "count": 1,
  "limit": 1,
  "offset": 1,
  "next": "string",
  "previous": "string"
}

Create draft

Create a new draft with content for one or more social media platforms. The draft can be saved as a draft, scheduled for later publishing, or published immediately.

Account-level settings: This endpoint automatically applies the following account-level settings if enabled: Auto-Retweet, Auto-Plug, and Natural Posting Time.

Required permission: WRITE access to create drafts. PUBLISH access is required to schedule or publish immediately.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Body·
required
application/json

Request schema for creating a draft

  • platforms
    Type: object ·
    required

    Platform configurations for each social media platform

  • draft_title
    Type: string · Draft Title
    max length:  
    512
    nullable

    Human-readable title for the draft. This is for internal organization only and is not posted to social media.

  • scratchpad_text
    Type: string · Scratchpad Textnullable

    Plain text scratchpad notes for the draft. Formatting is stripped.

  • tags
    Type: array string[] · Tags …10

    List of tag slugs (not names) associated with this draft. Use the /tags endpoint to get available tags with their slugs. Tags must already exist in the social set.

  • share
    Type: boolean · Share

    Whether to generate a public share URL for this draft. When true, anyone with the URL can view the draft content.

  • publish_at
    nullable

    When to publish the draft. Options: "now" to publish immediately, "next-free-slot" to schedule to your next available posting slot, or an ISO 8601 datetime string with timezone for a specific future time (e.g., '2025-01-20T14:00:00Z' for UTC or '2025-01-20T09:00:00-05:00' for EST). Timezone is required. Omit to save as a draft.

    Note on "now": publishing runs asynchronously. The response returns immediately with publish_state="in_progress" while status stays "draft" and published_at/*_published_url are still null. This is the expected success response, not a failure. Poll GET /drafts/{id} until publish_state is "finished", then read status and the per-platform published URLs for the outcome.

    • Type: string · Publish AtFormat: date-time

      When to publish the draft. Options: "now" to publish immediately, "next-free-slot" to schedule to your next available posting slot, or an ISO 8601 datetime string with timezone for a specific future time (e.g., '2025-01-20T14:00:00Z' for UTC or '2025-01-20T09:00:00-05:00' for EST). Timezone is required. Omit to save as a draft.

      Note on "now": publishing runs asynchronously. The response returns immediately with publish_state="in_progress" while status stays "draft" and published_at/*_published_url are still null. This is the expected success response, not a failure. Poll GET /drafts/{id} until publish_state is "finished", then read status and the per-platform published URLs for the outcome.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for post/v2/social-sets/{social_set_id}/drafts
curl https://api.typefully.com/v2/social-sets/1/drafts \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "platforms": {
    "x": {
      "enabled": true,
      "posts": [
        {
          "text": "1/ Excited to share our latest product update!"
        },
        {
          "text": "2/ We'\''ve added new features based on your feedback."
        },
        {
          "text": "3/ Try it out and let us know what you think!"
        }
      ]
    },
    "linkedin": {
      "enabled": true,
      "posts": [
        {
          "text": "Excited to share our latest product update! We'\''ve added new features based on your feedback. Try it out and let us know what you think!"
        }
      ]
    }
  },
  "share": true
}'
{
  "id": 12345,
  "social_set_id": 67890,
  "status": "draft",
  "publish_state": null,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-16T09:15:00Z",
  "scheduled_date": "2025-01-20T14:00:00Z",
  "published_at": "2025-01-20T14:00:05Z",
  "draft_title": "Weekly Newsletter",
  "tags": [
    "marketing",
    "product"
  ],
  "preview": "Excited to announce our new feature! 🚀",
  "share_url": "https://typefully.com/share/abc123",
  "private_url": "https://typefully.com/?d=12345&a=67890",
  "platforms": {
    "x": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "quote_post_url": "string",
          "subscribers_only": true,
          "paid_partnership": true,
          "made_with_ai": true
        }
      ],
      "settings": {
        "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
        "community_id": "string",
        "share_with_followers": true
      }
    },
    "linkedin": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "linkedin_reshare_urn": "string",
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "mastodon": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ]
        }
      ],
      "settings": {}
    },
    "threads": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "bluesky": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "substack": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "x_article": {
      "content_markdown": "string",
      "cover_media_id": "string"
    }
  },
  "x_published_url": "https://x.com/username/status/1234567890",
  "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
  "mastodon_published_url": "https://mastodon.social/@username/1234567890",
  "threads_published_url": "https://www.threads.net/@username/post/ABC123",
  "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
  "substack_published_url": "https://substack.com/@username/note/c-123456789",
  "x_article_published_url": "https://x.com/i/article/1234567890",
  "x_post_published_at": "2025-01-20T14:00:05Z",
  "linkedin_post_published_at": "2025-01-20T14:00:08Z",
  "mastodon_post_published_at": "2025-01-20T14:00:10Z",
  "threads_post_published_at": "2025-01-20T14:00:12Z",
  "bluesky_post_published_at": "2025-01-20T14:00:15Z",
  "substack_post_published_at": "2025-01-20T14:00:15Z",
  "x_article_published_at": "2025-01-20T14:00:15Z",
  "scratchpad_text": "line 1\nline 2\n\nline 4"
}

Get draft

Retrieve a specific draft by ID, including its content for all configured platforms, status, and scheduling information.

If the draft has comment threads, the response includes Typefully comment-thread markers in posts[*].text and, for X Articles, in platforms.x_article.content_markdown. These markers are structural anchor metadata for GET → modify → PATCH round-trips; preserve them exactly when editing.

For read-only display/export, pass ?exclude_comment_markers=true to render draft text without markers. Content returned with that flag set should not be PATCHed back unless you intend to resolve or remove comment anchors.

Required permission: READ access to this social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

Query Parameters
  • exclude_comment_markers
    Type: boolean · Exclude Comment Markers

    When true, render posts[*].text as plain user-visible text without <typ:comment-thread> markers, and render X Article content_markdown without comment markers. Use only for read-only flows (LLM context windows, exports). The default (false) emits markers so a round-trip back to PATCH preserves comment anchors.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/drafts/{draft_id}
curl https://api.typefully.com/v2/social-sets/1/drafts/1 \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "id": 12345,
  "social_set_id": 67890,
  "status": "draft",
  "publish_state": null,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-16T09:15:00Z",
  "scheduled_date": "2025-01-20T14:00:00Z",
  "published_at": "2025-01-20T14:00:05Z",
  "draft_title": "Weekly Newsletter",
  "tags": [
    "marketing",
    "product"
  ],
  "preview": "Excited to announce our new feature! 🚀",
  "share_url": "https://typefully.com/share/abc123",
  "private_url": "https://typefully.com/?d=12345&a=67890",
  "platforms": {
    "x": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "quote_post_url": "string",
          "subscribers_only": true,
          "paid_partnership": true,
          "made_with_ai": true
        }
      ],
      "settings": {
        "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
        "community_id": "string",
        "share_with_followers": true
      }
    },
    "linkedin": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "linkedin_reshare_urn": "string",
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "mastodon": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ]
        }
      ],
      "settings": {}
    },
    "threads": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "bluesky": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "substack": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "x_article": {
      "content_markdown": "string",
      "cover_media_id": "string"
    }
  },
  "x_published_url": "https://x.com/username/status/1234567890",
  "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
  "mastodon_published_url": "https://mastodon.social/@username/1234567890",
  "threads_published_url": "https://www.threads.net/@username/post/ABC123",
  "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
  "substack_published_url": "https://substack.com/@username/note/c-123456789",
  "x_article_published_url": "https://x.com/i/article/1234567890",
  "x_post_published_at": "2025-01-20T14:00:05Z",
  "linkedin_post_published_at": "2025-01-20T14:00:08Z",
  "mastodon_post_published_at": "2025-01-20T14:00:10Z",
  "threads_post_published_at": "2025-01-20T14:00:12Z",
  "bluesky_post_published_at": "2025-01-20T14:00:15Z",
  "substack_post_published_at": "2025-01-20T14:00:15Z",
  "x_article_published_at": "2025-01-20T14:00:15Z",
  "scratchpad_text": "line 1\nline 2\n\nline 4"
}

Update draft

Update an existing draft with partial update semantics. Only provided fields are updated; omitted fields remain unchanged. Scheduled drafts require publish access to edit.

Note about Comment-thread markers

If the draft has comment threads, submitted posts[*].text and X Article platforms.x_article.content_markdown must preserve the Typefully comment-thread markers received from GET /drafts/{id}. Validation is platform-level: every comment thread anchored on a platform must appear somewhere in that platform's submitted text.

Recommended edit flow: GET the draft without exclude_comment_markers, modify text while preserving markers exactly, then PATCH with force_overwrite_comments: false (the default).

  • 409 COMMENTS_MARKER_MISMATCH will be thrown if an expected comment thread marker is missing unless "force_overwrite_comments": true is set, in which case the affected threads are resolved server-side.
  • 400 COMMENTS_MARKER_UNKNOWN_ID will be thrown if you submit an id that doesn't exist on this draft. - 400 COMMENTS_MARKER_MALFORMED will be thrown if the marker tag is malformed (bad UUID, unbalanced, attribute violations, etc.).

Pass ?exclude_comment_markers=true to render the response text without markers (read-only / display rendering — does NOT skip server-side marker validation on the request body). Do not PATCH content returned with that flag unless you intend to resolve or remove comment anchors.

Required permission: WRITE access to edit drafts. PUBLISH access is required to edit scheduled drafts, schedule, or publish.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

Query Parameters
  • exclude_comment_markers
    Type: boolean · Exclude Comment Markers

    Render the response's posts[*].text as plain text without <typ:comment-thread> markers, and render X Article content_markdown without comment markers. Render-only — does not affect request-body validation.

Body·
required
application/json

Request schema for updating a draft (partial updates supported)

  • platforms
    Type: object · nullable

    Platform configurations. Only provided platforms will be updated; omitted platforms remain unchanged.

    Schema for all platform configurations

  • draft_title
    Type: string · Draft Title
    max length:  
    512
    nullable

    Human-readable title for the draft. This is for internal organization only and is not posted to social media. Omit to keep unchanged.

  • scratchpad_text
    Type: string · Scratchpad Textnullable

    Plain text scratchpad notes for the draft. Formatting is stripped. Omit to keep unchanged.

  • tags
    Type: array string[] | null · Tags …10nullable

    List of tag slugs (not names) associated with this draft. Use the /tags endpoint to get available tags with their slugs. Tags must already exist in the social set. Omit to keep unchanged.

  • share
    Type: boolean · Sharenullable

    Whether to generate a public share URL. Omit to keep unchanged.

  • publish_at
    nullable

    When to publish the draft. Options: "now" to publish immediately, "next-free-slot" to schedule to your next available posting slot, or an ISO 8601 datetime string with timezone for a specific future time (e.g., '2025-01-20T14:00:00Z' for UTC or '2025-01-20T09:00:00-05:00' for EST). Timezone is required. Omit to keep unchanged.

    Note on "now": publishing runs asynchronously. The response returns immediately with publish_state="in_progress" while status is unchanged. Poll GET /drafts/{id} until publish_state is "finished", then read status and the per-platform published URLs for the outcome.

    • Type: string · Publish AtFormat: date-time

      When to publish the draft. Options: "now" to publish immediately, "next-free-slot" to schedule to your next available posting slot, or an ISO 8601 datetime string with timezone for a specific future time (e.g., '2025-01-20T14:00:00Z' for UTC or '2025-01-20T09:00:00-05:00' for EST). Timezone is required. Omit to keep unchanged.

      Note on "now": publishing runs asynchronously. The response returns immediately with publish_state="in_progress" while status is unchanged. Poll GET /drafts/{id} until publish_state is "finished", then read status and the per-platform published URLs for the outcome.

  • force_overwrite_comments
    Type: boolean · Force Overwrite Comments

    Comment-thread anchor preservation toggle. When false (the default), submitting posts[*].text or X Article content_markdown whose <typ:comment-thread> markers don't match the draft's stored comment threads is rejected with 409 COMMENTS_MARKER_MISMATCH. Recover by re-including the missing markers and retrying. When true, missing markers are accepted: the affected comment threads are resolved server-side and their anchors are stripped from the draft. Markers that ARE submitted continue to be validated and re-anchored normally. StrictBool: only the JSON literals true/false are accepted (not "true" strings).

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for patch/v2/social-sets/{social_set_id}/drafts/{draft_id}
curl https://api.typefully.com/v2/social-sets/1/drafts/1 \
  --request PATCH \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "platforms": {
    "x": {
      "enabled": true,
      "posts": [
        {
          "text": "Updated post content!"
        }
      ]
    }
  }
}'
{
  "id": 12345,
  "social_set_id": 67890,
  "status": "draft",
  "publish_state": null,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-16T09:15:00Z",
  "scheduled_date": "2025-01-20T14:00:00Z",
  "published_at": "2025-01-20T14:00:05Z",
  "draft_title": "Weekly Newsletter",
  "tags": [
    "marketing",
    "product"
  ],
  "preview": "Excited to announce our new feature! 🚀",
  "share_url": "https://typefully.com/share/abc123",
  "private_url": "https://typefully.com/?d=12345&a=67890",
  "platforms": {
    "x": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "quote_post_url": "string",
          "subscribers_only": true,
          "paid_partnership": true,
          "made_with_ai": true
        }
      ],
      "settings": {
        "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
        "community_id": "string",
        "share_with_followers": true
      }
    },
    "linkedin": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "linkedin_reshare_urn": "string",
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "mastodon": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ]
        }
      ],
      "settings": {}
    },
    "threads": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "bluesky": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "substack": {
      "enabled": true,
      "posts": [
        {
          "text": "string",
          "media_ids": [
            "string"
          ],
          "hide_link_preview": false
        }
      ],
      "settings": {}
    },
    "x_article": {
      "content_markdown": "string",
      "cover_media_id": "string"
    }
  },
  "x_published_url": "https://x.com/username/status/1234567890",
  "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
  "mastodon_published_url": "https://mastodon.social/@username/1234567890",
  "threads_published_url": "https://www.threads.net/@username/post/ABC123",
  "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
  "substack_published_url": "https://substack.com/@username/note/c-123456789",
  "x_article_published_url": "https://x.com/i/article/1234567890",
  "x_post_published_at": "2025-01-20T14:00:05Z",
  "linkedin_post_published_at": "2025-01-20T14:00:08Z",
  "mastodon_post_published_at": "2025-01-20T14:00:10Z",
  "threads_post_published_at": "2025-01-20T14:00:12Z",
  "bluesky_post_published_at": "2025-01-20T14:00:15Z",
  "substack_post_published_at": "2025-01-20T14:00:15Z",
  "x_article_published_at": "2025-01-20T14:00:15Z",
  "scratchpad_text": "line 1\nline 2\n\nline 4"
}

Delete draft

Delete a draft. Requires WRITE access. You can delete your own drafts in any status (DRAFT, ERROR, SCHEDULED, PUBLISHED, PUBLISHING) with WRITE access. Drafts created by other users also require WRITE access to delete.

Required permission: WRITE access to this social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

Responses
  • 204

    No Content

  • application/json
  • application/json
  • application/json
Request Example for delete/v2/social-sets/{social_set_id}/drafts/{draft_id}
curl https://api.typefully.com/v2/social-sets/1/drafts/1 \
  --request DELETE \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
No Body

Comments

List, create, edit, resolve, and delete comment threads on a draft — the same threads collaborators see in the webapp.

A comment thread is the anchored discussion container. A comment is one message inside that thread. The canonical collection path is /v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads.

Notable behaviors

  • Listing. GET /comment-threads defaults to status=unresolved, so resolved threads are omitted unless you request status=resolved or status=all.
  • Anchoring. A new thread anchors to a substring (selected_text + occurrence). Post-platform comments target a post in posts[]; X Article comments target rendered article text. The thread response carries the original selected_text snapshot — it does not change if the draft is edited later, and it may be null for older whole-post threads.
  • X Article matching. For platform: "x_article", selected_text matches visible article text in document order. Markdown syntax, media tags, and X post embed tags are ignored. X Article text comments cannot overlap existing stored X Article anchors; overlapping selections return 400 VALIDATION_ERROR.
  • LinkedIn mentions appear in posts[*].text as @[Name](urn:li:organization:ID) or @[Name](urn:li:person:ID). A mention is indivisible, so selected_text must either contain the entire mention substring or stay outside it.
  • Resolution is one-way. There is no unresolve endpoint.
  • Adding a comment to a resolved thread, or to a thread on an auto-synced platform, returns 409 CONFLICT.
  • Comment threads cannot be created on auto-synced platforms (autosync overwrites the post's content and would orphan the thread).
  • Editing a comment is restricted to its author — even users with WRITE access on the social set cannot edit someone else's comment.
  • Root-comment delete cascades. Deleting the first (oldest) comment in a thread deletes the entire thread. Use DELETE /comment-threads/{id} to delete a thread explicitly.
  • Mentioning users in comment bodies via API v2 is not supported. Editing a comment via API v2 clears any mentions the comment previously held.
  • Hard limits. 5,000 comment threads per draft and 500 comments per thread.

List comment threads on a draft

Retrieve comment threads attached to a draft, ordered by creation time. Each thread includes the original selected_text snapshot and the full ordered list of comments.

By default this endpoint returns only unresolved threads (status=unresolved). Use status=resolved to list resolved threads or status=all to list both unresolved and resolved threads. Example: GET /v2/social-sets/4/drafts/12/comment-threads?status=all&limit=50.

Required permission: READ access to this social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

Query Parameters
  • platform
    Type: string · Platformenumnullable

    Optional platform filter.

    values
    • x
    • linkedin
    • mastodon
    • threads
    • bluesky
    • substack
    • x_article
  • status
    Type: string · Statusenum

    Resolution filter. Defaults to unresolved, so resolved threads are omitted unless you request resolved or all.

    values
    • unresolved
    • resolved
    • all
  • limit
    Type: integer · Limit
    min:  
    1
    max:  
    50

    Integer numbers.

  • offset
    Type: integer · Offset
    min:  
    0

    Integer numbers.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads
curl https://api.typefully.com/v2/social-sets/1/drafts/1/comment-threads \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "results": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "draft_id": 1,
      "platform": "x",
      "status": "unresolved",
      "selected_text": "string",
      "comments": [
        {
          "id": "123e4567-e89b-12d3-a456-426614174000",
          "text": "string",
          "created_at": "2026-08-02T18:27:28.790Z",
          "user": {
            "id": 1,
            "name": "string",
            "profile_image_url": "string"
          }
        }
      ]
    }
  ],
  "count": 1,
  "limit": 1,
  "offset": 1,
  "next": "string",
  "previous": "string"
}

Create a comment thread

Create a new comment thread on a draft. A comment thread is the anchored discussion container; comments are the messages inside the thread.

For post platforms (x, linkedin, mastodon, threads, bluesky, substack), provide post_index and anchor to a substring of that post's visible text using selected_text. Use occurrence to disambiguate when the same substring appears more than once; omit it to anchor on the first match.

For X Articles, send platform: "x_article" and omit post_index (or use 0). selected_text matches rendered article text in document order; Markdown syntax, media tags, and X post embed tags are ignored. X Article text comments cannot overlap existing stored X Article anchors; overlapping selections return 400 VALIDATION_ERROR.

LinkedIn mentions appear in posts[*].text as @[Name](urn:li:organization:ID) or @[Name](urn:li:person:ID). A mention is indivisible — selected_text must either contain the entire mention substring or stay outside it.

Required permission: WRITE access to this social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

Body·Payload
required
application/json
  • Create a new comment thread anchored on a span of a draft post.

    • post_index
      Type: integer · Post Index
      min:  
      0
      required

      Zero-based index of the target post within the platform's posts array.

    • selected_text
      Type: string · Selected Text
      min length:  
      1
      max length:  
      50000
      required

      Exact substring (codepoint-equal) of the target platform's visible flat text the comment thread is anchored to. Copy verbatim from the GET response.

      LinkedIn mentions appear inside posts[*].text as @[Name](urn:li:organization:ID) or @[Name](urn:li:person:ID). Mentions are indivisible — selected_text may either include the entire mention substring or stay outside it. A selection that starts or ends in the middle of a mention is rejected with 400 VALIDATION_ERROR.

    • text
      Type: string · Text
      min length:  
      1
      max length:  
      10000
      required

      Plain-text comment body. The server derives the stored rich_text from this.

    • platform
      Type: string · Platformenumnullable

      Required when the draft has multiple commentable platforms; otherwise resolves to the source platform.

      values
      • x
      • linkedin
      • mastodon
      • threads
      • bluesky
      • substack
    • occurrence
      Type: integer · Occurrence
      min:  
      0
      max:  
      10000

      Zero-based occurrence of selected_text within the post when the same substring appears multiple times.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for post/v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads
curl https://api.typefully.com/v2/social-sets/1/drafts/1/comment-threads \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "post_index": 0,
  "platform": "x",
  "selected_text": "",
  "occurrence": 0,
  "text": ""
}'
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "draft_id": 1,
  "platform": "x",
  "status": "unresolved",
  "selected_text": "string",
  "comments": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "text": "string",
      "created_at": "2026-08-02T18:27:28.790Z",
      "user": {
        "id": 1,
        "name": "string",
        "profile_image_url": "string"
      }
    }
  ]
}

Add a comment to an existing comment thread

Append a comment to an existing comment thread. Returns the full updated thread.

Required permission: WRITE access to this social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

  • comment_thread_id
    Type: string · Comment Thread IdFormat: uuid
    required
Body·
required
application/json

Add a comment to an existing comment thread.

  • text
    Type: string · Text
    min length:  
    1
    max length:  
    10000
    required

    Plain-text comment body. The server derives the stored rich_text from this.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for post/v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads/{comment_thread_id}/comments
curl https://api.typefully.com/v2/social-sets/1/drafts/1/comment-threads/123e4567-e89b-12d3-a456-426614174000/comments \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "text": ""
}'
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "draft_id": 1,
  "platform": "x",
  "status": "unresolved",
  "selected_text": "string",
  "comments": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "text": "string",
      "created_at": "2026-08-02T18:27:28.790Z",
      "user": {
        "id": 1,
        "name": "string",
        "profile_image_url": "string"
      }
    }
  ]
}

Resolve a comment thread

Resolves the comment thread and removes the corresponding comment markers from the text.

Required permission: Either authorship of the comment thread or WRITE access on the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

  • comment_thread_id
    Type: string · Comment Thread IdFormat: uuid
    required
Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for post/v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads/{comment_thread_id}/resolve
curl https://api.typefully.com/v2/social-sets/1/drafts/1/comment-threads/123e4567-e89b-12d3-a456-426614174000/resolve \
  --request POST \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "draft_id": 1,
  "platform": "x",
  "status": "unresolved",
  "selected_text": "string",
  "comments": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "text": "string",
      "created_at": "2026-08-02T18:27:28.790Z",
      "user": {
        "id": 1,
        "name": "string",
        "profile_image_url": "string"
      }
    }
  ]
}

Update a comment's text

Update the plain-text body of a single comment. Returns the full updated thread.

Required permission: Authorship of the comment.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

  • comment_thread_id
    Type: string · Comment Thread IdFormat: uuid
    required
  • comment_id
    Type: string · Comment IdFormat: uuid
    required
Body·
required
application/json

Update the text body of a single comment within a comment thread.

  • text
    Type: string · Text
    min length:  
    1
    max length:  
    10000
    required

    Plain-text comment body. The server derives the stored rich_text from this.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for patch/v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads/{comment_thread_id}/comments/{comment_id}
curl https://api.typefully.com/v2/social-sets/1/drafts/1/comment-threads/123e4567-e89b-12d3-a456-426614174000/comments/123e4567-e89b-12d3-a456-426614174000 \
  --request PATCH \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "text": ""
}'
{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "draft_id": 1,
  "platform": "x",
  "status": "unresolved",
  "selected_text": "string",
  "comments": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "text": "string",
      "created_at": "2026-08-02T18:27:28.790Z",
      "user": {
        "id": 1,
        "name": "string",
        "profile_image_url": "string"
      }
    }
  ]
}

Delete a comment

Deletes a comment from a comment thread. If comment_id identifies the root (oldest) comment, the entire thread is deleted and the corresponding comment markers are removed from the text.

Required permission: Authorship of the comment or WRITE access on the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

  • comment_thread_id
    Type: string · Comment Thread IdFormat: uuid
    required
  • comment_id
    Type: string · Comment IdFormat: uuid
    required
Responses
  • 204

    No Content

  • application/json
  • application/json
  • application/json
  • application/json
Request Example for delete/v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads/{comment_thread_id}/comments/{comment_id}
curl https://api.typefully.com/v2/social-sets/1/drafts/1/comment-threads/123e4567-e89b-12d3-a456-426614174000/comments/123e4567-e89b-12d3-a456-426614174000 \
  --request DELETE \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
No Body

Delete a comment thread

Deletes the comment thread along with all its comments and removes the corresponding comment markers from the text.

Required permission: Authorship of the comment thread or WRITE access on the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • draft_id
    Type: integer · Draft Id
    required

    Integer numbers.

  • comment_thread_id
    Type: string · Comment Thread IdFormat: uuid
    required
Responses
  • 204

    No Content

  • application/json
  • application/json
  • application/json
  • application/json
Request Example for delete/v2/social-sets/{social_set_id}/drafts/{draft_id}/comment-threads/{comment_thread_id}
curl https://api.typefully.com/v2/social-sets/1/drafts/1/comment-threads/123e4567-e89b-12d3-a456-426614174000 \
  --request DELETE \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
No Body

Queue

Inspect the queue (free slots + scheduled drafts) and manage the queue schedule for a social set.

  • Use GET /v2/social-sets/{social_set_id}/queue for date-range queue views.
  • Use GET/PUT /v2/social-sets/{social_set_id}/queue/schedule to read/replace slot rules.

Get queue schedule

Retrieve the queue schedule rules for a social set.

Required permission: READ access to this social set.

Behavior:

  • If the schedule row does not exist yet, it is created with defaults.
Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/queue/schedule
curl https://api.typefully.com/v2/social-sets/1/queue/schedule \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "social_set_id": 123,
  "timezone": "America/New_York",
  "rules": [
    {
      "h": 12,
      "m": 0,
      "days": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri"
      ]
    },
    {
      "h": 17,
      "m": 0,
      "days": [
        "mon",
        "tue",
        "wed",
        "thu",
        "fri"
      ]
    }
  ]
}

Replace queue schedule

Replace the queue schedule rules for a social set.

Required permission: ADMIN access to this social set. Semantics: full replacement (atomic).

Rule validation:

  • h in 0..23, m in 0..59
  • days values are one of: mon,tue,wed,thu,fri,sat,sun
  • Duplicate day+time combinations are rejected

Note: rules=[] is allowed and represents an empty schedule.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Body·
required
application/json

Request schema for fully replacing queue schedule rules.

  • rules
    Type: array object[] · Rules
    required

    New schedule rules (full replacement).

    Single schedule rule (local time + days of week).

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for put/v2/social-sets/{social_set_id}/queue/schedule
curl https://api.typefully.com/v2/social-sets/1/queue/schedule \
  --request PUT \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "rules": [
    {
      "h": 9,
      "m": 30,
      "days": [
        "mon",
        "wed",
        "fri"
      ]
    }
  ]
}'
{
  "social_set_id": 123,
  "timezone": "America/New_York",
  "rules": [
    {
      "h": 9,
      "m": 30,
      "days": [
        "mon",
        "wed",
        "fri"
      ]
    }
  ]
}

Get queue

Retrieve queue slots and scheduled drafts between start_date and end_date (inclusive).

Required permission: READ access to this social set.

Notes:

  • start_date and end_date are interpreted in the social set timezone.
  • Ranges larger than 62 days are rejected.
Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Query Parameters
  • start_date
    Type: string · Start Date
    required
  • end_date
    Type: string · End Date
    required
Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/queue
curl 'https://api.typefully.com/v2/social-sets/1/queue?start_date=&end_date=' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "social_set_id": 123,
  "start_date": "2026-02-01",
  "end_date": "2026-02-29",
  "days": [
    {
      "date": "2026-02-12",
      "items": [
        {
          "at": "2026-02-12T17:00:00Z",
          "kind": "queue_slot",
          "draft": null
        },
        {
          "at": "2026-02-12T22:00:00Z",
          "kind": "queue_slot",
          "draft": {
            "id": 98765,
            "preview": "Hello world",
            "scheduled_date": "2026-02-12T22:00:00Z",
            "draft_title": null,
            "mastodon_post_enabled": false,
            "social_set_id": 123,
            "share_url": null,
            "private_url": "https://typefully.com/?d=98765&a=123",
            "status": "scheduled",
            "tags": [],
            "created_at": "2026-02-12T21:30:00Z",
            "updated_at": null,
            "published_at": null,
            "mastodon_post_published_at": null,
            "linkedin_post_published_at": null,
            "threads_post_published_at": null,
            "bluesky_post_published_at": null,
            "substack_post_published_at": null,
            "x_post_published_at": null,
            "x_post_enabled": true,
            "linkedin_post_enabled": false,
            "threads_post_enabled": false,
            "bluesky_post_enabled": false,
            "substack_post_enabled": false,
            "x_published_url": null,
            "linkedin_published_url": null,
            "mastodon_published_url": null,
            "threads_published_url": null,
            "bluesky_published_url": null,
            "substack_published_url": null
          }
        },
        {
          "at": "2026-02-12T22:00:00Z",
          "kind": "custom_time",
          "draft": {
            "id": 99999,
            "preview": "Hello world",
            "scheduled_date": "2026-02-12T22:00:00Z",
            "draft_title": null,
            "mastodon_post_enabled": false,
            "social_set_id": 123,
            "share_url": null,
            "private_url": "https://typefully.com/?d=98765&a=123",
            "status": "scheduled",
            "tags": [],
            "created_at": "2026-02-12T21:30:00Z",
            "updated_at": null,
            "published_at": null,
            "mastodon_post_published_at": null,
            "linkedin_post_published_at": null,
            "threads_post_published_at": null,
            "bluesky_post_published_at": null,
            "substack_post_published_at": null,
            "x_post_published_at": null,
            "x_post_enabled": true,
            "linkedin_post_enabled": false,
            "threads_post_enabled": false,
            "bluesky_post_enabled": false,
            "substack_post_enabled": false,
            "x_published_url": null,
            "linkedin_published_url": null,
            "mastodon_published_url": null,
            "threads_published_url": null,
            "bluesky_published_url": null,
            "substack_published_url": null
          }
        }
      ]
    }
  ]
}

Media

Allows you to upload media to use in your drafts. Supported formats: jpg, jpeg, png, webp, gif, mp4, mov, pdf.

The flow for uploading media is three-fold:

  1. Get an upload URL
  2. Upload the media to the URL
  3. Verify that the media has completed processing

For example scripts in Python and Node.js, see: https://gist.github.com/rajatkapoor/e5be4497506f58b3546a35925db6a3a8

Create media upload

Generate a presigned S3 upload URL for images, videos, GIFs, or PDFs. After you receive the URL, upload the file contents with a PUT request and then reference the returned media_id when creating drafts.

Uploading: Send a plain PUT with only raw file bytes as the body — no extra headers (Content-Type, Authorization, etc.). The presigned URL signature was calculated without them, so adding headers causes a 403 SignatureDoesNotMatch. Use curl -T <file> (not --data-binary), requests.put(url, data=file_bytes) in Python, or fetch(url, {method:'PUT', body:buffer}) in JS. A successful upload returns 200 or 204.

Required permission: WRITE access to the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Body·
required
application/json

Schema for media upload request

  • file_name
    Type: string · File Name
    max length:  
    255
    Pattern: ^[a-zA-Z0-9_.()\-]+\.([jJ][pP][gG]|[jJ][pP][eE][gG]|[pP][nN][gG]|[wW][eE][bB][pP]|[gG][iI][fF]|[mM][pP]4|[mM][oO][vV]|[pP][dD][fF])$
    required

    Original filename with extension (e.g., 'image.jpg', 'video.mp4'). Used for MIME type detection and display. Allowed characters: letters, numbers, hyphens, underscores, periods, parentheses. Allowed extensions: .jpg, .jpeg, .png, .webp, .gif, .mp4, .mov, .pdf

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for post/v2/social-sets/{social_set_id}/media/upload
curl https://api.typefully.com/v2/social-sets/1/media/upload \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "file_name": "profile-photo.jpg"
}'
{
  "media_id": "550e8400-e29b-41d4-a716-446655440000",
  "upload_url": "https://s3.amazonaws.com/bucket/path/file.jpg?X-Amz-Algorithm=..."
}

Get media status

Retrieves the processing status of an uploaded media file. Poll this endpoint after uploading to check when the file is ready to use in drafts.

If no file is received before the upload URL expires (1 hour), the media transitions to 'failed' — create a new media upload and try again.

Required permission: READ access to the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

  • media_id
    Type: string · Media IdFormat: uuid
    required
Responses
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/media/{media_id}
curl https://api.typefully.com/v2/social-sets/1/media/123e4567-e89b-12d3-a456-426614174000 \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "media_id": "123e4567-e89b-12d3-a456-426614174000",
  "file_name": "photo.jpg",
  "mime": "image/jpeg",
  "status": "ready",
  "error_reason": "Unsupported file format",
  "media_urls": {
    "large": "https://cdn.../resized/...",
    "medium": "https://cdn.../resized/...",
    "original": "https://cdn.../original/...",
    "small": "https://cdn.../resized/..."
  }
}

Tags

Get all your tags and or create new ones to easily organize your drafts.

List tags

Retrieve all tags for a social set, ordered by their slugs.

Required permission: READ access to the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Query Parameters
  • limit
    Type: integer · Limit
    min:  
    1
    max:  
    50
    nullable

    Maximum number of items to return per page

  • offset
    Type: integer · Offset
    min:  
    0

    Number of items to skip from the beginning

Responses
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for get/v2/social-sets/{social_set_id}/tags
curl https://api.typefully.com/v2/social-sets/1/tags \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "results": [
    {
      "slug": "marketing",
      "name": "Marketing",
      "created_at": "2025-01-15T10:30:00Z"
    }
  ],
  "count": 1,
  "limit": 1,
  "offset": 1,
  "next": "string",
  "previous": "string"
}

Create tag

Create a new tag for a social set. The slug is automatically generated from the tag name, which must be unique per social set.

Required permission: WRITE access to the social set.

Path Parameters
  • social_set_id
    Type: integer · Social Set Id
    required

    Integer numbers.

Body·
required
application/json

Request schema for creating a tag

  • name
    Type: string · Name
    min length:  
    1
    max length:  
    32
    required

    Display name for the tag. The slug will be auto-generated from this name.

Responses
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
  • application/json
Request Example for post/v2/social-sets/{social_set_id}/tags
curl https://api.typefully.com/v2/social-sets/1/tags \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "name": "Marketing"
}'
{
  "slug": "marketing",
  "name": "Marketing",
  "created_at": "2025-01-15T10:30:00Z"
}

Webhooks

Configure webhooks to receive real-time notifications when events occur in your account.

Webhook Events

Subscribe to any combination of these events:

Event Description
draft.created Triggered when a new draft is created
draft.scheduled Triggered when a draft is scheduled for publishing
draft.published Triggered when a draft is successfully published
draft.status_changed Triggered on any status transition (includes scheduled/published)
draft.tags_changed Triggered when draft tags are modified
draft.deleted Triggered when a draft is deleted

Payload Structure

All webhooks send a JSON payload with two fields:

  • event: The event type (e.g., "draft.created")
  • data: The full draft details (see DraftDetailResponse schema)

HTTP Headers

Each webhook request includes these headers:

  • X-Typefully-Event: The event type (e.g., "draft.published")
  • X-Typefully-Timestamp: Unix timestamp when the event was generated
  • X-Typefully-Signature: HMAC-SHA256 signature for verification (format: sha256=<hex>)

Signature Verification

To verify webhook authenticity, compute the expected signature and compare:

import hmac
import hashlib

def verify_signature(payload_body: bytes, timestamp: str, signature: str, webhook_secret: str) -> bool:
    # Construct the signed payload
    signature_payload = f"{timestamp}.{payload_body.decode('utf-8')}"

    # Compute expected signature
    expected = hmac.new(
        webhook_secret.encode(),
        signature_payload.encode(),
        hashlib.sha256
    ).hexdigest()

    # Compare using constant-time comparison to prevent timing attacks
    expected_sig = f"sha256={expected}"
    return hmac.compare_digest(expected_sig, signature)

Important notes:

  • The JSON payload uses compact separators (no spaces after : or ,) and sorted keys
  • Always use constant-time comparison to prevent timing attacks
  • Verify the timestamp is recent to prevent replay attacks

Retry Behavior

Failed webhook deliveries are retried with exponential backoff up to 4 times (5 attempts total) over a 1 hour window.

Your endpoint should return any 2xx status code to acknowledge receipt. Non-2xx responses trigger retries.

Auto-Disable

Webhooks are automatically disabled after 100 consecutive failures. You'll receive an email notification when this happens. Re-enable from your API settings after fixing the endpoint issue.

Webhook

Draft Created

Triggered when a new draft is created in a social set you have access to.

Body
required
application/json

Payload envelope sent to webhook endpoints.

  • event
    const:  
    draft.created
    required

    The event type that triggered this webhook

  • data
    Type: object ·
    required

    The draft data at the time of the event.

Responses
  • 200

    Return any 2xx status to acknowledge receipt

Request Example for postdraft.created
{
  "event": "draft.created",
  "data": {
    "id": 12345,
    "social_set_id": 67890,
    "status": "draft",
    "publish_state": null,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T09:15:00Z",
    "scheduled_date": "2025-01-20T14:00:00Z",
    "published_at": "2025-01-20T14:00:05Z",
    "draft_title": "Weekly Newsletter",
    "tags": [
      "marketing",
      "product"
    ],
    "preview": "Excited to announce our new feature! 🚀",
    "share_url": "https://typefully.com/share/abc123",
    "private_url": "https://typefully.com/?d=12345&a=67890",
    "platforms": {
      "x": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "quote_post_url": "",
            "subscribers_only": true,
            "paid_partnership": true,
            "made_with_ai": true
          }
        ],
        "settings": {
          "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
          "community_id": "",
          "share_with_followers": true
        }
      },
      "linkedin": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "linkedin_reshare_urn": "",
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "mastodon": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ]
          }
        ],
        "settings": {}
      },
      "threads": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "bluesky": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "substack": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "x_article": {
        "content_markdown": "",
        "cover_media_id": ""
      }
    },
    "x_published_url": "https://x.com/username/status/1234567890",
    "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
    "mastodon_published_url": "https://mastodon.social/@username/1234567890",
    "threads_published_url": "https://www.threads.net/@username/post/ABC123",
    "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
    "substack_published_url": "https://substack.com/@username/note/c-123456789",
    "x_article_published_url": "https://x.com/i/article/1234567890",
    "x_post_published_at": "2025-01-20T14:00:05Z",
    "linkedin_post_published_at": "2025-01-20T14:00:08Z",
    "mastodon_post_published_at": "2025-01-20T14:00:10Z",
    "threads_post_published_at": "2025-01-20T14:00:12Z",
    "bluesky_post_published_at": "2025-01-20T14:00:15Z",
    "substack_post_published_at": "2025-01-20T14:00:15Z",
    "x_article_published_at": "2025-01-20T14:00:15Z",
    "scratchpad_text": "line 1\nline 2\n\nline 4"
  }
}
No Body
Webhook

Draft Scheduled

Triggered when a draft is scheduled for publishing.

Body
required
application/json

Payload envelope sent to webhook endpoints.

  • event
    const:  
    draft.scheduled
    required

    The event type that triggered this webhook

  • data
    Type: object ·
    required

    The draft data at the time of the event.

Responses
  • 200

    Return any 2xx status to acknowledge receipt

Request Example for postdraft.scheduled
{
  "event": "draft.scheduled",
  "data": {
    "id": 12345,
    "social_set_id": 67890,
    "status": "draft",
    "publish_state": null,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T09:15:00Z",
    "scheduled_date": "2025-01-20T14:00:00Z",
    "published_at": "2025-01-20T14:00:05Z",
    "draft_title": "Weekly Newsletter",
    "tags": [
      "marketing",
      "product"
    ],
    "preview": "Excited to announce our new feature! 🚀",
    "share_url": "https://typefully.com/share/abc123",
    "private_url": "https://typefully.com/?d=12345&a=67890",
    "platforms": {
      "x": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "quote_post_url": "",
            "subscribers_only": true,
            "paid_partnership": true,
            "made_with_ai": true
          }
        ],
        "settings": {
          "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
          "community_id": "",
          "share_with_followers": true
        }
      },
      "linkedin": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "linkedin_reshare_urn": "",
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "mastodon": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ]
          }
        ],
        "settings": {}
      },
      "threads": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "bluesky": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "substack": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "x_article": {
        "content_markdown": "",
        "cover_media_id": ""
      }
    },
    "x_published_url": "https://x.com/username/status/1234567890",
    "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
    "mastodon_published_url": "https://mastodon.social/@username/1234567890",
    "threads_published_url": "https://www.threads.net/@username/post/ABC123",
    "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
    "substack_published_url": "https://substack.com/@username/note/c-123456789",
    "x_article_published_url": "https://x.com/i/article/1234567890",
    "x_post_published_at": "2025-01-20T14:00:05Z",
    "linkedin_post_published_at": "2025-01-20T14:00:08Z",
    "mastodon_post_published_at": "2025-01-20T14:00:10Z",
    "threads_post_published_at": "2025-01-20T14:00:12Z",
    "bluesky_post_published_at": "2025-01-20T14:00:15Z",
    "substack_post_published_at": "2025-01-20T14:00:15Z",
    "x_article_published_at": "2025-01-20T14:00:15Z",
    "scratchpad_text": "line 1\nline 2\n\nline 4"
  }
}
No Body
Webhook

Draft Published

Triggered when a draft is successfully published to one or more platforms.

Body
required
application/json

Payload envelope sent to webhook endpoints.

  • event
    const:  
    draft.published
    required

    The event type that triggered this webhook

  • data
    Type: object ·
    required

    The draft data at the time of the event.

Responses
  • 200

    Return any 2xx status to acknowledge receipt

Request Example for postdraft.published
{
  "event": "draft.published",
  "data": {
    "id": 12345,
    "social_set_id": 67890,
    "status": "draft",
    "publish_state": null,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T09:15:00Z",
    "scheduled_date": "2025-01-20T14:00:00Z",
    "published_at": "2025-01-20T14:00:05Z",
    "draft_title": "Weekly Newsletter",
    "tags": [
      "marketing",
      "product"
    ],
    "preview": "Excited to announce our new feature! 🚀",
    "share_url": "https://typefully.com/share/abc123",
    "private_url": "https://typefully.com/?d=12345&a=67890",
    "platforms": {
      "x": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "quote_post_url": "",
            "subscribers_only": true,
            "paid_partnership": true,
            "made_with_ai": true
          }
        ],
        "settings": {
          "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
          "community_id": "",
          "share_with_followers": true
        }
      },
      "linkedin": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "linkedin_reshare_urn": "",
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "mastodon": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ]
          }
        ],
        "settings": {}
      },
      "threads": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "bluesky": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "substack": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "x_article": {
        "content_markdown": "",
        "cover_media_id": ""
      }
    },
    "x_published_url": "https://x.com/username/status/1234567890",
    "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
    "mastodon_published_url": "https://mastodon.social/@username/1234567890",
    "threads_published_url": "https://www.threads.net/@username/post/ABC123",
    "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
    "substack_published_url": "https://substack.com/@username/note/c-123456789",
    "x_article_published_url": "https://x.com/i/article/1234567890",
    "x_post_published_at": "2025-01-20T14:00:05Z",
    "linkedin_post_published_at": "2025-01-20T14:00:08Z",
    "mastodon_post_published_at": "2025-01-20T14:00:10Z",
    "threads_post_published_at": "2025-01-20T14:00:12Z",
    "bluesky_post_published_at": "2025-01-20T14:00:15Z",
    "substack_post_published_at": "2025-01-20T14:00:15Z",
    "x_article_published_at": "2025-01-20T14:00:15Z",
    "scratchpad_text": "line 1\nline 2\n\nline 4"
  }
}
No Body
Webhook

Draft Status Changed

Triggered on any status transition. This event fires alongside specific events like draft.scheduled or draft.published.

Body
required
application/json

Payload envelope sent to webhook endpoints.

  • event
    const:  
    draft.status_changed
    required

    The event type that triggered this webhook

  • data
    Type: object ·
    required

    The draft data at the time of the event.

Responses
  • 200

    Return any 2xx status to acknowledge receipt

Request Example for postdraft.status_changed
{
  "event": "draft.status_changed",
  "data": {
    "id": 12345,
    "social_set_id": 67890,
    "status": "draft",
    "publish_state": null,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T09:15:00Z",
    "scheduled_date": "2025-01-20T14:00:00Z",
    "published_at": "2025-01-20T14:00:05Z",
    "draft_title": "Weekly Newsletter",
    "tags": [
      "marketing",
      "product"
    ],
    "preview": "Excited to announce our new feature! 🚀",
    "share_url": "https://typefully.com/share/abc123",
    "private_url": "https://typefully.com/?d=12345&a=67890",
    "platforms": {
      "x": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "quote_post_url": "",
            "subscribers_only": true,
            "paid_partnership": true,
            "made_with_ai": true
          }
        ],
        "settings": {
          "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
          "community_id": "",
          "share_with_followers": true
        }
      },
      "linkedin": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "linkedin_reshare_urn": "",
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "mastodon": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ]
          }
        ],
        "settings": {}
      },
      "threads": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "bluesky": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "substack": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "x_article": {
        "content_markdown": "",
        "cover_media_id": ""
      }
    },
    "x_published_url": "https://x.com/username/status/1234567890",
    "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
    "mastodon_published_url": "https://mastodon.social/@username/1234567890",
    "threads_published_url": "https://www.threads.net/@username/post/ABC123",
    "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
    "substack_published_url": "https://substack.com/@username/note/c-123456789",
    "x_article_published_url": "https://x.com/i/article/1234567890",
    "x_post_published_at": "2025-01-20T14:00:05Z",
    "linkedin_post_published_at": "2025-01-20T14:00:08Z",
    "mastodon_post_published_at": "2025-01-20T14:00:10Z",
    "threads_post_published_at": "2025-01-20T14:00:12Z",
    "bluesky_post_published_at": "2025-01-20T14:00:15Z",
    "substack_post_published_at": "2025-01-20T14:00:15Z",
    "x_article_published_at": "2025-01-20T14:00:15Z",
    "scratchpad_text": "line 1\nline 2\n\nline 4"
  }
}
No Body
Webhook

Draft Tags Changed

Triggered when tags are added to or removed from a draft.

Body
required
application/json

Payload envelope sent to webhook endpoints.

  • event
    const:  
    draft.tags_changed
    required

    The event type that triggered this webhook

  • data
    Type: object ·
    required

    The draft data at the time of the event.

Responses
  • 200

    Return any 2xx status to acknowledge receipt

Request Example for postdraft.tags_changed
{
  "event": "draft.tags_changed",
  "data": {
    "id": 12345,
    "social_set_id": 67890,
    "status": "draft",
    "publish_state": null,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T09:15:00Z",
    "scheduled_date": "2025-01-20T14:00:00Z",
    "published_at": "2025-01-20T14:00:05Z",
    "draft_title": "Weekly Newsletter",
    "tags": [
      "marketing",
      "product"
    ],
    "preview": "Excited to announce our new feature! 🚀",
    "share_url": "https://typefully.com/share/abc123",
    "private_url": "https://typefully.com/?d=12345&a=67890",
    "platforms": {
      "x": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "quote_post_url": "",
            "subscribers_only": true,
            "paid_partnership": true,
            "made_with_ai": true
          }
        ],
        "settings": {
          "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
          "community_id": "",
          "share_with_followers": true
        }
      },
      "linkedin": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "linkedin_reshare_urn": "",
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "mastodon": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ]
          }
        ],
        "settings": {}
      },
      "threads": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "bluesky": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "substack": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "x_article": {
        "content_markdown": "",
        "cover_media_id": ""
      }
    },
    "x_published_url": "https://x.com/username/status/1234567890",
    "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
    "mastodon_published_url": "https://mastodon.social/@username/1234567890",
    "threads_published_url": "https://www.threads.net/@username/post/ABC123",
    "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
    "substack_published_url": "https://substack.com/@username/note/c-123456789",
    "x_article_published_url": "https://x.com/i/article/1234567890",
    "x_post_published_at": "2025-01-20T14:00:05Z",
    "linkedin_post_published_at": "2025-01-20T14:00:08Z",
    "mastodon_post_published_at": "2025-01-20T14:00:10Z",
    "threads_post_published_at": "2025-01-20T14:00:12Z",
    "bluesky_post_published_at": "2025-01-20T14:00:15Z",
    "substack_post_published_at": "2025-01-20T14:00:15Z",
    "x_article_published_at": "2025-01-20T14:00:15Z",
    "scratchpad_text": "line 1\nline 2\n\nline 4"
  }
}
No Body
Webhook

Draft Deleted

Triggered when a draft is deleted. The payload contains the draft data as it was before deletion.

Body
required
application/json

Payload envelope sent to webhook endpoints.

  • event
    const:  
    draft.deleted
    required

    The event type that triggered this webhook

  • data
    Type: object ·
    required

    The draft data at the time of the event.

Responses
  • 200

    Return any 2xx status to acknowledge receipt

Request Example for postdraft.deleted
{
  "event": "draft.deleted",
  "data": {
    "id": 12345,
    "social_set_id": 67890,
    "status": "draft",
    "publish_state": null,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T09:15:00Z",
    "scheduled_date": "2025-01-20T14:00:00Z",
    "published_at": "2025-01-20T14:00:05Z",
    "draft_title": "Weekly Newsletter",
    "tags": [
      "marketing",
      "product"
    ],
    "preview": "Excited to announce our new feature! 🚀",
    "share_url": "https://typefully.com/share/abc123",
    "private_url": "https://typefully.com/?d=12345&a=67890",
    "platforms": {
      "x": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "quote_post_url": "",
            "subscribers_only": true,
            "paid_partnership": true,
            "made_with_ai": true
          }
        ],
        "settings": {
          "reply_to_url": "https://x.com/therajatkapoor/status/1399394576951959554",
          "community_id": "",
          "share_with_followers": true
        }
      },
      "linkedin": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "linkedin_reshare_urn": "",
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "mastodon": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ]
          }
        ],
        "settings": {}
      },
      "threads": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "bluesky": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "substack": {
        "enabled": true,
        "posts": [
          {
            "text": "",
            "media_ids": [
              ""
            ],
            "hide_link_preview": false
          }
        ],
        "settings": {}
      },
      "x_article": {
        "content_markdown": "",
        "cover_media_id": ""
      }
    },
    "x_published_url": "https://x.com/username/status/1234567890",
    "linkedin_published_url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
    "mastodon_published_url": "https://mastodon.social/@username/1234567890",
    "threads_published_url": "https://www.threads.net/@username/post/ABC123",
    "bluesky_published_url": "https://bsky.app/profile/username.bsky.social/post/abc123",
    "substack_published_url": "https://substack.com/@username/note/c-123456789",
    "x_article_published_url": "https://x.com/i/article/1234567890",
    "x_post_published_at": "2025-01-20T14:00:05Z",
    "linkedin_post_published_at": "2025-01-20T14:00:08Z",
    "mastodon_post_published_at": "2025-01-20T14:00:10Z",
    "threads_post_published_at": "2025-01-20T14:00:12Z",
    "bluesky_post_published_at": "2025-01-20T14:00:15Z",
    "substack_post_published_at": "2025-01-20T14:00:15Z",
    "x_article_published_at": "2025-01-20T14:00:15Z",
    "scratchpad_text": "line 1\nline 2\n\nline 4"
  }
}
No Body

Models