> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Midaz SDK para Go

> Construa aplicações Go sobre o Midaz com o SDK oficial v4 — paginação tipada, erros estruturados e observabilidade OpenTelemetry de fábrica.

O **Midaz SDK para Go** é o cliente v4 idiomático para as APIs de Ledger financeiro do Midaz. Ele oferece acesso tipado a todos os serviços — Organizations, Ledgers, Accounts, Transactions e mais — com uma única superfície para autenticação, paginação, erros, logging e observabilidade.

Seja para colocar de pé seu primeiro Ledger ou para rodar fluxos de pagamento em produção em escala, o SDK mantém você focado na lógica de negócio e longe do código repetitivo.

<Warning>
  **Vindo da v2?** A v4 é uma major version limpa, com breaking changes em autenticação, paginação, erros e acesso a serviços. Não há janela de depreciação — você troca seu import de `/v2` para `/v4` e migra ao mesmo tempo.

  Leia o [Guia de migração da v2 para v3](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/migration-v2-to-v3.md) antes de atualizar.
</Warning>

## Primeiros passos

***

### Passo 1 – Instale o Go

Antes de usar o SDK, você **deve** instalar o Go na sua máquina. A v4 declara **Go 1.26** no `go.mod`. A API pública também usa `iter.Seq2` e `log/slog`.

<Steps>
  <Step>
    Acesse o [site oficial do Go](https://golang.org/dl/).
  </Step>

  <Step>
    Baixe o instalador para o seu sistema operacional (Windows, macOS ou Linux).
  </Step>

  <Step>
    [**Siga as instruções de instalação.**](https://go.dev/doc/install)
  </Step>
</Steps>

### Passo 2 – Crie ou use um projeto Go existente

**Crie um projeto Go:**

Para criar um projeto Go, use o seguinte comando:

<CodeGroup>
  ```bash Bash theme={null}
  mkdir my-midaz-app
  cd my-midaz-app
  go mod init my-midaz-app
  ```
</CodeGroup>

**Use um projeto Go existente:**

Se você está trabalhando em um projeto existente, certifique-se de que há um arquivo `go.mod` na raiz. Se não, execute o seguinte comando para criar um:

<CodeGroup>
  ```bash Bash theme={null}
  go mod init your-module-name
  ```
</CodeGroup>

### Passo 3 – Adicione o Midaz SDK

Dentro do diretório do seu projeto, execute o seguinte comando para baixar o SDK v4 e adicioná-lo aos seus arquivos `go.mod` e `go.sum`:

<Warning>
  **O caminho do módulo exige o sufixo `/v4`.** Se você omitir, o Go vai resolver uma release antiga, anterior à v4, que não tem nenhuma das mudanças entregues nesta versão. Sempre importe `github.com/LerianStudio/midaz-sdk-golang/v4`.
</Warning>

<CodeGroup>
  ```bash Bash theme={null}
  go get github.com/LerianStudio/midaz-sdk-golang/v4
  ```
</CodeGroup>

<Tip>
  Usando VS Code ou GoLand? Sua IDE pode executar `go get` automaticamente quando você importa um novo pacote.
</Tip>

### Passo 4 – Importe o SDK

Crie ou abra um arquivo `main.go` e adicione o seguinte conteúdo. O exemplo abaixo cria um cliente contra seu stack Midaz local com autenticação anônima, lista organizações e cria uma nova.

<Note>
  O exemplo abaixo aponta para um stack Midaz local com auth desabilitada. Se você ainda não tem um rodando, veja [Primeiros passos com o Midaz](/pt/getting-started) para subir um antes de executar o snippet.
</Note>

<CodeGroup>
  ```go Go expandable theme={null}
  package main

  import (
  	"context"
  	"fmt"
  	"log"

  	"github.com/LerianStudio/midaz-sdk-golang/v4"
  	"github.com/LerianStudio/midaz-sdk-golang/v4/models"
  )

  func main() {
  	// Build a client. v4 requires exactly one auth source — use
  	// midaz.WithAnonymous() for a local stack, or midaz.WithAccessManager(...)
  	// for a development or production environment.
  	c, err := midaz.New(
  		midaz.WithEnvironment(midaz.EnvironmentLocal),
  		midaz.WithAnonymous(),
  	)
  	if err != nil {
  		log.Fatalf("midaz.New: %v", err)
  	}
  	defer c.Shutdown(context.Background())

  	ctx := context.Background()

  	// List the first 5 organizations using a typed list-opts struct.
  	page, err := c.Organizations.ListOrganizations(ctx, models.OrganizationsListOpts{
  		PageListOpts: models.PageListOpts{Limit: 5},
  	})
  	if err != nil {
  		log.Fatalf("ListOrganizations: %v", err)
  	}

  	for _, org := range page.Items {
  		fmt.Printf("- %s (%s)\n", org.LegalName, org.ID)
  	}

  	// Create a new organization. Notice that midaz.CreateOrganizationInput is
  	// the same type as models.CreateOrganizationInput — re-exported on the
  	// midaz package so most user code only needs one import.
  	dba := "Example Inc."
  	org, err := c.Organizations.CreateOrganization(ctx, &midaz.CreateOrganizationInput{
  		LegalName:       "Example Corporation",
  		LegalDocument:   "123456789",
  		DoingBusinessAs: &dba, // optional fields are *string — use &local for short literals
  		Address: midaz.Address{
  			Line1:   "123 Main St",
  			City:    "New York",
  			State:   "NY",
  			ZipCode: "10001",
  			Country: "US",
  		},
  	})
  	if err != nil {
  		log.Fatalf("CreateOrganization: %v", err)
  	}

  	fmt.Printf("Organization created: %s\n", org.ID)
  }
  ```
</CodeGroup>

Isso te dá acesso a:

* O cliente Midaz para chamar todos os serviços da API.
* Os data models embutidos (como `CreateOrganizationInput`).
* Autenticação via **Access Manager** (produção) ou **Anonymous** (desenvolvimento local).
* Um sistema de configuração tipado que falha rápido na construção do cliente.

<Tip>
  Quer aprender mais sobre autenticação? Pule para a seção [Autenticação](#autenticação) para a configuração completa.
</Tip>

### Passo 5 – Execute o projeto

Execute o seguinte comando:

<CodeGroup>
  ```bash Bash theme={null}
  go run main.go
  ```
</CodeGroup>

## Arquitetura do SDK

***

O **Midaz SDK para Go** é construído com clareza e previsibilidade. Todo serviço é acessado direto no cliente, todo método de listagem segue o mesmo trio de assinaturas, todo erro é estruturado, e toda opção falha rápido na construção.

#### Design em camadas

| Camada                  | O que ela resolve                                                                                    |
| :---------------------- | :--------------------------------------------------------------------------------------------------- |
| **Client**              | O ponto de entrada principal — `midaz.New(...)` conecta autenticação, retries e observabilidade.     |
| **Services**            | Acesso de alto nível a cada domínio do Midaz, expostos como campos promovidos no Client.             |
| **Models**              | Estruturas de dados core que espelham a lógica de domínio do Midaz, re-exportadas no pacote `midaz`. |
| **Pacotes utilitários** | Helpers modulares para config, erros, observabilidade, retries, idempotency e mais.                  |

<Note>
  Os serviços são acessados direto no cliente — `c.Accounts`, `c.Transactions`, `c.Organizations`. Você pode ver um campo `Entity` embutido no autocomplete, mas código novo deve usar os campos de serviço diretos mostrados neste guia.
</Note>

<Tip>
  Quer mergulhar mais fundo? Confira o [racional de design da v3](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/v3-dx-plan.md) para a história arquitetural completa por trás do rewrite.
</Tip>

### Serviços

A camada `Services` é seu ponto de acesso a cada domínio do Midaz. Cada serviço cuida de uma família de recursos e entrega todos os métodos como parte de sua única interface — sem toggle `UseAllAPIs()`, sem etapa de registro de serviço. Todo serviço já está inicializado e pronto para uso no momento em que `midaz.New()` retorna.

#### Serviços disponíveis

| Serviço               | O que ele faz                                          |
| :-------------------- | :----------------------------------------------------- |
| `c.Organizations`     | Gerencia organizações.                                 |
| `c.Ledgers`           | Cria e recupera Ledgers.                               |
| `c.Assets`            | Define e gerencia ativos.                              |
| `c.AssetRates`        | Configura e busca taxas de câmbio entre ativos.        |
| `c.Accounts`          | Gerencia contas e consulta saldos.                     |
| `c.AccountTypes`      | Gerencia definições de tipos de conta.                 |
| `c.Portfolios`        | Agrupa contas em portfólios.                           |
| `c.Segments`          | Categoriza contas por segmentos.                       |
| `c.Transactions`      | Cria e busca transações financeiras.                   |
| `c.TransactionRoutes` | Define e gerencia regras de roteamento de transações.  |
| `c.Operations`        | Detalha as operações atômicas dentro de uma transação. |
| `c.OperationRoutes`   | Define e gerencia regras de roteamento de operações.   |
| `c.Balances`          | Consulta saldos de conta em tempo real.                |
| `c.Holders`           | Gerencia holders de conta no CRM.                      |
| `c.Aliases`           | Gerencia aliases de CRM para contas e entidades.       |
| `c.MetadataIndexes`   | Gerencia índices de metadados pesquisáveis.            |

### Models

Os models refletem como o Midaz pensa em finanças, com cada tipo amarrado a um conceito de negócio do mundo real. Você vai usá-los em toda chamada de serviço — desde o onboarding de contas até o registro de transações multi-leg.

Na v4, os tipos de model mais comuns são re-exportados no próprio pacote `midaz`. Isso significa que `midaz.Account` e `models.Account` são o mesmo tipo, e a maioria do código só precisa de um import.

#### Tipos de modelos comuns

| Model                | O que ele representa                                                             |
| :------------------- | :------------------------------------------------------------------------------- |
| `midaz.Organization` | Uma entidade de negócio que detém Ledgers e contas.                              |
| `midaz.Ledger`       | Uma coleção de contas e transações.                                              |
| `midaz.Asset`        | Uma unidade de valor (moeda, token etc.) que pode ser armazenada ou movimentada. |
| `midaz.Account`      | Uma conta para rastreamento de ativos e saldos.                                  |
| `midaz.Portfolio`    | Uma coleção de contas para agrupamento e gestão.                                 |
| `midaz.Segment`      | Uma unidade de categorização para organização granular.                          |
| `midaz.Transaction`  | Um evento financeiro composto por múltiplas operações.                           |
| `midaz.Operation`    | Uma entrada individual de débito ou crédito dentro de uma transação.             |
| `midaz.Balance`      | O estado atual das posições de uma conta.                                        |

<Tip>
  Precisa de um builder, de uma struct de request interna ou de um tipo deprecado? Importe `github.com/LerianStudio/midaz-sdk-golang/v4/models` direto — todo tipo vive lá, e os aliases do `midaz` preservam a identidade dos tipos, então os dois caminhos de import interoperam sem fricção.
</Tip>

### Pacotes utilitários

Dentro da pasta `pkg` do SDK, você encontra pacotes utilitários que atacam desafios comuns de dev — de tratamento de config a políticas de retry e primitivas de segurança. Eles se dividem em dois grupos: pacotes **core** que sustentam preocupações transversais do SDK, e pacotes **helpers** que oferecem utilitários específicos de domínio ou de baixo nível.

#### Pacotes core

| Pacote          | O que ele resolve                                                                            |
| :-------------- | :------------------------------------------------------------------------------------------- |
| `auth`          | OAuth do Access Manager e ciclo de vida do token. Substitui o pacote `access-manager` da v2. |
| `config`        | Tratamento centralizado de config, overrides via env e URLs de serviço customizadas.         |
| `concurrent`    | Ferramentas para batching, rate-limiting e worker pools.                                     |
| `errors`        | Tipos de erro estruturados, classificadores e o predicado canônico `Retryable()`.            |
| `observability` | Tracing, métricas e logs por meio de um único provider OpenTelemetry.                        |
| `retry`         | Opções de política de retry com backoff exponencial e jitter.                                |
| `sdkctx`        | Flags de context por request — chaves de idempotency, soft vs hard delete, include-deleted.  |
| `validation`    | Validação de input com mensagens de erro claras e estruturadas.                              |

#### Pacotes helpers

| Pacote        | O que ele resolve                                                         |
| :------------ | :------------------------------------------------------------------------ |
| `accounts`    | Helpers e funções de conveniência específicas para contas.                |
| `conversion`  | Helpers de conversão de tipos entre models e formatos externos.           |
| `data`        | Utilitários de dados e helpers de faker para testes e demos.              |
| `format`      | Utilitários para formatar dados no padrão Midaz (datas, horas etc.).      |
| `generator`   | Geração de demo e dados em massa para cenários ponta a ponta.             |
| `integrity`   | Utilitários de checksum e verificação de integridade.                     |
| `performance` | Helpers para tunar operações em lote e tarefas de alto throughput.        |
| `security`    | Utilitários de segurança, incluindo proteção contra SSRF e validação TLS. |
| `stats`       | Estatísticas de processamento e agregação de métricas.                    |
| `transaction` | Helpers de construção de transações e fluent builders.                    |
| `utils`       | Helpers de uso geral utilizados pelo SDK.                                 |
| `version`     | Metadados e identificação da versão do SDK.                               |

<Note>
  O pacote `pkg/access-manager` da v2 virou `pkg/auth` (assim o nome do diretório bate com o nome do pacote). O pacote `pkg/pagination` da v2 foi removido — sua superfície hoje vive em `models` e em cada serviço.
</Note>

## Autenticação

***

Na v4, o SDK exige exatamente uma fonte de autenticação no momento da construção. Chamar `midaz.New(...)` sem nenhuma retorna um erro de configuração tipado — chega de cascatas silenciosas de 401 na primeira chamada de API.

Você tem duas escolhas:

* **`midaz.WithAccessManager(...)`** — OAuth no formato de produção via Lerian Access Manager. Recomendado para qualquer stack não-local.
* **`midaz.WithAnonymous()`** — opt-out total de autenticação. Apropriado apenas para um stack Midaz local com auth desabilitada.

As duas opções são mutuamente exclusivas.

### Produção: Access Manager

Encaixe suas credenciais do Access Manager em `midaz.WithAccessManager`. O SDK busca um token inicial logo na construção, então erros de configuração aparecem como erros de configuração e não como uma cascata de 401.

<Warning>
  Substitua os valores no bloco `// Configure Access Manager` por suas próprias credenciais antes de executar.
</Warning>

<CodeGroup>
  ```go Go expandable theme={null}
  package main

  import (
  	"context"
  	"log"
  	"os"

  	"github.com/LerianStudio/midaz-sdk-golang/v4"
  )

  func main() {
  	// Configure Access Manager. ClientID and ClientSecret are typically
  	// loaded from environment variables — never hardcoded.
  	c, err := midaz.New(
  		midaz.WithEnvironment(midaz.EnvironmentProduction),
  		midaz.WithAccessManager(midaz.AccessManager{
  			Address:      "https://auth.midaz.io",
  			ClientID:     os.Getenv("MIDAZ_CLIENT_ID"),
  			ClientSecret: os.Getenv("MIDAZ_CLIENT_SECRET"),
  		}),
  	)
  	if err != nil {
  		log.Fatalf("midaz.New: %v", err)
  	}
  	defer c.Shutdown(context.Background())

  	// Use c.Organizations, c.Ledgers, c.Accounts, ... as usual.
  }
  ```
</CodeGroup>

O SDK pede um token ao seu Access Manager, anexa em toda chamada de API e renova automaticamente quando ele expira.

### Desenvolvimento local: Anonymous

Para um stack Midaz local com auth desabilitada, faça o opt-out de forma explícita:

<CodeGroup>
  ```go Go theme={null}
  c, err := midaz.New(
      midaz.WithEnvironment(midaz.EnvironmentLocal),
      midaz.WithAnonymous(),
  )
  ```
</CodeGroup>

### Configure via variáveis de ambiente

Você também pode apontar o SDK para o seu Access Manager via variáveis de ambiente. Exporte-as no seu shell ou no seu gerenciador de processos:

<CodeGroup>
  ```bash Bash theme={null}
  export PLUGIN_AUTH_ENABLED=true
  export PLUGIN_AUTH_ADDRESS=https://your-auth-service.com
  export MIDAZ_CLIENT_ID=your-client-id
  export MIDAZ_CLIENT_SECRET=your-client-secret
  ```
</CodeGroup>

<Note>
  `config.FromEnvironment()` lê o **ambiente do processo**, não um arquivo `.env`. Se você mantém variáveis em um arquivo `.env` durante o desenvolvimento, carregue-as com uma biblioteca como `godotenv` antes de chamar `config.NewConfig(config.FromEnvironment())`.
</Note>

Depois, faça o opt-in para o carregamento via env no momento de configurar:

<CodeGroup>
  ```go Go theme={null}
  import "github.com/LerianStudio/midaz-sdk-golang/v4/pkg/config"

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

  c, err := midaz.New(midaz.WithConfig(cfg))
  ```
</CodeGroup>

<Note>
  O carregamento via env é **explícito** na v4 — `config.FromEnvironment()` precisa estar na cadeia de opções. O SDK não lê mais env vars de forma implícita durante a construção.
</Note>

<Tip>
  Quer o passo a passo completo de auth? Confira o [Guia de autenticação](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/auth.md) no repositório do SDK.
</Tip>

## Multi-tenancy

***

**O escopo de tenant é derivado dos claims do Access Manager / JWT** usados para obter o token. O SDK aplica a identidade de tenant automaticamente com base nesses claims — nenhuma configuração extra no client.

Para rodar chamadas em outro escopo de tenant, use um conjunto separado de credenciais de Access Manager — ou construa um segundo cliente com seu próprio context de token.

## Listagem e iteração

***

Todo endpoint de listagem na v4 vem em três formatos. Escolha o que casa com seu caso de uso — eles são consistentes em todos os serviços.

| Método         | Retorna                              | Use quando                                                        |
| :------------- | :----------------------------------- | :---------------------------------------------------------------- |
| `ListXxx`      | `*models.ListResponse[T]` (uma page) | Você quer exatamente uma page e decide quando avançar.            |
| `ListXxxAll`   | `iter.Seq2[T, error]`                | Você quer todos os itens; o SDK cuida da paginação internamente.  |
| `ListXxxPages` | `iter.Seq2[*ListResponse[T], error]` | Você precisa de metadados de page para checkpointing ou batching. |

### Opções de listagem tipadas

Cada método de listagem recebe uma struct de opts tipada que embute uma de duas structs base, dependendo de como o endpoint pagina:

| Formato de paginação | Endpoints                                                                                                | Struct base                                                               |
| :------------------- | :------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------ |
| **Page-based**       | Organizations, Ledgers, Assets, Portfolios, Segments, Accounts, AccountTypes, Balances, Holders, Aliases | `models.PageListOpts{Limit, Page, SortDirection, StartDate, EndDate}`     |
| **Cursor-based**     | Transactions, Operations, OperationRoutes, TransactionRoutes, AssetRates                                 | `models.CursorListOpts{Limit, Cursor, SortDirection, StartDate, EndDate}` |

Cada endpoint também expõe uma sub-struct `Filters` tipada com apenas os campos que aquele endpoint realmente honra. Setar um campo no formato errado — por exemplo, `Page` em um endpoint cursor-based — falha em tempo de compilação, não silenciosamente em runtime.

### Itere todos os itens com `ListAll`

O formato mais idiomático: um `range` sobre todo item de toda page. O SDK avança cursors e busca pages internamente.

<CodeGroup>
  ```go Go theme={null}
  import (
      "github.com/LerianStudio/midaz-sdk-golang/v4"
      "github.com/LerianStudio/midaz-sdk-golang/v4/models"
  )

  opts := models.AccountsListOpts{
      PageListOpts: models.PageListOpts{Limit: 100},
      Filters: models.AccountsFilters{
          Status:    "ACTIVE",
          AssetCode: "USD",
      },
  }

  for account, err := range c.Accounts.ListAccountsAll(ctx, orgID, ledgerID, opts) {
      if err != nil {
          return fmt.Errorf("list accounts: %w", err)
      }
      process(account)
  }
  ```
</CodeGroup>

### Itere envelopes de page com `ListPages`

Quando você precisa de metadados de page — para checkpointing, batching ou para parar no meio de uma page —, itere por `ListXxxPages`. Cada entrada é um `*ListResponse[T]` com o bloco `Pagination` completo anexado.

<CodeGroup>
  ```go Go theme={null}
  opts := models.TransactionsListOpts{
      CursorListOpts: models.CursorListOpts{Limit: 50},
      Filters:        models.TransactionsFilters{Status: "APPROVED"},
  }

  for page, err := range c.Transactions.ListTransactionsPages(ctx, orgID, ledgerID, opts) {
      if err != nil {
          return fmt.Errorf("page iter: %w", err)
      }
      log.Printf("page=%d items=%d next_cursor=%q",
          page.Pagination.Page, len(page.Items), page.Pagination.NextCursor)

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

      if shouldStop(page) {
          break // The SDK aborts in-flight paging cleanly.
      }
  }
  ```
</CodeGroup>

Veja o [guia de Paginação](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/pagination.md) no repositório do SDK para a semântica de `HasMore()`, o tratamento de `NextCursor` e a tabela de decisão page-vs-cursor.

## Tratamento de erros

***

A maioria dos erros retornados pela camada de serviço do SDK é `*pkg/errors.Error` com campos estruturados:

| Campo       | O que carrega                                                               |
| :---------- | :-------------------------------------------------------------------------- |
| `Category`  | A classe do erro (validation, authentication, network, configuration etc.). |
| `Code`      | Um código string estável para branching ou telemetry.                       |
| `Operation` | A operação do SDK que produziu o erro (ex.: `Accounts.GetAccount`).         |
| `Resource`  | A família de recurso que o erro referencia, quando relevante.               |

Você pode ramificar com predicados tipados, percorrer os campos com `errors.As`, ou usar o método canônico `Retryable()` para guiar sua política de retry.

### Ramifique com predicados tipados

O SDK traz um conjunto completo de predicados `Is*` para você casar erros sem cutucar internals:

<CodeGroup>
  ```go Go expandable theme={null}
  import (
      "errors"
      "fmt"

      sdkerrors "github.com/LerianStudio/midaz-sdk-golang/v4/pkg/errors"
  )

  acc, err := c.Accounts.GetAccount(ctx, orgID, ledgerID, accountID)
  if err != nil {
      switch {
      case sdkerrors.IsNotFoundError(err):
          return fmt.Errorf("account not found: %w", err)
      case sdkerrors.IsAuthError(err):
          // Matches both 401 and 403 — re-authenticate or fix permissions.
          return fmt.Errorf("auth failure: %w", err)
      case sdkerrors.IsValidationError(err):
          return fmt.Errorf("invalid input: %w", err)
      case sdkerrors.IsConflictError(err):
          return fmt.Errorf("already exists: %w", err)
      case sdkerrors.IsRateLimitError(err):
          return fmt.Errorf("rate limited: %w", err)
      case sdkerrors.IsNetworkError(err):
          return fmt.Errorf("transient transport: %w", err)
      case sdkerrors.IsConfigurationError(err):
          return fmt.Errorf("setup mistake: %w", err)
      }

      // Walk the structured fields when you need them.
      var sdkErr *sdkerrors.Error
      if errors.As(err, &sdkErr) {
          log.Printf("op=%s resource=%s code=%s retryable=%v",
              sdkErr.Operation, sdkErr.Resource, sdkErr.Code, sdkErr.Retryable())
      }
  }
  ```
</CodeGroup>

### Guie decisões de retry com `Retryable()`

O método `Error.Retryable()` é a fonte canônica para política de retry. Use-o no lugar de construir sua própria classificação.

<CodeGroup>
  ```go Go theme={null}
  var sdkErr *sdkerrors.Error
  if errors.As(err, &sdkErr) && sdkErr.Retryable() {
      // Apply your retry logic — backoff, jitter, max attempts, etc.
  }
  ```
</CodeGroup>

### Embrulhe erros de transporte raw

Se você está chamando código HTTP de baixo nível fora do SDK e quer o mesmo formato de erro estruturado, use `ClassifyTransportError`:

<CodeGroup>
  ```go Go theme={null}
  import sdkerrors "github.com/LerianStudio/midaz-sdk-golang/v4/pkg/errors"

  resp, err := httpClient.Do(req)
  if err != nil {
      return sdkerrors.ClassifyTransportError("PaymentService.Charge", err)
  }
  ```
</CodeGroup>

### Validação local: FieldErrors

A validação local de input expõe `*pkg/validation.FieldErrors` — uma coleção estruturada de reclamações por campo emitidas pelo SDK antes de qualquer chamada HTTP. Use `errors.As` para inspecioná-las quando estiver validando input do usuário ou builders.

<CodeGroup>
  ```go Go theme={null}
  import (
      "errors"
      "fmt"

      "github.com/LerianStudio/midaz-sdk-golang/v4/pkg/validation"
  )

  var fieldErrs *validation.FieldErrors
  if errors.As(err, &fieldErrs) {
      for _, fe := range fieldErrs.Errs() {
          fmt.Printf("- %s: %s\n", fe.Field, fe.Message)
      }
  }
  ```
</CodeGroup>

<Tip>
  Quer mergulhar mais fundo? Confira o [guia de Tratamento de erros](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/errors.md) no repositório do SDK para o mapa completo de categorias, todos os códigos e a semântica das fronteiras de retry.
</Tip>

## Logging

***

Na v4, **`*slog.Logger` é a superfície canônica de logger**. Conecte-o via `midaz.WithLogger(...)`. O SDK é **silencioso por padrão** — ele usa `slog.DiscardHandler` até você fazer o opt-in.

Isso significa que você não vai ver linhas de log surpresa no seu stdout, e nem precisa brigar com o SDK por formato de log. Você decide o handler, o nível e o destino.

<CodeGroup>
  ```go Go expandable theme={null}
  package main

  import (
      "context"
      "log"
      "log/slog"
      "os"

      "github.com/LerianStudio/midaz-sdk-golang/v4"
  )

  func main() {
      logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
          Level: slog.LevelInfo,
      }))

      c, err := midaz.New(
          midaz.WithEnvironment(midaz.EnvironmentLocal),
          midaz.WithAnonymous(),
          midaz.WithLogger(logger),
      )
      if err != nil {
          log.Fatalf("midaz.New: %v", err)
      }
      defer c.Shutdown(context.Background())

      // SDK retry diagnostics, slow-call warnings, and other internal
      // log lines now flow through your handler.
  }
  ```
</CodeGroup>

Precisa de zap, zerolog ou charmbracelet/log? Todos integram como adapters de `slog.Handler` — o SDK não se importa qual backend produz os records, só que ele fale slog.

<Tip>
  Conectando zap, zerolog ou outro backend? O [guia de Logging](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/logging.md) traz receitas de adapter para todas as bibliotecas de logging comuns.
</Tip>

## Observabilidade

***

OpenTelemetry é first-class na v4. Um único provider de observabilidade te dá spans, métricas e logs correlacionados via OTel por meio de um único ponto de wiring.

Configure observabilidade passando um provider já construído, ou passando opções que o SDK monta para você.

### Conecte um provider

<CodeGroup>
  ```go Go expandable theme={null}
  package main

  import (
      "context"
      "log"

      "github.com/LerianStudio/midaz-sdk-golang/v4"
      "github.com/LerianStudio/midaz-sdk-golang/v4/pkg/observability"
  )

  func main() {
      ctx := context.Background()

      provider, err := observability.New(ctx,
          observability.WithServiceName("payments-api"),
          observability.WithEnvironment("production"),
          observability.WithComponentEnabled(true, true, true), // tracing, metrics, logs
      )
      if err != nil {
          log.Fatalf("observability.New: %v", err)
      }
      defer provider.Shutdown(ctx)

      c, err := midaz.New(
          midaz.WithEnvironment(midaz.EnvironmentProduction),
          midaz.WithAccessManager(midaz.AccessManager{ /* ... */ }),
          midaz.WithObservabilityProvider(provider),
      )
      if err != nil {
          log.Fatalf("midaz.New: %v", err)
      }
      defer c.Shutdown(ctx)
  }
  ```
</CodeGroup>

### Ou passe opções inline

<CodeGroup>
  ```go Go theme={null}
  import "github.com/LerianStudio/midaz-sdk-golang/v4/pkg/observability"

  c, err := midaz.New(
      midaz.WithEnvironment(midaz.EnvironmentProduction),
      midaz.WithAccessManager(am),
      midaz.WithObservabilityOptions(
          observability.WithServiceName("payments-api"),
          observability.WithComponentEnabled(true, true, true),
      ),
  )
  ```
</CodeGroup>

O SDK emite um span HTTP por request outbound com propagação correta de `traceparent` W3C. Os records de log de negócio carregam apenas IDs seguros — nunca payloads, nomes, endereços ou auth headers.

Você também pode embrulhar um bloco de lógica de negócio em um span via `Client.Trace`:

<CodeGroup>
  ```go Go theme={null}
  err = c.Trace("create-organization", func(ctx context.Context) error {
      _, err := c.Organizations.CreateOrganization(ctx, input)
      return err
  })
  ```
</CodeGroup>

<Warning>
  `WithObservabilityOptions` e `WithObservabilityProvider` usam **semântica de substituição**, não de merge. Cada chamada substitui qualquer provider previamente instalado. Para começar a partir de uma baseline, inclua `observability.WithDevelopmentDefaults` ou `observability.WithProductionDefaults` como a primeira opção na cadeia.
</Warning>

<Tip>
  Quer mergulhar mais fundo? Confira o [guia de Tracing](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/tracing.md) no repositório do SDK para os contratos de atributos de span, nomes de métricas e configuração de exporter.
</Tip>

## Idempotência

***

A auto-idempotency está **ligada por padrão** na v4. O SDK emite um header `X-Idempotency: <uuid>` em todo request HTTP unsafe (POST, PUT, PATCH, DELETE), então retries em falhas transientes não criam recursos em duplicidade.

Você pode sobrescrever a chave auto-gerada por chamada quando precisar de uma chave estável fornecida pelo caller — típico em passos de saga, linhas de outbox ou submissões dirigidas pela UI.

### Defina uma chave estável por request

<CodeGroup>
  ```go Go theme={null}
  import "github.com/LerianStudio/midaz-sdk-golang/v4/pkg/sdkctx"

  ctx := sdkctx.WithIdempotencyKey(context.Background(), "tx-2026-05-06-001")

  tx, err := c.Transactions.CreateTransaction(ctx, orgID, ledgerID, input)
  ```
</CodeGroup>

### Suprima a idempotency em uma chamada

Para os raros endpoints administrativos do tipo fire-and-forget, suprima o header por request:

<CodeGroup>
  ```go Go theme={null}
  ctx := sdkctx.WithoutAutoIdempotency(context.Background())

  err := c.SomeAdminService.DoOneShotThing(ctx, input)
  ```
</CodeGroup>

### Desative globalmente

Se você não quer auto-idempotency em lugar nenhum, desligue no nível do cliente:

<CodeGroup>
  ```go Go theme={null}
  c, err := midaz.New(
      midaz.WithEnvironment(midaz.EnvironmentLocal),
      midaz.WithAnonymous(),
      midaz.WithIdempotency(false),
  )
  ```
</CodeGroup>

Você também pode desativar via a variável de ambiente `MIDAZ_IDEMPOTENCY=false` quando estiver usando `config.FromEnvironment()`.

## Variáveis de ambiente

***

Você pode configurar o SDK via variáveis de ambiente, sem precisar hardcodar nada. O carregamento via env é **explícito** na v4 — passe `config.FromEnvironment()` na sua cadeia de opções de config para fazer o opt-in.

| Variável                | Descrição                                                                      |
| :---------------------- | :----------------------------------------------------------------------------- |
| `MIDAZ_ENVIRONMENT`     | Ambiente alvo (`local`, `development`, `production`).                          |
| `MIDAZ_BASE_URL`        | Base URL única usada quando URLs específicas de serviço não estão setadas.     |
| `MIDAZ_ONBOARDING_URL`  | Sobrescreve a base URL do serviço de onboarding.                               |
| `MIDAZ_TRANSACTION_URL` | Sobrescreve a base URL do serviço de transação.                                |
| `MIDAZ_CRM_URL`         | Sobrescreve a base URL do serviço de CRM (usado por Holders e Aliases).        |
| `PLUGIN_AUTH_ENABLED`   | Habilita a autenticação via Access Manager (`true` ou `false`).                |
| `PLUGIN_AUTH_ADDRESS`   | Endereço do serviço de Access Manager.                                         |
| `MIDAZ_CLIENT_ID`       | Client ID para a autenticação via Access Manager.                              |
| `MIDAZ_CLIENT_SECRET`   | Client secret para a autenticação via Access Manager.                          |
| `MIDAZ_TIMEOUT`         | Timeout de request HTTP em segundos.                                           |
| `MIDAZ_USER_AGENT`      | Header User-Agent customizado enviado em toda request.                         |
| `MIDAZ_DEBUG`           | Habilita logs de debug (`true` ou `false`).                                    |
| `MIDAZ_MAX_RETRIES`     | Tentativas máximas de retry para requests com falha.                           |
| `MIDAZ_IDEMPOTENCY`     | Habilita a geração automática de chave de idempotency em requests unsafe.      |
| `MIDAZ_SKIP_AUTH_CHECK` | Pula a validação da config do Access Manager na inicialização (apenas testes). |

Para a matriz completa de opções entre `midaz`, `pkg/config` e `pkg/sdkctx`, consulte o [guia de Configuração](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/configuration.md) no repositório do SDK.

## Projetos de exemplo

***

<Tip>
  O SDK vem com um tour numerado das suas capacidades core (exemplos 01–10) mais um conjunto de exemplos avançados e de referência. O conjunto numerado é de **tutoriais focados**: cada um ensina exatamente um conceito com o menor corpo possível. Navegue por eles no [diretório de exemplos](https://github.com/LerianStudio/midaz-sdk-golang/tree/main/examples) no GitHub.
</Tip>

<Columns cols={2}>
  | Exemplo                 | O que ele demonstra                                                |
  | :---------------------- | :----------------------------------------------------------------- |
  | `01-hello-world`        | Init mínimo mais a primeira chamada de API (\~17 linhas de corpo). |
  | `02-auth`               | Autenticação via Access Manager (configuração de produção).        |
  | `03-end-to-end`         | Org → ledger → asset → account → transaction.                      |
  | `04-listing-cursor`     | Paginação cursor-based com `iter.Seq2`.                            |
  | `05-listing-pages`      | Paginação page-based — `List` / `ListAll` / `ListPages`.           |
  | `06-idempotency`        | Modos de idempotency auto / explícito / suprimido.                 |
  | `07-retries`            | Política padrão, política customizada, retries desabilitados.      |
  | `08-logging-slog`       | Integração com `*slog.Logger` (logging da v4).                     |
  | `09-testing-with-mocks` | `go.uber.org/mock` para teste unitário do seu código contra o SDK. |
  | `10-observability-otel` | Superfície completa de OpenTelemetry (tracing + métricas + logs).  |
</Columns>

O repositório também inclui exemplos especializados e de referência — `concurrency`, `configuration`, `context`, `tracing`, `tracing-server`, `pkg-validation-demo`, `mass-demo-generator` e `workflow-with-entities`. Eles cobrem padrões avançados (paralelismo limitado, propagação de context OTel entre processos, geração massiva de dados) para quando você passou do conjunto focado.

## Migrando da v2

***

A v4 é uma **major version de corte limpo, sem janela de depreciação**. Não há release transicional, não há shim `// Deprecated:`, não há alias retrocompatível da superfície antiga. Troque seu import de `/v2` para `/v4` e percorra as breaking changes com os exemplos lado a lado no guia de migração.

As maiores mudanças para planejar:

* **Caminho do módulo e nome do pacote**: `github.com/LerianStudio/midaz-sdk-golang/v4` (era `/v2`), pacote `midaz` (era `client`).
* **Autenticação**: `WithAuthToken` foi embora. Use `WithAccessManager` para produção ou `WithAnonymous` para stacks locais. Uma fonte de auth é obrigatória na construção.
* **Acesso a serviços**: `c.Accounts.X` (era `c.Entity.Accounts.X`). O campo `c.Entity` ainda existe por compatibilidade, mas todo exemplo usa a forma curta.
* **Paginação**: `models.ListOptions` e seus 30 fluent setters foram embora. Use as opts tipadas por endpoint (`models.AccountsListOpts`, `models.TransactionsListOpts`, ...) e os novos iteradores `ListAll` / `ListPages`.
* **Erros**: `*MidazError` foi embora. Erros da camada de serviço agora usam `*pkg/errors.Error` com `Retryable()` como fonte oficial de retry. Validação local pode expor `*pkg/validation.FieldErrors`.
* **Identidade de tenant**: `WithTenantID`, a variável de ambiente `MIDAZ_TENANT_ID` e o header `X-Tenant-ID` foram embora. O escopo de tenant flui pelos claims do Access Manager / JWT.
* **Logging**: `*slog.Logger` substitui a interface dedicada `observability.Logger` como superfície canônica. O SDK é silencioso por padrão.

Para o passo a passo completo com código v2 / v3 lado a lado em toda breaking change, leia o [Guia de migração da v2 para v3](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/migration-v2-to-v3.md).

## Explore as APIs

***

Para mais informações sobre as APIs, consulte os links a seguir:

<Columns cols={2}>
  <Card title="Mapeamento da API externa" icon="link" horizontal href="https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/mapping/external_apis.md" />

  <Card title="Mapeamento da API interna" icon="link" horizontal href="https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/mapping/internal_apis.md" />

  <Card title="Documentação Godoc" icon="books" horizontal href="https://pkg.go.dev/github.com/LerianStudio/midaz-sdk-golang/v4" />
</Columns>
