> ## 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.

# SDK do Midaz para Go

> Crie aplicações Go sobre o Midaz com o SDK v4 oficial: paginação tipada, erros estruturados e observabilidade OpenTelemetry prontas para uso.

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

<Warning>
  **Vindo da v2?** A v4 é uma versão major limpa, com mudanças que quebram compatibilidade em autenticação, paginação, erros e acesso a serviços. Não há período de depreciação. Você troca o import de `/v2` para `/v4` e migra ao mesmo tempo.

  Veja [Migrando da v2](#migrating-from-v2) antes de atualizar.
</Warning>

## Primeiros passos

***

### Passo 1 – Instalar 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 – Criar ou usar um projeto Go existente

**Criar um projeto Go:**

Para criar um projeto Go, use o comando a seguir:

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

**Usar um projeto Go existente:**

Se você já está trabalhando em um projeto existente, confirme que há um arquivo `go.mod` na raiz. Caso não haja, execute o comando a seguir para criar um:

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

### Passo 3 – Adicionar o SDK do Midaz

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

<Warning>
  **O caminho do módulo exige o sufixo `/v4`.** Se você omitir esse sufixo, o Go resolve uma versão desatualizada anterior à v4, que não traz nenhuma das mudanças lançadas 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>
  No VS Code ou no GoLand, sua IDE pode executar `go get` automaticamente quando você importa um pacote novo.
</Tip>

### Passo 4 – Importar o SDK

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

<Note>
  O exemplo abaixo é para uma stack local do Midaz com autenticação desabilitada. Se você ainda não tem uma rodando, veja [Primeiros passos com o Midaz](/pt/start-here/getting-started) para subir uma 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 oferece acesso a:

* O cliente do Midaz para chamar todos os serviços da API.
* Modelos de dados prontos (como `CreateOrganizationInput`).
* Autenticação via **Access Manager** (produção) ou **Anônimo** (desenvolvimento local).
* Um sistema de configuração tipado que falha rápido no momento da construção.

<Tip>
  Para a configuração completa, veja a seção [Autenticação](#authentication).
</Tip>

### Passo 5 – Executar o projeto

Execute o comando a seguir:

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

## Arquitetura do SDK

***

Cada serviço é acessível diretamente no cliente. Cada método de listagem segue o mesmo formato de trio. Cada erro é estruturado. Cada opção falha rápido no momento da construção.

#### Design em camadas

| Camada               | O que ela trata                                                                                              |
| :------------------- | :----------------------------------------------------------------------------------------------------------- |
| **Client**           | O ponto de entrada principal — `midaz.New(...)` conecta autenticação, novas tentativas e observabilidade.    |
| **Services**         | Acesso de alto nível a cada domínio do Midaz, exposto como campos promovidos no cliente.                     |
| **Models**           | As estruturas de dados principais que espelham a lógica de domínio do Midaz, reexportadas no pacote `midaz`. |
| **Utility packages** | Helpers modulares para configuração, erros, observabilidade, novas tentativas, idempotência, entre outros.   |

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

<Tip>
  Para o design por trás da reescrita, veja o [guia de arquitetura](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/architecture.md).
</Tip>

### Services

A camada `Services` é o seu ponto de acesso a cada domínio do Midaz. Cada serviço trata uma família de recursos e expõe todos os seus métodos como parte de uma única interface. Não existe um toggle `UseAllAPIs()` nem uma etapa de registro de serviço. Cada serviço fica pronto para uso assim 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 cotações de ativos.                  |
| `c.Accounts`          | Gerencia contas e verifica saldos.                     |
| `c.AccountTypes`      | Gerencia definições de tipo de conta.                  |
| `c.Portfolios`        | Agrupa contas em portfólios.                           |
| `c.Segments`          | Categoriza contas usando segmentos.                    |
| `c.Transactions`      | Cria e pesquisa transações financeiras.                |
| `c.TransactionRoutes` | Define e gerencia regras de rota de transação.         |
| `c.Operations`        | Detalha as operações atômicas dentro de uma transação. |
| `c.OperationRoutes`   | Define e gerencia regras de rota de operação.          |
| `c.Balances`          | Obtém saldos de conta em tempo real.                   |
| `c.Holders`           | Gerencia titulares de conta no CRM.                    |
| `c.Aliases`           | Gerencia aliases de CRM para contas e entidades.       |
| `c.MetadataIndexes`   | Gerencia índices de metadados pesquisáveis.            |

### Models

Cada tipo de modelo está diretamente ligado 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 com múltiplas pernas.

Na v4, os tipos de modelo mais comuns são reexportados no próprio pacote `midaz`. Isso significa que `midaz.Account` e `models.Account` são o mesmo tipo, e a maior parte do código precisa de apenas um import.

#### Tipos de modelo comuns

| Modelo               | O que ele representa                                                             |
| :------------------- | :------------------------------------------------------------------------------- |
| `midaz.Organization` | Uma entidade de negócio que é dona de 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 rastrear 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`    | Um lançamento individual de débito ou crédito dentro de uma transação.           |
| `midaz.Balance`      | O estado atual das posições de uma conta.                                        |

<Tip>
  Para um builder, um formato de requisição interno ou um tipo descontinuado, importe `github.com/LerianStudio/midaz-sdk-golang/v4/models` diretamente. Todo tipo vive lá, e os aliases de `midaz` preservam a identidade do tipo, então os dois caminhos de import interoperam sem conflitos.
</Tip>

### Utility packages

Dentro da pasta `pkg` do SDK, você encontra pacotes utilitários para tratamento de configuração, políticas de novas tentativas e primitivas de segurança. Eles se dividem em dois grupos. Os pacotes **Core** atendem preocupações transversais do SDK. Os pacotes **Helper** oferecem utilitários específicos de domínio ou de baixo nível.

#### Core packages

| 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 configuração, overrides de variáveis de ambiente e URLs de serviço personalizadas. |
| `concurrent`    | Ferramentas para lotes, 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 provedor OpenTelemetry.                                         |
| `retry`         | Opções de política de novas tentativas com backoff exponencial e jitter.                                      |
| `sdkctx`        | Flags de contexto por requisição — chaves de idempotência, soft delete vs. hard delete, include-deleted.      |
| `validation`    | Validação de entrada com mensagens de erro claras e estruturadas.                                             |

#### Helper packages

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

<Note>
  O pacote `pkg/access-manager` da v2 foi movido para `pkg/auth` (para que o diretório corresponda ao nome do pacote). O pacote `pkg/pagination` da v2 foi removido. Sua superfície hoje vive em `models` e em cada serviço.
</Note>

<h2 id="authentication">
  Autenticação
</h2>

***

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

Você tem duas opções:

* **`midaz.WithAccessManager(...)`**: OAuth no formato de produção via o Lerian Access Manager. Recomendado para qualquer stack que não seja local.
* **`midaz.WithAnonymous()`**: desativa a autenticação por completo. Adequado apenas para uma stack local do Midaz com autenticação desabilitada.

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

### Produção: Access Manager

Conecte suas credenciais do Access Manager a `midaz.WithAccessManager`. O SDK busca um token inicial de forma antecipada, já no momento da construção, então configurações incorretas aparecem como erros de configuração, em vez de gerar cascatas de 401.

<Warning>
  Substitua os valores no bloco `// Configure Access Manager` pelas 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 solicita um token ao seu Access Manager, anexa esse token a cada chamada de API e o renova automaticamente quando ele expira.

### Desenvolvimento local: Anônimo

Para uma stack local do Midaz com autenticação desabilitada, desative a autenticação explicitamente:

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

### Configurar via variáveis de ambiente

Você também pode apontar o SDK para o seu Access Manager usando 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 de 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, habilite o carregamento por ambiente no momento da configuração:

<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 por ambiente é **explícito** na v4. `config.FromEnvironment()` deve estar na cadeia de opções. O SDK não lê mais variáveis de ambiente de forma implícita durante a construção.
</Note>

<Tip>
  Para o passo a passo completo de autenticação, veja 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 do tenant vem do Access Manager / das claims do JWT** usadas para obter o token. O SDK aplica a identidade do tenant automaticamente a partir dessas claims. O lado do cliente não precisa de nenhuma configuração extra.

Para executar chamadas em um escopo de tenant diferente, use um conjunto separado de credenciais do Access Manager, ou construa um segundo cliente com seu próprio contexto de token.

## Listagem e iteração

***

Cada endpoint de listagem na v4 vem em três formatos. Escolha o que corresponde ao seu caso de uso. Eles são consistentes em todos os serviços.

| Método         | Retorna                                | Use quando                                                                                |
| :------------- | :------------------------------------- | :---------------------------------------------------------------------------------------- |
| `ListXxx`      | `*models.ListResponse[T]` (uma página) | Você quer exatamente uma página e decide quando avançar.                                  |
| `ListXxxAll`   | `iter.Seq2[T, error]`                  | Você quer cada item; o SDK trata a paginação internamente.                                |
| `ListXxxPages` | `iter.Seq2[*ListResponse[T], error]`   | Você precisa de metadados no nível de página para checkpointing ou processamento em lote. |

### Opções de listagem tipadas

Cada método de listagem recebe uma struct de opções tipada que incorpora uma de duas structs base, dependendo de como o endpoint pagina:

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

Cada endpoint também expõe uma sub-struct `Filters` tipada, apenas com os campos que esse endpoint realmente aceita. Definir um campo na struct errada (por exemplo, `Page` em um endpoint baseado em cursor) falha em tempo de compilação, não silenciosamente em tempo de execução.

### Iterar por cada item com `ListAll`

O formato mais idiomático é um loop `range` sobre cada item em todas as páginas. O SDK avança os cursores e busca as páginas 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>

### Iterar envelopes de página com `ListPages`

Quando você precisa de metadados no nível de página (para checkpointing, processamento em lote ou para parar no meio de uma página), itere sobre `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 entre página e cursor.

## Tratamento de erros

***

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

| Campo       | O que ele carrega                                                                  |
| :---------- | :--------------------------------------------------------------------------------- |
| `Category`  | A classe do erro (validação, autenticação, rede, configuração e assim por diante). |
| `Code`      | Um código de string estável, adequado para ramificação de lógica ou telemetria.    |
| `Operation` | A operação do SDK que produziu o erro (por exemplo, `Accounts.GetAccount`).        |
| `Resource`  | A família de recursos à qual o erro se refere, quando relevante.                   |

Você pode ramificar a lógica com predicados tipados, percorrer campos com `errors.As`, ou usar o método canônico `Retryable()` para orientar a política de novas tentativas.

### Ramificar com predicados tipados

O SDK vem com um conjunto completo de predicados `Is*`, para você reconhecer erros sem mexer nos detalhes internos:

<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>

### Guiar decisões de novas tentativas com `Retryable()`

O método `Error.Retryable()` é a fonte canônica da política de novas tentativas. Use-o em vez de criar 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>

### Envolver erros brutos de transporte

Se você está chamando código HTTP de nível mais baixo 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 entrada expõe `*pkg/validation.FieldErrors`, uma coleção estruturada de reclamações por campo geradas pelo SDK antes de qualquer chamada HTTP. Use `errors.As` para inspecioná-las ao validar entradas de 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>
  Para o mapa completo de categorias, todos os códigos e a semântica dos limites de nova tentativa, veja o [guia de tratamento de erros](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/errors.md) no repositório do SDK.
</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ê habilitar o logging.

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>

zap, zerolog e charmbracelet/log se integram como adapters de `slog.Handler`. O SDK funciona com qualquer backend que fale slog.

<Tip>
  O [guia de logging](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/logging.md) tem receitas de adapters para todas as bibliotecas de logging mais comuns.
</Tip>

## Observabilidade

***

O OpenTelemetry é um recurso de primeira classe na v4. Um único provedor de observabilidade oferece spans, métricas e logs correlacionados via OTel, através de um único ponto de conexão.

Configure a observabilidade passando um provedor já pronto, ou passando opções que o SDK monta para você.

### Conectar um provedor

<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 passar 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 requisição de saída, com propagação adequada do `traceparent` do W3C. Os registros de log de negócio carregam apenas IDs seguros, nunca payloads, nomes, endereços ou headers de autenticação.

Você também pode envolver um bloco de lógica de negócio em um span usando `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 provedor instalado anteriormente. Para partir de uma base, inclua `observability.WithDevelopmentDefaults` ou `observability.WithProductionDefaults` como a primeira opção na cadeia.
</Warning>

<Tip>
  Veja o [exemplo `10-observability-otel`](https://github.com/LerianStudio/midaz-sdk-golang/tree/main/examples/10-observability-otel) no repositório do SDK para atributos de span, nomes de métrica e configuração de exporter.
</Tip>

## Idempotência

***

A idempotência automática vem **habilitada por padrão** na v4. O SDK emite um header `X-Idempotency: <uuid>` em toda requisição HTTP insegura (POST, PUT, PATCH, DELETE). Assim, novas tentativas em falhas transitórias não criam recursos duplicados.

Você pode sobrescrever a chave gerada automaticamente por chamada quando precisar de uma chave estável, fornecida por quem chama. Isso é comum em etapas de saga, linhas de outbox ou envios orientados por UI.

### Definir uma chave estável por requisição

<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>

### Suprimir a idempotência para uma chamada

Para endpoints administrativos raros do tipo fire-and-forget, suprima o header por requisição:

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

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

### Desabilitar globalmente

Se você não quer idempotência automática em nenhum lugar, desative-a 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 desativá-la usando a variável de ambiente `MIDAZ_IDEMPOTENCY=false` ao usar `config.FromEnvironment()`.

## Variáveis de ambiente

***

Você pode configurar o SDK com variáveis de ambiente em vez de valores fixos no código. O carregamento por ambiente é **explícito** na v4. Passe `config.FromEnvironment()` na sua cadeia de opções de configuração para habilitá-lo.

| Variável              | Descrição                                                                                                       |
| :-------------------- | :-------------------------------------------------------------------------------------------------------------- |
| `MIDAZ_ENVIRONMENT`   | Ambiente de destino (`local`, `development`, `production`).                                                     |
| `MIDAZ_BASE_URL`      | URL base para todos os serviços do Midaz, usada quando as URLs específicas de cada serviço não estão definidas. |
| `MIDAZ_LEDGER_URL`    | URL da API do Ledger. Ela atende os endpoints de onboarding e transação.                                        |
| `MIDAZ_CRM_URL`       | URL da API de CRM. Usada 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 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 da requisição HTTP, em segundos.                                                                        |
| `MIDAZ_DEBUG`         | Habilita logs de debug (`true` ou `false`).                                                                     |
| `MIDAZ_MAX_RETRIES`   | Número máximo de novas tentativas para requisições que falharem. Defina `0` para desativar as novas tentativas. |
| `MIDAZ_IDEMPOTENCY`   | Habilita chaves de idempotência automáticas para requisições inseguras (`true` ou `false`).                     |

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

## Exemplos de projetos

***

<Tip>
  O SDK vem com um tour numerado pelas suas capacidades principais (exemplos 01–10), além de um conjunto de exemplos avançados e de referência. O conjunto numerado é formado por **tutoriais focados**: cada um ensina exatamente um conceito, com o corpo de código menor 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`        | Inicialização mínima 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 → ativo → conta → transação.                                   |
  | `04-listing-cursor`     | Paginação baseada em cursor com `iter.Seq2`.                                |
  | `05-listing-pages`      | Paginação baseada em página — `List` / `ListAll` / `ListPages`.             |
  | `06-idempotency`        | Modos de idempotência automática / explícita / suprimida.                   |
  | `07-retries`            | Política padrão, política personalizada, novas tentativas desativadas.      |
  | `08-logging-slog`       | Integração com `*slog.Logger` (logging da v4).                              |
  | `09-testing-with-mocks` | `go.uber.org/mock` para testar unitariamente seu código contra o SDK.       |
  | `10-observability-otel` | Superfície completa do 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 contexto OTel entre processos, geração de dados em massa) para quando o conjunto focado já não for suficiente.

<h2 id="migrating-from-v2">
  Migrando da v2
</h2>

***

A v4 é uma **versão major com corte limpo e sem período de depreciação**. Não há release de transição, nem shim `// Deprecated:`, nem alias compatível com versões anteriores para a superfície antiga. Troque o import de `/v2` para `/v4` e percorra as mudanças que quebram compatibilidade a seguir.

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` não existe mais. Use `WithAccessManager` para produção ou `WithAnonymous` para stacks locais. Uma fonte de autenticação é obrigatória no momento da construção.
* **Acesso a serviços**: `c.Accounts.X` (era `c.Entity.Accounts.X`). O campo `c.Entity` ainda existe por compatibilidade, mas todos os exemplos usam a forma curta.
* **Paginação**: `models.ListOptions` e seus 30 setters fluentes não existem mais. Use as opções tipadas por endpoint (`models.AccountsListOpts`, `models.TransactionsListOpts`, ...) e os novos iteradores `ListAll` / `ListPages`.
* **Erros**: `*MidazError` não existe mais. Os erros da camada de serviço agora usam `*pkg/errors.Error`, com `Retryable()` como a fonte oficial de decisão de nova tentativa. A validação local pode expor `*pkg/validation.FieldErrors`.
* **Identidade do tenant**: `WithTenantID`, a variável de ambiente `MIDAZ_TENANT_ID` e o header `X-Tenant-ID` não existem mais. O escopo do tenant flui através do Access Manager / das claims do JWT.
* **Logging**: `*slog.Logger` substitui a interface `observability.Logger` sob medida como a superfície canônica. O SDK é silencioso por padrão.

Para os detalhes das mudanças de autenticação, veja o [guia de autenticação](https://github.com/LerianStudio/midaz-sdk-golang/blob/main/docs/auth.md) no repositório do SDK. O [diretório de exemplos](https://github.com/LerianStudio/midaz-sdk-golang/tree/main/examples) mostra a API v4 na prática.

## Explore as APIs

***

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

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

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

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