Skip to main content
Configurable client options ship in v1.2.0. See the Changelog before upgrading.

Initialize the client

Your Blnk client is the single entry point to everything: ledgers, balances, transactions, reconciliation, and more. Configure it once when your app starts, then use it everywhere.
client.go
package blnk

import (
	"net/url"
	"os"
	"time"

	blnkgo "github.com/blnkfinance/blnk-go"
)

func NewBlnkClient() *blnkgo.Client {
	baseURL, _ := url.Parse(os.Getenv("BLNK_BASE_URL"))
	if baseURL == nil || baseURL.String() == "" {
		baseURL, _ = url.Parse("http://localhost:5001/")
	}

	apiKey := os.Getenv("BLNK_API_KEY")
	return blnkgo.NewClient(
		baseURL,
		&apiKey,
		blnkgo.WithTimeout(10*time.Second),
		blnkgo.WithRetry(2),
	)
}
That’s it. One import, one call, one client. From here you can create ledgers, move money, reconcile transactions, and manage your entire financial infrastructure.
create-ledger.go
client := NewBlnkClient()

ledger, resp, err := client.Ledger.Create(blnkgo.CreateLedgerRequest{
	Name: "Customer Savings Account",
	MetaData: map[string]interface{}{
		"project_owner": "YOUR_APP_NAME",
	},
})
if err != nil {
	return err
}

fmt.Printf("Ledger created (HTTP %d): %s\n", resp.StatusCode, ledger.LedgerID)
Per-method SDK pages in the sidebar list each call on client.Ledger, client.LedgerBalance, and other services.

Authentication

NewClient takes a base URL and an optional API key pointer. The SDK sends the key on every request in the X-Blnk-Key header when you pass a non-nil pointer. How you set the API key depends on whether Core runs in secure mode:
When server.secure is enabled, pass a pointer to your API key as the second argument.
apiKey := os.Getenv("BLNK_API_KEY")
client := blnkgo.NewClient(baseURL, &apiKey)

Secure Blnk

Secure mode, master key, and server hardening.

Scoped API keys

Owner-scoped keys and permission limits.

Timeouts and retries

When connections fail, Core restarts, or requests hang, the SDK handles it without blocking your app. Pass functional options to NewClient to tune behavior:
client := blnkgo.NewClient(
	baseURL,
	&apiKey,
	blnkgo.WithTimeout(30*time.Second),
	blnkgo.WithRetry(3),
	blnkgo.WithRetryDelay(2*time.Second),
)
OptionTypeDefaultWhat it does for you
WithTimeouttime.Duration10sHow long to wait before giving up on a request. Bump this for slow operations like bulk reconciliations.
WithRetryint1Total attempts including the first try. 1 means no retries. 3 means up to three attempts.
WithRetryDelaytime.Duration2sBase delay between retries. Uses linear backoff.
When to tune these:
  • Keep defaults if you’re making fast, local calls and want to fail fast.
  • Increase WithTimeout if you’re running large batch requests that may take a while to complete synchronously.
  • Increase WithRetry if you’re reading data across an unreliable network.
Retries apply to idempotent GET requests and retryable network failures. POST, PUT, and DELETE are not retried on HTTP errors.

Custom logger

By default, the SDK logs retry and transport events through a built-in logger that writes to stdout with INFO: and ERROR: prefixes. Pass a type that implements blnkgo.Logger to route these messages to your own logging system instead of stdout.
type appLogger struct{}

func (l appLogger) Info(msg string)  { log.Println("info:", msg) }
func (l appLogger) Error(msg string) { log.Println("error:", msg) }

client := blnkgo.NewClient(
	baseURL,
	&apiKey,
	blnkgo.WithLogger(appLogger{}),
)
LevelWhen the SDK calls it
InfoBefore a retry, or when a retryable network failure will be retried
ErrorWhen a request returns a retryable HTTP status on a GET, or exhausts retry attempts

Building transaction requests

Call client.Transaction.Create and pass a blnkgo.CreateTransactionRequest struct. It has two parts:
  1. ParentTransaction holds the core transaction fields: amount, currency, source, destination, reference, and metadata.
  2. Top-level fields control how the request is processed, such as AllowOverdraft, Inflight, and ScheduledFor.
ParentTransaction is an embedded struct in the Go SDK, not a field in the API request body. The API expects flat JSON with fields like amount and source at the root.Do not confuse this struct with the API response field parent_transaction, which is a transaction ID linking related records such as inflight commits or split distributions.
blnkgo.CreateTransactionRequest{
	ParentTransaction: blnkgo.ParentTransaction{
		PreciseAmount: 100000,
		Precision: 100,
		Currency: "USD",
		Source: "bln_28f25ef6-2e0d-4fa6",
		Destination: "bln_86ba7976-499d-4282",
		Reference: "payment_001",
	},
	AllowOverdraft: true,
}
Transactions are the exception. Every other resource uses a single request struct with no nesting. Pass CreateLedgerRequest to client.Ledger.Create, CreateLedgerBalanceRequest to client.LedgerBalance.Create, and so on.

JSON field names

Go struct fields use PascalCase, like MetaData and LedgerID. These map to the API’s snake_case JSON fields (meta_data, ledger_id). You should always use the Go field names in your code.

Date and time fields

Fields such as DOB, EffectiveDate, ScheduledFor, InflightCommitDate, and historical balance timestamps use time.Time (or *time.Time). Parse ISO 8601 strings with time.Parse(time.RFC3339, "..."), for example "2024-04-22T15:28:03Z" or "2024-12-21T01:36:46+01:00", then pass the resulting value. Use a pointer when the field is optional so zero values omit from JSON.

Quick start

Install the SDK and create your first transaction.

Error handling

Three-value returns and Core error bodies.

Changelog

Go SDK releases and version history.

Go SDK examples

Escrow, savings, cards, and reconciliation.

Need help?

We are very happy to help you make the most of Blnk, regardless of whether it is your first time or you are switching from another tool. To ask questions or discuss issues, please contact us or join our Discord community.