github.com/alguna-io/alguna-go is the official Go client for the Alguna Public API. It has one typed method for each endpoint: customers, products and plans, subscriptions, usage events, credits and wallets, invoices, payments, and checkout and portal sessions. The request and response types come from the versioned OpenAPI spec. Use it from Go services where you would otherwise write HTTP calls by hand. It sets the Authorization and Alguna-Version headers, returns typed errors, sends an idempotency key on writes, and retries failed calls only when a retry is safe. The objects it handles are described in How Alguna works.
Use the SDK on a server only. API keys are secret: never ship them to a browser or a mobile app. To embed a purchase flow in your frontend, use Embedded Checkout. Your server creates the session with this SDK, and your frontend mounts it.
How it works
- Create an API key under Settings → Connections → Developers → API keys. A key looks like
<key_id>.<key_secret>. - Create the client with
client.NewAlguna. With no options, it reads the key fromALGUNA_API_KEY. Every request carriesAuthorization: Bearerand theAlguna-Versionheader. - Call resources such as
c.Customersandc.Subscriptions. Every method takes acontext.Contextfirst, and returns a typed response and anerror.
Installation
github.com/alguna-io/alguna-go on pkg.go.dev. Its source is alguna-io/alguna-go on GitHub. A release is a git tag on that repository.
alguna package. The options are in option.
Quick start: customer → subscription → invoice → portal session
Optional fields are pointers.alguna.String, alguna.Int, alguna.Bool and the other helpers in the root package return a pointer to a value.
Subscriptions are created in
draft status. Set AutoActivate (as above) or call c.Subscriptions.Activate when you are ready to go live. See Creating a Subscription for the full set of patterns.Resources
The client has one field for each API resource, and one method for each operation. The client is generated from the versioned spec, so every public operation has a method.
The client also has
Products, Plans, Bundles, CreditNotes, Payments, Refunds, Integrations, Insights, Quotes, RevenueSchedules, Merchants, Tags, Tax, Users and Feedback. Method names follow the operation they wrap. The full list is in reference.md in the SDK repository, and in the generated API reference.
Every method takes per-call options as its last arguments: option.WithIdempotencyKey (writes), option.WithMaxAttempts, option.WithoutRetries, option.WithHTTPClient, option.WithHTTPHeader and option.WithAPIVersion.
To get the status code and headers as well, call the same method on WithRawResponse, for example c.Customers.WithRawResponse.Get(ctx, id).
Pagination
List methods acceptLimit, Offset and the same filter parameters as the HTTP API. A list method returns a *core.Page: Results holds the items of the current page, and Response holds the full body. Iterator walks every item and gets the next page when it needs one.
limit maximum per page. The next page starts after the items that the SDK got, so a larger Limit skips nothing. Iteration stops at the first empty page, so a walk ends with one request that returns no items. To page by hand, call page.GetNextPage(ctx). After the last page, it returns core.ErrNoPages.
PDF downloads
Invoices.GeneratePdf, Quotes.GetPdf and Subscriptions.DownloadPdf return an io.Reader:
Error handling
When the API answers with an error status, the call returns one of the typed errors below. Each type embeds*core.APIError, which has StatusCode and Header. Match them with errors.As:
core is github.com/alguna-io/alguna-go/core.
err.Error() is the status and the body’s detail, else its title, else its message, else the HTTP status text. For example: 404: customer not found. Each typed error has the decoded body in Body. When the body does not decode, as with the empty body of some 502 responses, the error is a plain *core.APIError. A failure with no response is the *url.Error from net/http.
Include the X-Request-Id header of the failed response when you contact support. Status meanings and retry guidance are on the Errors page.
Idempotency and retries
Every request that is not a GET sends anIdempotency-Key: your key, or a UUID v4 that the SDK makes for the call. Every retry of the call sends the same key. The API then returns the first result and does not repeat the write (see Idempotency). Pass your own key when you repeat a call yourself, for example after a restart:
Events.Ingest, Credits.Check and Credits.Track are different. The events in the request body identify the work, so the SDK makes no key for these calls and still retries them. A key that you pass is sent on every attempt. See Writes identified by their events.
The SDK retries a failed attempt 2 times by default (3 attempts in total) when:
- the status is
408,429,502,503or504; - the status is
409with aRetry-Afterheader. The API sends this only while a request with the same key is still running. A409withoutRetry-Afteris a real conflict and is not retried; - no response arrived: the connection was refused, reset or closed, or the attempt timed out.
ctx is cancelled or its deadline passes. Between attempts it waits 1 s, then 2 s, with random jitter of up to 10%. When the response has a Retry-After header, it waits that long instead, at most 60 s. option.WithMaxAttempts(n) sets the number of attempts, the first included, on the client or on one call. option.WithMaxAttempts(0) means the default of 3 attempts. To turn retries off, use option.WithoutRetries().
Each attempt times out after 60 s. A timed-out attempt is retried, so one call can take 3 times the timeout plus the waits. To set a different time for each attempt, pass your own http.Client with a Timeout. To limit the whole call, retries included, give ctx a deadline:
Configuration
client.NewAlguna cannot return an error, so it does not check the key. A client without a key sends each request anyway, and the API answers with a 401: the call returns an *alguna.UnauthorizedError.
Pin the API version with option.WithAPIVersion. Without it, the SDK sends the version its types were generated from, so upgrading the module can move you to a newer API version. See Versioning.
The SDK sends User-Agent: alguna-go/<version>. A User-Agent in option.WithHTTPHeader replaces it.
Webhook types
Thealguna package has one type for each webhook body, such as alguna.WebhookPaymentCreatedPayload. Read type first, then decode the body into the matching type. The SDK types a payload. It does not check that Alguna sent it. Verify the svix-id, svix-timestamp and svix-signature headers against the raw request body before you trust a payload, as Verifying signatures shows.
FAQ
Can I use the SDK in a browser or mobile app? No. It authenticates with your secret API key. For browser purchase flows, create a checkout session on your server and mount it with Embedded Checkout. Does the SDK cover every endpoint? Yes. The client is generated from the versioned OpenAPI spec, so every operation in the API reference has a method. Why are some fields pointers? Optional fields are pointers, so that an unset field is not sent. Usealguna.String, alguna.Int, alguna.Bool and the other helpers to set them.
Which version am I on, and how does it relate to the API version?
They are different. The module version is the git tag you installed. Read it from go.mod. The API version is the date sent as Alguna-Version, and it decides request and response shapes. When you pass option.WithAPIVersion, a module upgrade does not change it. Change it on purpose, as its own change, following Versioning.
How do I point it at the sandbox?
Pass option.WithBaseURL("https://api.sandbox.alguna.io") with a sandbox API key. Sandbox and production are separate environments with separate keys. See Base URLs.
Is there an SDK for another language?
Yes. There are TypeScript, Python and Rust SDKs and an alguna CLI. They are generated from the same API spec. See SDKs and CLI.