CI Hex.pm Documentation Coverage License: MIT

A production-grade Elixir hex package for the ClearBank UK API.

Features

  • Complete API coverage — GBP Accounts, GBP Payments, Multi-currency & FX, Embedded Banking
  • RSA-SHA256 digital signatures — PKCS#1 v1.5, HSM-compatible
  • Webhook verification & dispatch — signature verification, idiomatic Handler behaviour
  • Multi-tenant — per-call client structs for multiple credential sets
  • NimbleOptions config validation — fail-fast with clear error messages
  • Telemetry — all requests emit structured events
  • Client-side rate limiter — token-bucket GenServer
  • Typed errors%ClearBank.Error{} with retryable?/1
  • Full test suite — ExUnit + Bypass HTTP mocking
  • CI matrix — Elixir 1.14–1.16, OTP 25–26
  • Dialyzer + Credo — strict type checking and linting
  • ExDoc with grouped module navigation and guides

Supported APIs

AreaModules
GBP AccountsAccounts, Accounts.Transactions, Accounts.BacsPaymentData, Accounts.Reporting
GBP PaymentsPayments.FasterPayments, Payments.Chaps, Payments.Bacs, Payments.BacsDirectDebit, Payments.Cheques, Payments.CrossBorder, Payments.ConfirmationOfPayee
Multi-currency & FXMultiCurrency.Accounts, MultiCurrency.Payments, MultiCurrency.FxTrade, MultiCurrency.FxTradeRfq, MultiCurrency.SepaCreditTransfer
Embedded BankingEmbeddedBanking.Customers, EmbeddedBanking.Accounts, EmbeddedBanking.Isa, EmbeddedBanking.Interest, EmbeddedBanking.Kyc
WebhooksWebhook, Webhook.Verifier, Webhook.Handler

Installation

# mix.exs
def deps do
  [
    {:clearbank, "~> 1.0"}
  ]
end

Quick Start

1. Configure

# config/runtime.exs
config :clearbank,
  api_token: System.fetch_env!("CLEARBANK_API_TOKEN"),
  private_key_path: System.fetch_env!("CLEARBANK_PRIVATE_KEY_PATH"),
  environment: :simulation  # :simulation | :production

2. Use

client = ClearBank.default_client()

# List GBP accounts
{:ok, %{"accounts" => accounts}} = ClearBank.Accounts.list(client)

# Send a Faster Payment
{:ok, _} = ClearBank.Payments.FasterPayments.send(client, %{
  account_id: "your-account-uuid",
  amount: "100.00",
  currency: "GBP",
  destination_sort_code: "040004",
  destination_account_number: "12345678",
  destination_account_name: "Jane Smith",
  reference: "Invoice 001"
})

# Execute an FX spot trade
{:ok, trade} = ClearBank.MultiCurrency.FxTrade.execute(client, %{
  sell_account_id: "eur-account-uuid",
  buy_account_id: "gbp-account-uuid",
  sell_currency: "EUR",
  buy_currency: "GBP",
  sell_amount: "10000.00"
})

# Create an embedded retail customer
{:ok, customer} = ClearBank.EmbeddedBanking.Customers.create_retail(client, %{
  first_name: "Alice",
  last_name: "Smith",
  date_of_birth: "1990-05-15",
  email: "alice@example.com"
})

3. Handle Webhooks

defmodule MyApp.WebhookHandler do
  use ClearBank.Webhook.Handler

  @impl true
  def handle(%ClearBank.Webhook{type: "TransactionSettled", payload: payload}) do
    MyApp.Ledger.record(payload)
    :ok
  end

  def handle(_webhook), do: :ok
end

4. Error Handling

case ClearBank.Payments.FasterPayments.send(client, payment) do
  {:ok, _}                                    -> :ok
  {:error, %ClearBank.Error{status: 409}}     -> :duplicate_ignored
  {:error, %ClearBank.Error{status: 429}}     -> retry_later()
  {:error, err} when ClearBank.Error.retryable?(err) -> retry_with_same_id()
  {:error, err}                               -> Logger.error(inspect(err))
end

Development

mix deps.get
mix test
mix test --cover
mix credo --strict
mix dialyzer
mix docs

Security

  • Never commit your private_key.pem — add it to .gitignore
  • In production, load private keys from an HSM, not the filesystem
  • Rotate API tokens before their 1-year expiry
  • Verify all inbound webhook signatures before processing
  • Store X-Correlation-Id from error responses — required for ClearBank support

License

MIT — see LICENSE.


Contributing

Pull requests welcome. Please ensure mix test, mix credo --strict, and mix dialyzer all pass before submitting.