Skip to content

LerianStudio/midaz-sdk-golang

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

321 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

banner

Latest Release Go Report Discord Go Version License

Midaz Go SDK

The Midaz Go SDK is an idiomatic Go client for the Midaz financial ledger APIs. It exposes entity services for Ledger resources, CRM holders and aliases, structured errors, explicit configuration, retries, pagination helpers, concurrency utilities, and OpenTelemetry observability.

Features

  • Current Midaz API coverage: Ledger resources plus CRM holders, aliases, and MetadataIndexes.
  • Entity service API: Access services through c.Entity.<Service> with explicit methods such as CreateOrganization, ListAccounts, and CreateTransactionWithDSL.
  • Functional options: Configure clients with client.WithConfig, client.WithBaseURL, client.WithRetries, client.WithObservabilityProvider, and related options.
  • Access Manager authentication: Configure plugin authentication with auth.AccessManager and config.WithAccessManager or environment variables.
  • Structured errors: Use pkg/errors categories, codes, helper checkers, status accessors, and request/resource context.
  • Retries and idempotency: Built-in retry behavior for transient failures, with idempotency-aware retries for unsafe requests.
  • Pagination: models.ListOptions, models.ListResponse[T], and pagination metadata helpers.
  • Observability: OpenTelemetry tracing propagation, metrics, logging, and middleware helpers.
  • Concurrency utilities: Worker pools, batching, and rate limiting in pkg/concurrent.

Installation

go get github.com/LerianStudio/midaz-sdk-golang/v2

Quick start

package main

import (
    "context"
    "fmt"
    "log"

    client "github.com/LerianStudio/midaz-sdk-golang/v2"
    "github.com/LerianStudio/midaz-sdk-golang/v2/models"
    "github.com/LerianStudio/midaz-sdk-golang/v2/pkg/config"
)

func main() {
    cfg, err := config.NewConfig(config.FromEnvironment())
    if err != nil {
        log.Fatalf("failed to create config: %v", err)
    }

    c, err := client.New(
        client.WithConfig(cfg),
        client.UseAllAPIs(),
    )
    if err != nil {
        log.Fatalf("failed to create client: %v", err)
    }
    defer c.Shutdown(context.Background())

    ctx := context.Background()
    orgInput := models.NewCreateOrganizationInput("Example Corporation", "123456789").
        WithDoingBusinessAs("Example Inc.").
        WithAddress(models.Address{
            Line1:   "123 Main St",
            City:    "New York",
            State:   "NY",
            ZipCode: "10001",
            Country: "US",
        })

    org, err := c.Entity.Organizations.CreateOrganization(ctx, orgInput)
    if err != nil {
        log.Fatalf("failed to create organization: %v", err)
    }

    fmt.Printf("organization created: %s\n", org.ID)
}

config.FromEnvironment() is explicit. Environment variables are not loaded unless you pass that option to config.NewConfig.

Client configuration

Environment-based configuration

cfg, err := config.NewConfig(config.FromEnvironment())
if err != nil {
    return err
}

c, err := client.New(
    client.WithConfig(cfg),
    client.UseAllAPIs(),
)

Access Manager configuration

import auth "github.com/LerianStudio/midaz-sdk-golang/v2/pkg/access-manager"

accessManager := auth.AccessManager{
    Enabled:      true,
    Address:      "https://your-auth-service.com",
    ClientID:     "your-client-id",
    ClientSecret: "your-client-secret",
}

cfg, err := config.NewConfig(
    config.WithAccessManager(accessManager),
)
if err != nil {
    return err
}

c, err := client.New(
    client.WithConfig(cfg),
    client.UseAllAPIs(),
)

Equivalent environment variables:

PLUGIN_AUTH_ENABLED=true
PLUGIN_AUTH_ADDRESS=https://your-auth-service.com
MIDAZ_CLIENT_ID=your-client-id
MIDAZ_CLIENT_SECRET=your-client-secret

Direct URL configuration

c, err := client.New(
    client.WithBaseURL("http://localhost"),
    client.WithTimeout(30*time.Second),
    client.WithRetries(3, 100*time.Millisecond, 10*time.Second),
    client.UseAllAPIs(),
)

Entity services

Enable entity services with client.UseAllAPIs() or client.UseEntityAPI(). The current service surface is:

  • Accounts
  • AccountTypes
  • Assets
  • AssetRates
  • Balances
  • Holders
  • Aliases
  • Ledgers
  • MetadataIndexes
  • Operations
  • OperationRoutes
  • Organizations
  • Portfolios
  • Segments
  • Transactions
  • TransactionRoutes

Example calls:

orgs, err := c.Entity.Organizations.ListOrganizations(ctx, models.NewListOptions().WithLimit(20))
ledger, err := c.Entity.Ledgers.CreateLedger(ctx, orgID, models.NewCreateLedgerInput("Main Ledger"))
account, err := c.Entity.Accounts.GetAccount(ctx, orgID, ledgerID, accountID)
balance, err := c.Entity.Accounts.GetBalance(ctx, orgID, ledgerID, accountID)
holders, err := c.Entity.Holders.ListHolders(ctx, orgID, models.NewListOptions().WithLimit(20))

Accounts.GetBalance and Accounts.GetExternalAccountBalance are convenience helpers for accounts with exactly one balance. Use the Balances service list methods when an account can have multiple balances.

Transactions

The current transaction contract uses a send-based payload:

txInput := models.NewCreateTransactionInput("USD", "100.00").
    WithDescription("Payment from customer to merchant").
    WithSend(&models.SendInput{
        Asset: "USD",
        Value: "100.00",
        Source: &models.SourceInput{
            From: []models.FromToInput{
                {Account: customerAlias, Amount: models.AmountInput{Asset: "USD", Value: "100.00"}},
            },
        },
        Distribute: &models.DistributeInput{
            To: []models.FromToInput{
                {Account: merchantAlias, Amount: models.AmountInput{Asset: "USD", Value: "100.00"}},
            },
        },
    })
txInput.IdempotencyKey = "payment-2026-05-03-0001"

tx, err := c.Entity.Transactions.CreateTransaction(ctx, orgID, ledgerID, txInput)

DSL-style structured transactions are available with CreateTransactionWithDSL, and raw DSL file content can be sent with CreateTransactionWithDSLFile.

Pagination

options := models.NewListOptions().
    WithLimit(50).
    WithFilter("status", "ACTIVE")

for {
    page, err := c.Entity.Accounts.ListAccounts(ctx, orgID, ledgerID, options)
    if err != nil {
        return err
    }

    for _, account := range page.Items {
        process(account)
    }

    if !page.Pagination.HasNextPage() {
        break
    }

    options = page.Pagination.NextPageOptions()
}

See pagination for page, cursor, and sorting details.

Error handling

account, err := c.Entity.Accounts.GetAccount(ctx, orgID, ledgerID, accountID)
if err != nil {
    switch {
    case sdkerrors.IsNotFoundError(err):
        return fmt.Errorf("account not found: %w", err)
    case sdkerrors.IsAuthenticationError(err):
        return fmt.Errorf("authentication failed: %w", err)
    case sdkerrors.IsRateLimitError(err):
        return fmt.Errorf("rate limited: %w", err)
    default:
        return fmt.Errorf("failed to get account: %w", err)
    }
}

Import the error package as:

import sdkerrors "github.com/LerianStudio/midaz-sdk-golang/v2/pkg/errors"

See error handling for categories, status accessors, retry boundaries, and validation details.

Observability

provider, err := observability.New(context.Background(),
    observability.WithServiceName("my-service"),
    observability.WithComponentEnabled(true, true, true),
    observability.WithCollectorEndpoint("localhost:4317"),
)
if err != nil {
    return err
}
defer provider.Shutdown(context.Background())

c, err := client.New(
    client.WithObservabilityProvider(provider),
    client.UseAllAPIs(),
)

The SDK creates one outbound SDK HTTP span per entity request, propagates W3C traceparent and baggage, and emits structured business events for high-value lifecycle operations when logging is enabled. Business logs include safe IDs such as organizationId, ledgerId, accountId, and transactionId; they do not include payloads, metadata, documents, names, addresses, auth headers, idempotency keys, or raw bodies.

See tracing for OpenTelemetry propagation, incoming HTTP extraction, and safe business logging examples.

Environment variables

The SDK reads these variables when config.FromEnvironment() is used:

  • MIDAZ_ENVIRONMENT
  • MIDAZ_BASE_URL
  • MIDAZ_ONBOARDING_URL
  • MIDAZ_TRANSACTION_URL
  • MIDAZ_CRM_URL
  • MIDAZ_USER_AGENT
  • MIDAZ_TIMEOUT
  • MIDAZ_DEBUG
  • MIDAZ_MAX_RETRIES
  • MIDAZ_IDEMPOTENCY
  • PLUGIN_AUTH_ENABLED
  • PLUGIN_AUTH_ADDRESS
  • MIDAZ_CLIENT_ID
  • MIDAZ_CLIENT_SECRET

Documentation

Generate docs with:

make docs

Start an interactive docs server with:

make godoc

Examples

Run the mass demo generator:

cd examples/mass-demo-generator
DEMO_NON_INTERACTIVE=1 go run . --org-locale=br

For a bounded smoke run, use:

cd examples/mass-demo-generator
DEMO_NON_INTERACTIVE=1 go run . --orgs=1 --ledgers=1 --accounts=1 --tx=0

Testing

make test
make coverage
make verify-sdk

For the full local pipeline, run:

make ci

Contributing

Contributions are welcome. See CONTRIBUTING.md for guidelines.

License

This project is licensed under the Apache License, Version 2.0. See LICENSE.md for details.

Copyright 2025 Lerian Studio

About

A Go client library for the Midaz financial ledger APIs. This SDK provides a flexible, and idiomatic way to interact with the Midaz platform, enabling developers to build robust financial applications with ease. Features include complete API coverage, observability integration, concurrency support, robust error handling, etc.

Resources

License

Contributing

Stars

Watchers

Forks

Contributors

Languages