Official Go client for the CycleTask Mail Forwarding API.
- Zero external dependencies (stdlib only)
- Context-aware with cancellation support
- Automatic retry with exponential backoff on 429/5xx
- Idiomatic Go: functional options, pointer helpers, exported types
go get github.com/cycletask/go-sdkRequires Go 1.21+.
package main
import (
"context"
"fmt"
"log"
cycletask "github.com/cycletask/go-sdk"
)
func main() {
client := cycletask.New("ct_live_your_api_key")
ctx := context.Background()
domains, err := client.Domains.List(ctx)
if err != nil {
log.Fatal(err)
}
for _, d := range domains {
fmt.Printf("%s verified=%t\n", d.Domain, d.IsVerified)
}
}client := cycletask.New("ct_live_key",
cycletask.WithBaseURL("https://custom.api.com/api"),
cycletask.WithTimeout(15 * time.Second),
cycletask.WithMaxRetries(5),
cycletask.WithHTTPClient(myHTTPClient),
)| Option | Default | Description |
|---|---|---|
WithBaseURL |
https://api.task-cycle.com/api |
Override the API base URL |
WithTimeout |
30s |
HTTP client timeout (ignored if WithHTTPClient is set) |
WithMaxRetries |
3 |
Max retry attempts for 429/5xx errors |
WithHTTPClient |
nil |
Use a custom *http.Client |
// List all domains
domains, err := client.Domains.List(ctx)
// Get a single domain
domain, err := client.Domains.Get(ctx, "domain_id")
// Create a domain
domain, err := client.Domains.Create(ctx, &cycletask.CreateDomainParams{
Domain: "example.com",
})
// Verify a domain
domain, err := client.Domains.Verify(ctx, "domain_id")
// Get required DNS records
records, err := client.Domains.GetDNSRecords(ctx, "domain_id")
// Delete a domain
err := client.Domains.Delete(ctx, "domain_id")// List aliases with pagination and filters
resp, err := client.Aliases.List(ctx, &cycletask.ListAliasesParams{
Page: 1,
Limit: 25,
Search: "hello",
Domain: "domain_id",
Status: "active",
Sort: "-createdAt",
})
// resp.Data contains []Alias
// resp.Pagination contains page info
// Create an alias
alias, err := client.Aliases.Create(ctx, &cycletask.CreateAliasParams{
Alias: "hello",
DomainID: "domain_id",
Destinations: []string{"me@gmail.com", "backup@gmail.com"},
Description: "My alias",
})
// Update an alias (pointer fields for partial updates)
alias, err := client.Aliases.Update(ctx, "alias_id", &cycletask.UpdateAliasParams{
IsActive: cycletask.Bool(false),
Description: cycletask.String("Disabled"),
Destinations: cycletask.Strings([]string{"new@gmail.com"}),
})
// Get forwarding logs for an alias
logs, err := client.Aliases.GetLogs(ctx, "alias_id", &cycletask.ListLogsParams{
Page: 1,
Limit: 50,
})
// Delete an alias
err := client.Aliases.Delete(ctx, "alias_id")// Get overview statistics
overview, err := client.Stats.Overview(ctx)
// overview.TotalForwarded, overview.TotalFailed, etc.
// Get chart data
chart, err := client.Stats.Chart(ctx, &cycletask.ChartParams{Days: 30})
// chart is []ChartDataPoint with Date, Forwarded, Failed
// Get forwarding logs (global)
logs, err := client.Stats.Logs(ctx, &cycletask.ListLogsParams{
Page: 1,
Limit: 100,
Status: "delivered",
})// Get service status
status, err := client.Status.Get(ctx)
// Get uptime information
uptime, err := client.Status.Uptime(ctx)
// Get incidents
incidents, err := client.Status.Incidents(ctx)All API errors are returned as *cycletask.Error:
domain, err := client.Domains.Get(ctx, "bad_id")
if err != nil {
var apiErr *cycletask.Error
if errors.As(err, &apiErr) {
fmt.Printf("Status: %d\n", apiErr.StatusCode)
fmt.Printf("Code: %s\n", apiErr.Code)
fmt.Printf("Message: %s\n", apiErr.Message)
}
}Convenience helpers:
if cycletask.IsNotFound(err) { ... }
if cycletask.IsRateLimited(err) { ... }
if cycletask.IsUnauthorized(err) { ... }The client automatically retries on:
- 429 Too Many Requests — respects
Retry-Afterheader - 5xx Server Errors — exponential backoff (500ms, 1s, 2s, ...)
- Network errors — connection failures, timeouts
Retries respect context cancellation. Configure with WithMaxRetries(n).
Use these to set optional fields in update params:
cycletask.Bool(true) // *bool
cycletask.String("value") // *string
cycletask.Int(42) // *int
cycletask.Strings([]string{"a", "b"}) // *[]stringMIT