Class: OmniSocials::Resources::Posts

Inherits:
Object
  • Object
show all
Defined in:
lib/omnisocials/resources/posts.rb

Overview

Posts resource: create, schedule, publish, update, and list posts.

content is a plain String, or a per-platform Hash with a "default" key. media_ids / media_urls are a flat Array, or a per-platform Hash. Each entry is a plain String, or a Hash with an "alt" accessibility description (max 1500 chars): { "url" => "https://...", "alt" => "..." } for media_urls, { "id" => "...", "alt" => "..." } for media_ids. Alt text is delivered to Mastodon (media description), Bluesky (embed alt), X (photos/GIFs), Pinterest (pin alt text), Instagram (images), and LinkedIn (images); the same entry shape works inside x/bluesky/mastodon thread_parts media.

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ Posts

Returns a new instance of Posts.



17
18
19
# File 'lib/omnisocials/resources/posts.rb', line 17

def initialize(client)
  @client = client
end

Instance Method Details

#create(content:, channels: nil, scheduled_at: nil, media_ids: nil, media_urls: nil, type: nil, source: nil, link_url: nil, link_title: nil, link_description: nil, link_thumbnail_url: nil, location_id: nil, collaborators: nil, user_tags: nil, hashtag_set: nil, hashtag_set_id: nil, hashtag_placement: nil, hashtag_platforms: nil, pinterest: nil, youtube: nil, instagram: nil, facebook: nil, linkedin: nil, linkedin_page: nil, tiktok: nil, x: nil, bluesky: nil, mastodon: nil, google_business: nil, linkedin_poll: nil) ⇒ Object

POST /posts/create - create a post (draft, or scheduled when scheduled_at is set).

hashtag_set (set name, case-insensitive) or hashtag_set_id applies a saved hashtag set once at create time; tags already in a caption are skipped; Instagram's 30-hashtag cap returns error code hashtag_limit_exceeded. hashtag_placement is "caption_append" (default) or "first_comment"; hashtag_platforms restricts the tags to a subset of channels.

When the post targets X and its text (or any thread part) contains a URL, the response includes a top-level "warnings" array (sibling of "data") with a "x_url_post_credits" entry carrying credits_required and credits_balance: X's link-post fee is passed through as prepaid credits, debited at publish time (from 2026-08-14). Credits are managed in the dashboard, not the API.

Separately, from 2026-08-14 this call (and #update / #publish) can refuse an X link post up front with a 402 and error code "x_credits_insufficient" (details: credits_required, credits_balance, credits_reserved) when reserving this post's cost would push the company's total reserved credits past its balance. Drafts are never gated, and posts scheduled to publish before 2026-08-14 are never gated either.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/omnisocials/resources/posts.rb', line 70

def create(content:, channels: nil, scheduled_at: nil, media_ids: nil,
           media_urls: nil, type: nil, source: nil, link_url: nil,
           link_title: nil, link_description: nil, link_thumbnail_url: nil,
           location_id: nil, collaborators: nil, user_tags: nil,
           hashtag_set: nil, hashtag_set_id: nil, hashtag_placement: nil,
           hashtag_platforms: nil, pinterest: nil, youtube: nil,
           instagram: nil, facebook: nil, linkedin: nil,
           linkedin_page: nil, tiktok: nil, x: nil, bluesky: nil,
           mastodon: nil, google_business: nil, linkedin_poll: nil)
  body = create_body(
    content: content, channels: channels, scheduled_at: scheduled_at,
    media_ids: media_ids, media_urls: media_urls, type: type,
    source: source, link_url: link_url, link_title: link_title,
    link_description: link_description, link_thumbnail_url: link_thumbnail_url,
    location_id: location_id, collaborators: collaborators,
    user_tags: user_tags, hashtag_set: hashtag_set,
    hashtag_set_id: hashtag_set_id, hashtag_placement: hashtag_placement,
    hashtag_platforms: hashtag_platforms, pinterest: pinterest,
    youtube: youtube, instagram: instagram, facebook: facebook,
    linkedin: linkedin, linkedin_page: linkedin_page, tiktok: tiktok,
    x: x, bluesky: bluesky, mastodon: mastodon,
    google_business: google_business, linkedin_poll: linkedin_poll
  )
  @client.request("POST", "/posts/create", json: body)
end

#create_and_publish(content:, channels: nil, media_ids: nil, media_urls: nil, type: nil, source: nil, link_url: nil, link_title: nil, link_description: nil, link_thumbnail_url: nil, location_id: nil, collaborators: nil, user_tags: nil, hashtag_set: nil, hashtag_set_id: nil, hashtag_placement: nil, hashtag_platforms: nil, pinterest: nil, youtube: nil, instagram: nil, facebook: nil, linkedin: nil, linkedin_page: nil, tiktok: nil, x: nil, bluesky: nil, mastodon: nil, google_business: nil, linkedin_poll: nil) ⇒ Object

POST /posts/create-and-publish - create and publish immediately. See #create for the "warnings" array and the 402 "x_credits_insufficient" credit gate on X link posts.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/omnisocials/resources/posts.rb', line 99

def create_and_publish(content:, channels: nil, media_ids: nil,
                       media_urls: nil, type: nil, source: nil,
                       link_url: nil, link_title: nil, link_description: nil,
                       link_thumbnail_url: nil, location_id: nil,
                       collaborators: nil, user_tags: nil,
                       hashtag_set: nil, hashtag_set_id: nil,
                       hashtag_placement: nil, hashtag_platforms: nil,
                       pinterest: nil, youtube: nil, instagram: nil,
                       facebook: nil, linkedin: nil, linkedin_page: nil,
                       tiktok: nil, x: nil, bluesky: nil, mastodon: nil,
                       google_business: nil, linkedin_poll: nil)
  body = create_body(
    content: content, channels: channels, scheduled_at: nil,
    media_ids: media_ids, media_urls: media_urls, type: type,
    source: source, link_url: link_url, link_title: link_title,
    link_description: link_description, link_thumbnail_url: link_thumbnail_url,
    location_id: location_id, collaborators: collaborators,
    user_tags: user_tags, hashtag_set: hashtag_set,
    hashtag_set_id: hashtag_set_id, hashtag_placement: hashtag_placement,
    hashtag_platforms: hashtag_platforms, pinterest: pinterest,
    youtube: youtube, instagram: instagram, facebook: facebook,
    linkedin: linkedin, linkedin_page: linkedin_page, tiktok: tiktok,
    x: x, bluesky: bluesky, mastodon: mastodon,
    google_business: google_business, linkedin_poll: linkedin_poll
  )
  @client.request("POST", "/posts/create-and-publish", json: body)
end

#delete(post_id) ⇒ Object

DELETE /posts/id - delete a post. Returns nil (204).



171
172
173
# File 'lib/omnisocials/resources/posts.rb', line 171

def delete(post_id)
  @client.request("DELETE", "/posts/#{post_id}")
end

#get(post_id) ⇒ Object

GET /posts/id - fetch a single post.



32
33
34
# File 'lib/omnisocials/resources/posts.rb', line 32

def get(post_id)
  @client.request("GET", "/posts/#{post_id}")
end

#list(status: nil, limit: nil, offset: nil) ⇒ Object

GET /posts - list posts (status: draft, in_approval, scheduled, posting, posted, failed, warning; in_approval = waiting for a reviewer in an approval workflow).



24
25
26
27
28
29
# File 'lib/omnisocials/resources/posts.rb', line 24

def list(status: nil, limit: nil, offset: nil)
  @client.request(
    "GET", "/posts",
    query: { "status" => status, "limit" => limit, "offset" => offset }
  )
end

#publish(post_id) ⇒ Object

POST /posts/id/publish - publish a draft or scheduled post now. See #create for the 402 "x_credits_insufficient" credit gate that can also refuse publishing a scheduled X link post.



178
179
180
# File 'lib/omnisocials/resources/posts.rb', line 178

def publish(post_id)
  @client.request("POST", "/posts/#{post_id}/publish")
end

#recent_platform(limit: nil, platforms: nil) ⇒ Object

GET /posts/recent-platform - recent posts fetched live from the connected platform APIs (including content published outside OmniSocials). Requires the analytics:read scope.



39
40
41
42
43
44
# File 'lib/omnisocials/resources/posts.rb', line 39

def recent_platform(limit: nil, platforms: nil)
  @client.request(
    "GET", "/posts/recent-platform",
    query: { "limit" => limit, "platforms" => Internal.join_list(platforms) }
  )
end

#retry(post_id) ⇒ Object

POST /posts/id/retry - retry the failed platforms of a "failed" or "warning" (partially failed) post, on the same post.

Only the platforms that failed are re-published; platforms that already succeeded are never posted again. Asynchronous: a 200 means the retry is queued - poll get for the outcome. Max 3 retries per platform.



189
190
191
# File 'lib/omnisocials/resources/posts.rb', line 189

def retry(post_id)
  @client.request("POST", "/posts/#{post_id}/retry")
end

#update(post_id, content: nil, scheduled_at: nil, channels: nil, media_ids: nil, media_urls: nil, type: nil, location_id: nil, collaborators: nil, user_tags: nil, pinterest: nil, youtube: nil, instagram: nil, facebook: nil, linkedin: nil, linkedin_page: nil, tiktok: nil, x: nil, bluesky: nil, mastodon: nil, google_business: nil, linkedin_poll: nil) ⇒ Object

PATCH /posts/id - update a draft or scheduled post.

Only top-level nils are dropped from the body, so passing e.g. x: { "thread_parts" => nil } still clears an X thread (reverts the post to single-tweet mode). The same applies to bluesky and mastodon thread parts.

See #create for the 402 "x_credits_insufficient" credit gate that can also refuse an update to a scheduled X link post.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/omnisocials/resources/posts.rb', line 136

def update(post_id, content: nil, scheduled_at: nil, channels: nil,
           media_ids: nil, media_urls: nil, type: nil, location_id: nil,
           collaborators: nil, user_tags: nil, pinterest: nil,
           youtube: nil, instagram: nil, facebook: nil, linkedin: nil,
           linkedin_page: nil, tiktok: nil, x: nil, bluesky: nil,
           mastodon: nil, google_business: nil, linkedin_poll: nil)
  body = Internal.drop_nil(
    {
      "content" => content,
      "scheduled_at" => scheduled_at,
      "channels" => channels,
      "media_ids" => media_ids,
      "media_urls" => media_urls,
      "type" => type,
      "location_id" => location_id,
      "collaborators" => collaborators,
      "user_tags" => user_tags,
      "pinterest" => pinterest,
      "youtube" => youtube,
      "instagram" => instagram,
      "facebook" => facebook,
      "linkedin" => linkedin,
      "linkedin_page" => linkedin_page,
      "tiktok" => tiktok,
      "x" => x,
      "bluesky" => bluesky,
      "mastodon" => mastodon,
      "google_business" => google_business,
      "linkedin_poll" => linkedin_poll
    }
  )
  @client.request("PATCH", "/posts/#{post_id}", json: body)
end