Ruby Quick Start

View as Markdown

Ruby syntax for the five Core Workflows. The canonical page owns the API semantics.

Client

require 'json'
require 'net/http'
require 'securerandom'
require 'time'
require 'uri'
 
BASE_URL = 'https://api.publora.com/api/v1'
 
def publora(method, path, body: nil, idempotency_key: nil)
  uri = URI("#{BASE_URL}/#{path}")
  request = Net::HTTP.const_get(method.capitalize).new(uri)
  request['x-publora-key'] = ENV.fetch('PUBLORA_API_KEY')
  request['Content-Type'] = 'application/json'
  request['Idempotency-Key'] = idempotency_key if idempotency_key
  request.body = JSON.generate(body) if body
  response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
  raise "Publora returned #{response.code}" unless response.is_a?(Net::HTTPSuccess)
  JSON.parse(response.body)
end
 
platform_id = ENV.fetch('PUBLORA_PLATFORM_ID')

1. Draft

draft = publora('post', 'create-post', body: {
  content: 'Draft from Ruby', platforms: [platform_id]
})

No scheduledTime means draft.

2. One-shot schedule

scheduled = publora('post', 'create-post', idempotency_key: SecureRandom.uuid, body: {
  content: 'Scheduled from Ruby',
  platforms: [platform_id],
  scheduledTime: (Time.now.utc + 300).iso8601
})

3. Upload and schedule

Follow the canonical presigned sequence. PUT bytes to the returned storage URL without the Publora API header, then:

upload_uri = URI(upload_url)
upload_request = Net::HTTP::Put.new(upload_uri)
upload_request['Content-Type'] = 'image/jpeg'
upload_request.body = File.binread('photo.jpg')
upload_response = Net::HTTP.start(upload_uri.host, upload_uri.port, use_ssl: true) do |http|
  http.request(upload_request)
end
raise 'Storage upload failed' unless upload_response.is_a?(Net::HTTPSuccess)
 
publora('post', "complete-media/#{media_file_id}")
publora('put', "update-post/#{post_group_id}",
  idempotency_key: "schedule-#{post_group_id}", body: {
    status: 'scheduled', scheduledTime: (Time.now.utc + 300).iso8601
  })

4. Update

publora('put', "update-post/#{post_group_id}",
  idempotency_key: "reschedule-#{post_group_id}", body: {
    status: 'scheduled', scheduledTime: (Time.now.utc + 600).iso8601
  })

5. Webhook consumer

require 'openssl'
 
post '/publora-webhook' do
  raw = request.body.read
  expected = OpenSSL::HMAC.hexdigest('SHA256', ENV.fetch('PUBLORA_WEBHOOK_SECRET'), raw)
  halt 401 unless Rack::Utils.secure_compare(expected, request.env['HTTP_X_PUBLORA_SIGNATURE'].to_s)
  envelope = JSON.parse(raw)
  status 204
end

Rails/Faraday/HTTParty may wrap the same calls; they do not change the wire contract. CSV import, batch operations, and LinkedIn analytics remain discoverable through dedicated pages and the OpenAPI document. See Webhooks.