Go SDK
Build a maxclicks integration into your Go service. Sync customer data, fire events, and trigger prepared experiences with context-aware requests and typed results.
Current API coverage
The SDK groups Public API calls by resource. Use the API reference for request fields, response payloads, and operation semantics, and the examples below for language-specific method calls.
Pagination helpers follow the API traversal limits. An iterator or method named all stops at the traversal cap; use scoped queries when working with larger datasets.
Install
go get github.com/maxclicks-ai/maxclicks-go
Quickstart
The client reads MAXCLICKS_API_KEY from the environment, or pass a key with WithAPIKey. The key is not validated at construction: a missing key surfaces as *maxclicks.ConfigurationError on the first authenticated call.
package main
import (
"context"
"fmt"
"log"
"github.com/maxclicks-ai/maxclicks-go"
)
func main() {
client := maxclicks.New(maxclicks.WithAPIKey("max_..."))
ctx := context.Background()
me, err := client.Me(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println("space:", me.Space.Slug)
contact, err := client.Records.Upsert(ctx, "students", maxclicks.RecordInput{
"email": "[email protected]",
"firstName": "Ada",
"tags": []string{"vip"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println("contact id:", contact.ID)
}
Configuration
maxclicks.New accepts functional options.
| Option | Default | Description |
|---|---|---|
WithAPIKey(string) | MAXCLICKS_API_KEY env var | Bearer API key. |
WithBaseURL(string) | https://api.maxclicks.ai/v1 | API base URL. Use maxclicks.StageBaseURL for stage. |
WithTimeout(time.Duration) | 60s | Per-request timeout. |
WithMaxRetries(int) | 2 | Extra retry attempts on retryable failures. |
WithHTTPClient(*http.Client) | &http.Client{} | Inject a custom client or transport. |
WithDefaultHeader(k, v string) | none | Add a header to every request. |
WithDefaultHeaders(map[string]string) | none | Add multiple headers. |
WithOnWarning(func(warnings []string, method, path string)) | none | Callback for API warnings. |
Errors
Every failure is a typed error. HTTP error responses map by status. Use errors.As against a specific type, or maxclicks.AsAPIError against the base *maxclicks.APIError.
_, err := client.Schemas.Get(ctx, "does-not-exist")
var notFound *maxclicks.NotFoundError
if errors.As(err, ¬Found) {
fmt.Println("missing:", notFound.Message, notFound.Code)
}
if apiErr, ok := maxclicks.AsAPIError(err); ok {
fmt.Println(apiErr.Status, apiErr.Type, apiErr.Code, apiErr.Message)
}
var rateLimit *maxclicks.RateLimitError
if errors.As(err, &rateLimit) {
time.Sleep(rateLimit.RetryAfter)
}
| Status or condition | Error type |
|---|---|
| 400 | *BadRequestError |
| 401 | *AuthenticationError |
| 402 | *PaymentRequiredError |
| 403 | *PermissionError |
| 404 | *NotFoundError |
| 405 | *MethodNotAllowedError |
| 409 | *ConflictError |
| 413 | *PayloadTooLargeError |
| 415 | *UnsupportedMediaTypeError |
| 422 | *UnprocessableEntityError |
| 429 | *RateLimitError (has RetryAfter) |
| 5xx | *ServerError |
| transport failure | *ConnectionError |
| timeout or deadline | *TimeoutError |
| missing API key | *ConfigurationError |
Every HTTP error type embeds *APIError, which carries Status, Code, Type, Message, Issues, Header, and RawBody. Issues is populated for validation-gate failures (such as broadcasts.send's broadcast_invalid) that report several problems at once. 402 signals insufficient_credits (an AI-generation or auto-fill call) or email_limit_reached (a send past the email allowance).
Retries are limited to what is safe to repeat. Reads retry on 429, any 5xx, and transport or timeout errors, up to WithMaxRetries extra attempts. A write retries on those only when you pass WithIdempotencyKey, since the server then collapses the repeat into the original; a keyless write that times out or hits a 5xx is reported to you instead of being sent again, so your code can inspect the outcome. The client also retries 429 responses according to its configured retry budget. Backoff is exponential with full jitter, and a Retry-After header (seconds or HTTP date) sets the delay floor.
Pagination
List endpoints return a *maxclicks.Page[T] and a matching ...All iterator that walks every page (stopping when hasMore is false or the maximum offset is reached).
// Single page:
page, err := client.Records.List(ctx, "students", &maxclicks.ListOptions{Limit: 100})
for _, r := range page.Data {
fmt.Println(r.ID)
}
if page.HasNextPage() {
page, err = page.NextPage(ctx)
}
// Auto-pager over every record:
it := client.Records.ListAll(ctx, "students", nil)
for it.Next(ctx) {
fmt.Println(it.Value().ID)
}
if err := it.Err(); err != nil {
log.Fatal(err)
}
client.Events.List is cursor-paginated, not offset-paginated. It returns a *maxclicks.CursorPage[Event] and a matching ListAll iterator, reading ready events within the selected time window. HasNextPage, NextPage, and Iterator work the same way.
Records and events preserve unknown custom-attribute keys in an Extra map[string]any field alongside the typed base fields.
Idempotency
Mutating endpoints the API documents as idempotency-aware accept maxclicks.WithIdempotencyKey(...) as a trailing option. A retry with the same key replays the original result instead of executing twice.
key := uuid.NewString()
contact, err := client.Records.Upsert(ctx, "students",
maxclicks.RecordInput{"email": "[email protected]"},
maxclicks.WithIdempotencyKey(key),
)
Pass an idempotency key to writes such as Records.Create, Records.Upsert, Suppressions.BatchCreate, Suppressions.BatchDelete, Templates.Send, Broadcasts.Send, and Workflows.Trigger. See the supported API writes and retry contract before replaying an operation.
Warnings
The API returns non-fatal warnings in the response body (warnings array), or, for the empty-body Workflows.Trigger response, in the maxclicks-Warning-Message header. Register a handler to observe them.
client := maxclicks.New(
maxclicks.WithAPIKey("max_..."),
maxclicks.WithOnWarning(func(warnings []string, method, path string) {
log.Printf("warning on %s %s: %v", method, path, warnings)
}),
)
*Page[T] also exposes the warnings for that page as page.Warnings.
Resource surface
Methods are grouped by resource on the client. Each list method also exposes a matching ...All auto-paging iterator.
- Name
client.Me- Type
- GET /me
- Description
The authenticated space and API key.
- Name
client.Schemas- Type
- /schemas
- Description
List,Get.
- Name
client.Attributes- Type
- /schemas/{schema}/attributes
- Description
List.
- Name
client.Records- Type
- /schemas/{schema}/records
- Description
List,Create,Upsert,Get,Update,Delete,AuditTrail.
- Name
client.Suppressions- Type
- /contacts/suppressions
- Description
List,Create,BatchCreate,BatchDelete,Delete. Admin key.
- Name
client.Events- Type
- /events
- Description
List(cursor),Fire,FireBatch.
- Name
client.Domains- Type
- /domains
- Description
List,Get.
- Name
client.Senders- Type
- /senders
- Description
List.
- Name
client.Topics- Type
- /topics
- Description
List,Get.
- Name
client.Segments- Type
- /segments
- Description
List,Create,Get,Delete,Count,ListContacts.
- Name
client.Broadcasts- Type
- /broadcasts
- Description
List,Get,Update,Send,ListRuns,GetMetrics.
- Name
client.Templates- Type
- /templates
- Description
List,Get,Send.
- Name
client.Webhooks- Type
- /webhooks
- Description
List,Create,Get,Update,Delete,RotateSecret.
- Name
client.Workflows- Type
- /workflows
- Description
List,Get,Trigger,Pause,Unpause,ListRuns,GetRun.
- Name
client.Forms- Type
- /forms/{formId}
- Description
Submit,ConfirmDoubleOptIn. No auth.
- Name
client.Emails- Type
- /emails/{emailId}
- Description
UnsubscribeOneClick. No auth.
Notable behaviors:
Events.FireBatchreturns a*BatchFireResulteven when the API responds422(a batch with failed items is a business result, not an error). Passmaxclicks.BatchOnErrorContinueormaxclicks.BatchOnErrorAbort.Templates.Sendis synchronous and returns a*TemplateSendResponse. A genuine send failure comes back asStatus: "failed"with a genericError. Pre-send validation and eligibility failures are typed errors.Workflows.Triggerreturns an empty body. Its path segment is a workflow-step reference, not a workflow id.Forms.ConfirmDoubleOptInandEmails.UnsubscribeOneClickfollow the browser redirect and return a*RedirectResultwith the final landing URL.
Create schemas, attributes, domains, senders, topics, templates and broadcasts in the maxclicks app, then use resource methods to read them or act on prepared work. Manage API keys and CSV imports in the app. See the API reference for request fields and response details.
Rate limits
Per API key: 100 read requests per second and 25 write requests per second. Exceeding a limit returns 429. The SDK retries automatically, honoring Retry-After.
The module path is github.com/maxclicks-ai/maxclicks-go. The SDK is MIT
licensed.
Retry outcomes
A repeated write can return a recorded result, including an error. If the API reports idempotency_outcome_unknown, inspect the affected resource or run history before creating a new operation. Keep the original key and payload while you reconcile. See the idempotency guide for supported operations and retention.