Skip to content

fintech-sdk/moov-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

moov-go

Go Reference CI

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.


Project structure

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/

Installation

go get github.com/fintech-sdk/moov-go

Quick start

import (
    "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{...})

Error handling

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

Idempotency

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

Synchronous transfers

transfer, err := m.Transfers.Create(ctx, accountID, req,
    moov.WithWaitFor("rail-response"),
)
// transfer.Status, transfer.Source.ACHDetails, etc. are now populated

Webhook verification

import "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)
}

Testing

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)

License

MIT — not officially affiliated with or endorsed by Moov Financial, Inc.

About

A complete, production-grade Go client for the [Moov API](https://docs.moov.io/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.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages