Go SDK
The flare-go module follows the same wire contract as every other Flare SDK. Zero third-party dependencies — uses net/http, encoding/json, and crypto/hmac from the standard library.
go get github.com/zeridion/flare-go
Requires: Go 1.22+
Quick start
package main
import (
"context"
"fmt"
"log"
flare "github.com/zeridion/flare-go"
)
func main() {
client, err := flare.NewClient(flare.WithAPIKey("zf_live_sk_..."))
if err != nil {
log.Fatal(err)
}
job, err := client.CreateJob(context.Background(), &flare.CreateJobRequest{
JobType: "SendWelcomeEmail",
Payload: map[string]any{"email": "alice@example.com"},
Queue: "default",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(job.ID, job.State) // "job_abc123 pending"
}
Or, with FLARE_API_KEY set in the environment, omit flare.WithAPIKey(...).
Client construction
client, err := flare.NewClient(
flare.WithAPIKey("zf_live_sk_..."),
flare.WithBaseURL("https://api.zeridion.com"), // override for dev / staging
flare.WithMaxRetries(3), // 0 to disable retries
flare.WithRetryBaseDelay(500 * time.Millisecond),
flare.WithRetryMaxDelay(30 * time.Second),
flare.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
flare.WithMaxResponseBytes(10 * 1024 * 1024), // 10 MiB cap (0 disables)
)
The timeout is set on the injected http.Client (default 30 seconds). Override it by passing your own client via flare.WithHTTPClient(...); the timeout on that client applies to every outbound HTTP request the SDK makes.
Typed error hierarchy
The following are exported from the flare package:
| Type | HTTP | When it fires |
|---|---|---|
flare.APIError | — | Base type every typed error embeds |
flare.AuthError | 401 | Missing / invalid / revoked API key |
flare.QuotaError | 402 | Billing state blocked — subscription past_due / unpaid / cancelled |
flare.NotFoundError | 404 | Resource doesn't exist |
flare.ConflictError | 409 | Idempotency or invalid-state conflict |
flare.RateLimitError | 429 | Inspect .RetryAfter, .Limit, .Remaining |
Use the package's As* helpers to unwrap into a typed pointer, or fall back to errors.As from the standard library:
// Idiomatic — package-supplied helper:
if rle, ok := flare.AsRateLimitError(err); ok {
log.Printf("rate limited, retry after %d (epoch sec)", rle.RetryAfter)
return
}
// Equivalent stdlib form:
var rle *flare.RateLimitError
if errors.As(err, &rle) {
log.Printf("rate limited, retry after %d (epoch sec)", rle.RetryAfter)
return
}
The same pattern works for AsAuthError, AsQuotaError, AsNotFoundError, and AsConflictError.
Method reference
client.CreateJob(ctx, req, opts...) // POST /flare/v1/jobs
client.GetJob(ctx, id, opts...) // GET /flare/v1/jobs/{id} — returns (nil, nil) for 404
client.ListJobs(ctx, lo, opts...) // GET /flare/v1/jobs (cursor-paginated)
client.CancelJob(ctx, id, opts...) // POST /flare/v1/jobs/{id}/cancel — returns (nil, nil) for 409
client.RetryJob(ctx, id, opts...) // POST /flare/v1/jobs/{id}/retry — returns (nil, nil) for 409
client.PollWorkers(ctx, req, opts...) // POST /flare/v1/workers/poll
client.AckWorker(ctx, req, opts...) // POST /flare/v1/workers/ack
client.RegisterWorker(ctx, req, opts...) // POST /flare/v1/workers/register
client.Heartbeat(ctx, req, opts...) // POST /flare/v1/workers/heartbeat
PollWorker (singular) is kept as a deprecated alias for PollWorkers and will be removed at v1.0.
Worker registration and heartbeats
RegisterWorker announces a worker — its queues, job types, and any recurring schedules — to the server. Registration is best-effort: a non-nil error is safe to ignore and the worker can keep polling.
func (c *Client) RegisterWorker(ctx context.Context, req *RegisterWorkerRequest, opts ...RequestOption) (*RegisterWorkerResponse, error)
resp, err := client.RegisterWorker(ctx, &flare.RegisterWorkerRequest{
WorkerID: "worker-1",
Queues: []string{"default", "critical"},
JobTypes: []string{"SendWelcomeEmail", "GenerateReport"},
RecurringSchedules: []flare.RecurringSchedule{
{JobType: "NightlyDigest", CronExpression: "0 2 * * *", Timezone: "America/New_York"},
},
})
Heartbeat reports liveness and optional progress (0–1) for one in-flight job and returns the server's directive. A "cancel" status means the worker should abort the job and acknowledge it.
func (c *Client) Heartbeat(ctx context.Context, req *HeartbeatRequest, opts ...RequestOption) (*HeartbeatResponse, error)
progress := 0.5
beat, err := client.Heartbeat(ctx, &flare.HeartbeatRequest{
JobID: job.ID,
WorkerID: "worker-1",
Progress: &progress,
})
if err == nil && beat.Status == "cancel" {
// Stop work, then ack the job as cancelled.
}
Webhook verification
flare.VerifyWebhook validates the X-Zeridion-Signature header on outbound webhook deliveries. Pass the raw request body bytes — re-encoding parsed JSON invalidates the signature.
func handler(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
header := r.Header.Get("X-Zeridion-Signature")
if !flare.VerifyWebhook(payload, header, webhookSecret,
flare.WithVerifyTolerance(5*time.Minute)) {
w.WriteHeader(http.StatusBadRequest)
return
}
// Safe to process the event.
w.WriteHeader(http.StatusOK)
}
flare.WithVerifyTolerance enables replay protection — deliveries whose signature timestamp drifts more than the given duration from the current time are rejected (recommended: 5 * time.Minute; default: no timestamp check). The helper verifies against every v1= digest in the header, so it keeps working through a secret rotation with no receiver change.
Feature parity
See the SDK overview for the full feature-parity matrix across .NET, TypeScript, Python, Go, Java, PHP, and Ruby.
Source
Module path: github.com/zeridion/flare-go — fetch with go get github.com/zeridion/flare-go.