Skip to content

cycletask/ruby-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CycleTask Ruby SDK

Official Ruby client for the CycleTask Mail Forwarding API.

Manage domains, aliases, email forwarding rules, and view delivery stats — all from idiomatic Ruby.

Installation

Add to your Gemfile:

gem 'cycletask'

Then run:

bundle install

Or install directly:

gem install cycletask

Quick Start

require 'cycletask'

client = CycleTask::Client.new(api_key: 'ct_live_your_api_key')

# List all domains
domains = client.domains.list
domains.each { |d| puts "#{d.domain}#{d.status}" }

# Create an alias
a = client.aliases.create(
  alias: 'hello',
  domain_id: domains.first.id,
  destinations: ['me@gmail.com']
)
puts "Created: #{a.alias_address}@#{a.domain}"

Configuration

client = CycleTask::Client.new(
  api_key:     'ct_live_your_api_key',  # Required
  base_url:    'https://api.task-cycle.com/api', # Default
  timeout:     30,                       # Seconds, default: 30
  max_retries: 3                         # Retries on 429/5xx, default: 3
)

API Reference

Domains

# List all domains
domains = client.domains.list
# => [#<CycleTask::Types::Domain id="d_1" domain="example.com" status="verified">]

# Create a domain
domain = client.domains.create(domain: 'example.com')

# Get a domain by ID
domain = client.domains.get('d_1')

# Delete a domain
client.domains.delete('d_1')

# Trigger DNS verification
domain = client.domains.verify('d_1')

# Get required DNS records
records = client.domains.dns_records('d_1')
records.each { |r| puts "#{r.type} #{r.name}#{r.value}" }

Aliases

# List aliases (paginated)
result = client.aliases.list(page: 1, limit: 10, search: 'hello')
result.data       # => [CycleTask::Types::Alias, ...]
result.total      # => 42
result.page       # => 1
result.total_pages # => 5
result.next_page? # => true

# Iterate directly
result.each { |a| puts a.alias_address }

# Create an alias
a = client.aliases.create(
  alias: 'hello',
  domain_id: 'd_1',
  destinations: ['me@gmail.com', 'backup@gmail.com'],
  description: 'My main alias',
  privacy_mode: false
)

# Update an alias
a = client.aliases.update('a_1', is_active: false, description: 'Disabled')

# Delete an alias
client.aliases.delete('a_1')

# Get forwarding logs for an alias
logs = client.aliases.logs('a_1')
logs.each { |l| puts "#{l.from}#{l.status}" }

List Parameters

Parameter Type Description
page Integer Page number
limit Integer Items per page
search String Search by alias name
domain String Filter by domain ID
status String Filter: "active"/"inactive"
sort String Sort field

Stats

# Overview statistics
overview = client.stats.overview
# => {"total_forwarded" => 1234, "total_blocked" => 56, ...}

# Chart data
chart = client.stats.chart(days: 30)

# Email logs (paginated)
logs = client.stats.logs(page: 1, limit: 20, status: 'delivered')
logs.each { |l| puts "#{l.subject}#{l.status}" }

Status (Public)

These endpoints do not require authentication.

# Current system status
status = client.status.get
# => {"status" => "operational", "message" => "All systems normal"}

# Uptime metrics
uptime = client.status.uptime

# Recent incidents
incidents = client.status.incidents

Response Objects

All API responses are wrapped in typed objects with method accessors:

domain = client.domains.get('d_1')
domain.id          # => "d_1"
domain.domain      # => "example.com"
domain.status      # => "verified"
domain.is_verified # => true
domain.to_h        # => {"id" => "d_1", "domain" => "example.com", ...}
domain["id"]       # => "d_1" (bracket access for any field)

Paginated responses implement Enumerable:

result = client.aliases.list
result.size        # => 20
result.total       # => 142
result.next_page?  # => true
result.map(&:id)   # => ["a_1", "a_2", ...]

Error Handling

All errors inherit from CycleTask::Error:

begin
  client.domains.create(domain: 'bad')
rescue CycleTask::AuthenticationError => e
  # 401 — invalid or missing API key
  puts e.message
rescue CycleTask::ValidationError => e
  # 422 — validation failed
  puts e.errors  # => {"domain" => ["is invalid"]}
rescue CycleTask::NotFoundError => e
  # 404 — resource not found
rescue CycleTask::RateLimitError => e
  # 429 — rate limited (auto-retried by default)
rescue CycleTask::ServerError => e
  # 5xx — server error (auto-retried by default)
rescue CycleTask::TimeoutError => e
  # Request timed out
rescue CycleTask::ConnectionError => e
  # Could not connect
rescue CycleTask::Error => e
  # Catch-all for any other API error
  puts e.status  # HTTP status code
  puts e.body    # Parsed response body
end

Error Hierarchy

CycleTask::Error
├── CycleTask::AuthenticationError  (401)
├── CycleTask::NotFoundError        (404)
├── CycleTask::ValidationError      (422)
├── CycleTask::RateLimitError       (429)
├── CycleTask::ServerError          (5xx)
├── CycleTask::TimeoutError
└── CycleTask::ConnectionError

Automatic Retries

Requests that receive 429 (rate limit) or 5xx (server error) responses are automatically retried with exponential backoff:

  • Attempt 1: immediate
  • Retry 1: 1 second delay
  • Retry 2: 2 second delay
  • Retry 3: 4 second delay

If the server provides a Retry-After header, that value is used instead. Configure with max_retries: 0 to disable.

Requirements

  • Ruby 3.0+
  • No external dependencies (uses stdlib net/http and json)

Development

git clone https://github.com/cycletask/ruby-sdk.git
cd ruby-sdk
bundle install
bundle exec rspec

License

MIT License. See LICENSE for details.

About

Official Ruby SDK for CycleTask Mail Forwarding API

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages