Skip to main content
The Midaz SDK for Go is the Go client for the Midaz ledger and Tracer APIs. It gives you typed access to each service (Organizations, Ledgers, Accounts, Transactions, and more) with one surface for authentication, pagination, errors, retries, logging, and observability.

Getting started


Step 1 – Install Go

Install Go before you use the SDK. The SDK declares Go 1.26 in go.mod. Its public API uses iter.Seq2 and log/slog.
2
Download the installer for your OS (Windows, macOS, or Linux).

Step 2 – Create or use an existing Go project

Create a Go project: To create a Go project, use the following command:
Use an existing Go project: If you’re working in an existing project, make sure there’s a go.mod file in the root. If not, run the following command to create one:

Step 3 – Add the Midaz SDK

Inside your project directory, run the following command to add the SDK to your go.mod and go.sum files:
The module path requires the /v6 suffix. If you omit it, Go resolves an old v1 release. Import github.com/LerianStudio/midaz-sdk-golang/v6.
In VS Code or GoLand, your IDE may automatically run go get when you import a new package.

Step 4 – Import the SDK

Create or open a main.go file and add the following content. The example builds a client against your local Midaz stack with anonymous authentication, lists organizations, then creates a new one.
The example below targets a local Midaz stack with auth disabled. If you don’t have one running yet, see Getting started with Midaz to spin one up before running the snippet.
This gives you access to:
  • The Midaz client for calling each API service.
  • Built-in data models (like CreateOrganizationInput).
  • Auth via Access Manager (production) or Anonymous (local development).
  • A typed configuration system that fails at construction time.
For the full setup, see the Authentication section.

Step 5 – Run the project

Run the following command:

SDK architecture


Layered design

Services

Midaz serves two ledger API versions: /v1, which is deprecated, and /v2. The SDK groups the ledger services by the version that serves them. Build against c.V2. A resource that one version does not serve is a compile error, not a 404.
Transactions has a different contract on each version. On /v1, you create a transaction through one of four creation endpoints with a nested send body. On /v2, c.V2.Transactions creates transactions with a flat body through CreateDirect, CreateHold, CreateBlock, and CreateUnblock. It returns models.TransactionV2.
A 201 response means that Midaz accepted the transaction, not that the balances are settled. To wait for the balance effect, use transaction.WaitForSettlement from the pkg/transaction package.

Models

Each model type represents a business concept. You use them in each service call. The most common model types are re-exported on the midaz package. midaz.Account and models.Account are the same type, so most code needs only one import.

Common model types

For a type that is not re-exported, such as models.TransactionV2, import github.com/LerianStudio/midaz-sdk-golang/v6/models directly. The midaz aliases keep the type identity, so the two import paths work together.

Utility packages

The pkg folder of the SDK holds utility packages. Core packages serve concerns that apply to the whole SDK. Helper packages give domain-specific or low-level utilities.

Core packages

Helper packages

Authentication


The SDK requires exactly one authentication source at construction time. If you call midaz.New(...) with neither, it returns a typed configuration error. You have two choices:
  • midaz.WithAccessManager(...): OAuth through the Lerian Access Manager. Use it for any non-local stack.
  • midaz.WithAnonymous(): no authentication. Use it only for a local Midaz stack with auth disabled.
If you apply both options, the last one wins.

Production: Access Manager

Put your Access Manager credentials in midaz.WithAccessManager. The SDK requests a token from your Access Manager, attaches it to each API call, and refreshes it when it expires.
Replace the values in the // Configure Access Manager block with your own credentials before running.

Local development: Anonymous

For a local Midaz stack with auth disabled, opt out explicitly:

Configure via environment variables

You can also point the SDK at your Access Manager with environment variables. Export them in your shell or your process manager:
config.FromEnvironment() reads the process environment, not a .env file. If you keep variables in a .env file during development, load them with a library like godotenv before calling config.NewConfig(config.FromEnvironment()).
Then opt in to environment loading at config time:
Environment loading is explicit. Put config.FromEnvironment() in the option chain. The SDK does not read environment variables during construction without it.
For the full auth walkthrough, see the Authentication guide in the SDK repo.

Tenant scope


Tenant scope comes from the Access Manager / JWT claims used to obtain the token. The SDK has no tenant configuration and does not send a tenant header. To run calls under a different tenant scope, use a separate set of Access Manager credentials, or build a second client with its own token context.

Listing and iteration


Most list endpoints come in three methods. Pick the one that matches your use case.

Typed list options

Each list method takes a typed opts struct. The struct embeds one of two base structs, based on how the endpoint paginates: Some endpoints also expose a typed Filters sub-struct. If you set a field of the wrong shape (for example, Page on a cursor endpoint), the code does not compile.
The transaction list does not filter by Status, AssetCode, Reference, SourceAccount, DestinationAccount, or Route. If you set one of these filters on List, the SDK refuses the call with an error. Count accepts Status and Route.

Iterate every item with All

The simplest shape is a range loop over each item across each page. The SDK fetches the pages internally.

Iterate page envelopes with Pages

When you need page-level metadata (for checkpointing, batching, or stopping mid-page), iterate over Pages. Each entry is a *models.ListResponse[T] with its Pagination block.
See the Pagination guide in the SDK repo for NextCursor handling and the page-vs-cursor decision table.

Error handling


The SDK service layer returns errors as *pkg/errors.Error with structured fields: You can branch with typed predicates, read fields with errors.As, or use the Retryable() method to drive retry policy.

Branch with typed predicates

The SDK has a set of Is* predicates, so you can match errors without reading internals:

Drive retry decisions with Retryable()

The Error.Retryable() method derives from Category. Use it instead of your own classification.

Wrap raw transport errors

If you call lower-level HTTP code outside the SDK and want the same structured error shape, use ClassifyTransportError:

Local validation: FieldErrors

Local input validation returns *pkg/validation.FieldErrors, a collection of per-field errors that the SDK finds before any HTTP call. Use errors.As to read them.
For the full category map, each code, and retry boundaries, see the Error handling guide in the SDK repo.

Retries


The default policy retries 3 times with exponential backoff and 25% jitter. It retries transport errors and the statuses 408, 425, 429, 500, 502, 503, and 504. The SDK retries POST, PUT, PATCH, and DELETE only when the request has an X-Idempotency header.
Use midaz.WithCustomRetryPolicy for your own retry predicate. To turn retries off, use midaz.WithoutRetries().

Logging


*slog.Logger is the logger surface of the SDK. Wire it with midaz.WithLogger(...). The SDK is silent by default: it uses slog.DiscardHandler until you opt in. You decide the handler, the level, and the destination.
charmbracelet/log, zap, and zerolog integrate through slog.Handler.
The Logging guide has adapter recipes for common logging libraries.

Observability


One observability provider gives you spans, metrics, and OpenTelemetry-correlated logs through one wiring point. Pass a provider that you build, or pass options that the SDK assembles for you.

Wire a provider

Or pass options inline

The SDK emits one HTTP span per outbound request with W3C traceparent propagation. Business log records carry safe IDs only: no payloads, names, addresses, or auth headers. You can also wrap a block of business logic in a span with Client.Trace:
WithObservabilityOptions and WithObservabilityProvider replace the installed provider. They do not merge. To start from a baseline, put observability.WithDevelopmentDefaults or observability.WithProductionDefaults first in the option chain.
See the 10-observability-otel example in the SDK repo for span attributes, metric names, and exporter setup.

Idempotency


Auto-idempotency is on by default. The SDK sends an X-Idempotency: <uuid> header on each unsafe HTTP request (POST, PUT, PATCH, DELETE). A retry after a transient failure then does not create a resource twice. You can override the generated key per call when you need a stable key of your own. This is typical for saga steps, outbox rows, or UI submissions.

Set a stable key per request

Suppress idempotency for one call

For rare administrative calls, suppress the header per request:
Without the header, the SDK does not retry that unsafe request.

Disable globally

To turn auto-idempotency off everywhere, turn it off at the client level:
You can also set MIDAZ_IDEMPOTENCY=false when you use config.FromEnvironment().

Environment variables


The SDK reads these variables only when config.FromEnvironment() is in your config option chain. For the full option matrix across midaz, pkg/config, and pkg/sdkctx, see the Configuration guide in the SDK repo.

Example projects


The SDK has a numbered set of focused tutorials (examples 01–10), plus advanced and reference examples. Each numbered example teaches one concept. Browse them in the examples directory on GitHub.
The repository also includes reference examples: concurrency, configuration, context, tracing, tracing-server, pkg-validation-demo, mass-demo-generator, and workflow-with-entities.

Explore the APIs


For more information about the APIs, refer to the following links:

External API mapping

Internal API mapping

Godoc documentation