shedcloud-gem

Official Ruby gem for the ShedCloud Partner API (/partner/v1/*).

Use this gem from Ruby 3.2+ to call company-scoped Partner API endpoints with an API key (sc_live_…) or OAuth2 client credentials.

Install

gem install shedcloud-partner_api

Or add to your Gemfile:

gem 'shedcloud-partner_api'

Hosts

Environment Host
production (default) https://go.shedcloud.com
sandbox https://api.shedcloudtest.com

Pass environment: for sandbox, or base_url: for a custom/local override.

Quick start

API key (production)

require 'shedcloud/partner_api'

client = ShedCloud::PartnerApi::Client.new(
  auth: ShedCloud::PartnerApi::Auth.new(api_key: ENV.fetch('SHEDCLOUD_API_KEY'))
)

stock = client.lot_stock.list(
  limit: 50,
  purchaseType: 'Lot Stock',
  sort: 'price',
  order: 'asc'
)

puts stock['total']
puts stock['data'].first['title']

Sandbox

client = ShedCloud::PartnerApi::Client.new(
  environment: 'sandbox',
  auth: ShedCloud::PartnerApi::Auth.new(api_key: ENV.fetch('SHEDCLOUD_API_KEY'))
)

OAuth2 client credentials

client = ShedCloud::PartnerApi::Client.new(
  auth: ShedCloud::PartnerApi::Auth.new(
    client_id: ENV.fetch('SHEDCLOUD_CLIENT_ID'),
    client_secret: ENV.fetch('SHEDCLOUD_CLIENT_SECRET')
  )
)

orders = client.orders.list(status: 'Unprocessed', limit: 25)

Create credentials in the ShedCloud portal under Settings → Developer API.

Resources

Each resource maps to a section of the hosted reference.

Client property Endpoints
client.lot_stock GET /partner/v1/lot-stock
client.stock_templates GET /partner/v1/stock-templates
client.leads GET/POST/PATCH /partner/v1/leads, status + status-history
client.quotes GET/POST/PATCH /partner/v1/quotes, convert, line-items
client.orders GET/POST/PATCH /partner/v1/orders, contract, payments, payment-links
client.work_orders GET/POST/PATCH /partner/v1/work-orders, status + status-history
client.locations GET/POST/PATCH /partner/v1/locations
client.customers GET/POST/PATCH /partner/v1/customers, merge
client.products GET/POST/PATCH /partner/v1/products, create sizes
client.domains GET /partner/v1/domains, location domains
client.agreements GET /partner/v1/agreements, state-legal
client.users GET/POST/PATCH /partner/v1/users, roles
client.payments GET /partner/v1/payments (read-only)
client.documents GET /partner/v1/documents, download
client.events GET /partner/v1/events, each iterator, redeliver, deliveries
client.site_events POST/GET /partner/v1/site-events (visitor behavioral tracking)
client.configurator_sessions POST /partner/v1/configurator-sessions

Idempotency and optimistic concurrency

quote = client.quotes.create(
  {
    serialNumber: 'SC-2024-00123',
    customer: { name: 'Jane Doe', email: 'jane@example.com' }
  },
  options: ShedCloud::PartnerApi::RequestOptions.with_idempotency_key(SecureRandom.uuid)
)

client.orders.update(
  order['id'],
  { customerPhone: '555-0100' },
  options: ShedCloud::PartnerApi::RequestOptions.with_if_match(order['version'])
)

For boolean query params that must be sent even when false:

client.quotes.list(converted: ShedCloud::PartnerApi::QueryValue.new(false))

Site events (marketing-site behavioral tracking)

Proxy batched events from your backend — never call this from the browser with a partner key. The ingest body is snake_case on the wire; query params on reads are camelCase.

res = client.site_events.track(
  {
    session_id: SecureRandom.uuid,
    visitor_id: visitor_id_from_local_storage,
    site_host: 'lelandssheds.com',
    events: [
      { event_type: 'page.view', page: '/sheds/lofted-barn' },
      { event_type: 'cta.click', page: '/sheds/lofted-barn', payload: { cta: 'design-your-own' } }
    ]
  }
)
puts res['accepted']

client.site_events.each(types: 'page.view') do |event|
  puts event['eventId'], event['eventType'], event['source']
end

Webhooks

Verify webhook deliveries with the subscription secret against the raw request body:

body = request.body.read
ShedCloud::PartnerApi::Webhooks.verify_signature(
  ENV.fetch('SHEDCLOUD_WEBHOOK_SECRET'),
  request.headers['X-ShedCloud-Signature'],
  body
)

Errors

Failed responses raise ShedCloud::PartnerApi::PartnerApiError (or AuthError for OAuth token failures):

begin
  client.orders.get(id)
rescue ShedCloud::PartnerApi::PartnerApiError => e
  puts e.status, e.message
  # e.forbidden?, e.not_found?, e.rate_limited?
end

Scopes

ShedCloud::PartnerApi::Scopes::LOT_STOCK_READ      # partner-api.lot-stock.read
ShedCloud::PartnerApi::Scopes::ORDERS_WRITE         # partner-api.orders.write
ShedCloud::PartnerApi::Scopes::SITE_EVENTS_WRITE    # partner-api.site-events.write
ShedCloud::PartnerApi::Scopes::SITE_EVENTS_READ     # partner-api.site-events.read

Development

bundle install
bundle exec rspec

Release

  1. Bump lib/shedcloud/partner_api/version.rb and add a CHANGELOG.md entry.
  2. Commit on main, then tag and push — GitHub Actions publishes to RubyGems on tag push:
git tag v0.2.0
git push origin main
git push origin v0.2.0

The workflow (.github/workflows/release.yml) runs bundle exec rspec, builds the gem, and pushes via rubygems/release-gem (OIDC). Tag format must be v* (e.g. v0.2.0).

Versioning & changelog

The Partner API is additive-only within /partner/v1. This gem is tagged with semver in lockstep with API additions.

Docs