A complete, production-grade Go client for the Moov API,
structured with Domain-Driven Design — each API resource group is its own
package with explicit types and a Service struct, with only moov.go in the
root acting as the façade entry point.
Zero external runtime dependencies. Go 1.25.
moov-go/
├── moov.go ← only .go file in root: Client, New(), all option funcs
│
├── types/ ← shared primitives (Amount, Address, TransferSource…)
├── errors/ ← public APIError type + IsNotFound/IsTransient helpers
├── webhook/ ← HMAC-SHA512 signature verification + event parsing
│
├── internal/
│ └── httpclient/ ← HTTP engine (not part of public API)
│ ├── client.go ← Do / DoRaw / UploadFile + auth + retry
│ ├── options.go ← Option / RequestOption functional options
│ ├── retry.go ← exponential backoff with full jitter
│ ├── idempotency.go ← UUID v4 via crypto/rand
│ └── query.go ← reflect-based URL query encoder
│
├── accounts/ ← bounded context: Moov accounts
├── capabilities/
├── representatives/
├── underwriting/
├── billing/
├── files/
├── onboarding/
├── resolution/
├── partner/
├── bankaccounts/ ← bounded context: sources
├── cards/
├── applepay/
├── googlepay/
├── paymentmethods/
├── terminal/
├── wallets/
├── transfers/ ← bounded context: money movement
├── sweeps/
├── refunds/
├── disputes/
├── issuing/
├── invoices/
├── paymentlinks/
├── receipts/
├── schedules/
├── images/ ← bounded context: account tools
├── products/
├── support/
├── branding/ ← bounded context: enrichment
├── enrichment/
├── institutions/
├── auth/ ← bounded context: authentication
├── e2ee/
└── ping/
go get github.com/fintech-sdk/moov-goimport (
"github.com/fintech-sdk/moov-go"
"github.com/fintech-sdk/moov-go/accounts"
"github.com/fintech-sdk/moov-go/transfers"
"github.com/fintech-sdk/moov-go/types"
)
// Build a client (only needs to happen once)
client := moov.NewClientWithBasicAuth(
os.Getenv("MOOV_PUBLIC_KEY"),
os.Getenv("MOOV_PRIVATE_KEY"),
moov.WithAPIVersion("v2026.04.00"),
)
// Use the all-in-one façade
m := moov.New(client)
// Create an account
account, err := m.Accounts.Create(ctx, accounts.CreateRequest{
AccountType: accounts.AccountTypeBusiness,
Profile: accounts.Profile{
Business: &accounts.BusinessProfile{
LegalBusinessName: "Whole Body Fitness LLC",
},
},
})
// Create a transfer
transfer, err := m.Transfers.Create(ctx, account.AccountID, transfers.CreateRequest{
Source: types.TransferSource{PaymentMethodID: srcPMID},
Destination: types.TransferDestination{PaymentMethodID: dstPMID},
Amount: types.Amount{Currency: "USD", Value: 2500},
})Or use domain services directly without the façade:
import "github.com/fintech-sdk/moov-go/accounts"
svc := accounts.NewService(client)
account, err := svc.Create(ctx, accounts.CreateRequest{...})import mooverr "github.com/fintech-sdk/moov-go/errors"
account, err := m.Accounts.Get(ctx, accountID)
if mooverr.IsNotFound(err) {
return nil, nil // 404 — account doesn't exist
}
var e *mooverr.APIError
if errors.As(err, &e) {
log.Printf("status=%d type=%s requestID=%s", e.StatusCode, e.Type, e.RequestID)
}Transfers.Create auto-generates a UUID v4 key reused across every retry. Pin
your own for cross-restart safety:
m.Transfers.Create(ctx, accountID, req,
moov.WithIdempotencyKey("order-"+order.ID),
)transfer, err := m.Transfers.Create(ctx, accountID, req,
moov.WithWaitFor("rail-response"),
)
// transfer.Status, transfer.Source.ACHDetails, etc. are now populatedimport "github.com/fintech-sdk/moov-go/webhook"
event, err := webhook.ParseEvent(r.Header, body, webhookSecret)
if errors.Is(err, webhook.ErrInvalidSignature) {
http.Error(w, "bad signature", 400)
return
}
switch event.Type {
case "transfer.updated":
var payload MyTransferPayload
json.Unmarshal(event.Data, &payload)
}srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(accounts.Account{AccountID: "acct_test"})
}))
defer srv.Close()
client := moov.NewClientWithBasicAuth("pub", "priv",
moov.WithBaseURL(srv.URL),
moov.WithMaxRetries(0),
)
svc := accounts.NewService(client)MIT — not officially affiliated with or endorsed by Moov Financial, Inc.