revolut

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 20, 2026 License: MIT Imports: 9 Imported by: 0

README

revolut-go

A production-grade, idiomatic Go SDK for the complete Revolut Developer API platform.

Zero external dependencies Tests


APIs covered

API Package Methods Key Resources
Merchant API (v2025-12-04) merchant 58 Orders (CRUD + capture + refund + incremental auth), Payments, Customers + saved methods, Subscription Plans (variations+phases), Subscriptions + billing cycles, Payouts, Disputes (accept/evidence/challenge), Report Runs, Webhooks + rotate secret, Locations, Synchronous Webhooks (Fast Checkout)
Business API business 53 Accounts + bank details, Cards (freeze/unfreeze/terminate), Counterparties (CoP validation), Expenses, FX (rate+exchange), Payment Drafts, Payout Links, Team Members, Transactions (+ by-request-id + cancel), Transfers + payments + card transfers, Webhooks v1+v2 (rotate secret + failed events)
Open Banking API openbanking 31 AISP: accounts, balances, beneficiaries, direct debits, standing orders, transactions. PISP: domestic, domestic scheduled, domestic standing orders, international, international scheduled, international standing orders, file payments (bulk CSV, beta)
Crypto Ramp API cryptoramp 13 Config, quote, buy redirect URL, orders (get+list), webhooks (full CRUD), signature verification + typed payload parsing
Crypto Exchange REST API cryptoexchange 12 Balances, orders (market/limit/TPSL + cancel all), trades (public + private fills), order book, ticker (single + all), symbols
Webhook handler webhook middleware HMAC verification (Revolut's v1.{ts}.{body} format), typed event dispatch, replay-attack protection

Total: 167 public methods · 174 struct types · 37 webhook event types · 6,953 lines · 38/38 tests pass


Design principles

  • Zero external dependencies — only the Go standard library
  • Context-first — every method accepts context.Context
  • Correct HMAC — uses Revolut's exact v1.{timestamp}.{body} webhook signature format
  • Functional options — composable WithXxx options on all clients
  • Generics for paginationtypes.PageResponse[T] across all paginated endpoints
  • Structured errors*APIError, *ValidationError, *SDKError with errors.As support
  • Retry + jitter — exponential backoff with full jitter, configurable per-call
  • Token-bucket rate limiting — client-side, zero external deps
  • Telemetry hooks — plug in your own logger/metrics via telemetry.Hook
  • Replay-attack protection — optional 5-minute timestamp window on webhook handler

Installation

go get github.com/iamkanishka/revolut-go

Quick start

Unified SDK
package main

import (
    "context"
    "log"

    revolut "github.com/iamkanishka/revolut-go"
    "github.com/iamkanishka/revolut-go/merchant"
    "github.com/iamkanishka/revolut-go/types"
)

func main() {
    sdk, err := revolut.New(
        revolut.WithMerchantKey("sk_live_..."),
        revolut.WithBusinessKey("biz_access_token"),
        revolut.WithEnvironment(types.EnvProduction),
        revolut.WithRateLimit(50, 100),
    )
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Create an order
    order, err := sdk.Merchant.CreateOrder(ctx, &merchant.CreateOrderRequest{
        Amount:      1000, // £10.00
        Currency:    "GBP",
        Description: "Widget purchase",
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("order: %s  checkout: %s", order.ID, order.CheckoutURL)
}
Sandbox
sdk, err := revolut.New(
    revolut.WithMerchantKey("sk_sandbox_..."),
    revolut.WithSandbox(),
)

Error handling

import revolverrors "github.com/iamkanishka/revolut-go/errors"

order, err := client.GetOrder(ctx, "ord_missing")
if err != nil {
    switch {
    case revolverrors.IsValidationError(err):
        log.Printf("bad input: %v", err) // caught before HTTP call
    default:
        if apiErr := revolverrors.AsAPIError(err); apiErr != nil {
            log.Printf("API %d [%s] request_id=%s: %s",
                apiErr.StatusCode, apiErr.Code, apiErr.RequestID, apiErr.Message)
            if apiErr.IsNotFound() { /* handle missing resource */ }
            if apiErr.IsRateLimited() { /* back off */ }
            if apiErr.IsRetryable() { /* 5xx or 429 */ }
        }
    }
}

Webhooks

import (
    "github.com/iamkanishka/revolut-go/webhook"
    "github.com/iamkanishka/revolut-go/types"
)

h := webhook.NewHandler(
    // wsk_... signing secret from Revolut dashboard
    webhook.WithSecret("wsk_VsuFcq6FIpa9gOWUu0n2WxiCbsDHIJlN"),
    // Reject events older than 5 minutes (anti-replay)
    webhook.WithTimestampValidation(),
    webhook.WithErrorHandler(func(ctx context.Context, err error) {
        slog.ErrorContext(ctx, "webhook error", "err", err)
    }),
)

// Revolut uses: HMAC-SHA256("v1.{Revolut-Request-Timestamp}.{body}") → v1={hex}
// The handler reads both Revolut-Signature and Revolut-Request-Timestamp headers automatically.

webhook.On(h, types.EventOrderCompleted, func(ctx context.Context, evt *webhook.OrderCompletedEvent) error {
    log.Printf("order %s completed: %d %s", evt.OrderID, evt.Amount, evt.Currency)
    return fulfillOrder(ctx, evt.OrderID)
})

webhook.On(h, types.EventDisputeActionRequired, func(ctx context.Context, evt *webhook.DisputeEvent) error {
    return notifyTeam(ctx, evt.DisputeID)
})

webhook.On(h, types.EventSubscriptionInitiated, func(ctx context.Context, evt *webhook.SubscriptionEvent) error {
    return activateSubscription(ctx, evt.SubscriptionID)
})

http.Handle("/webhooks/revolut", h)

Subscriptions (new Variations + Phases model)

// Create a plan with monthly and yearly variations, each with a trial phase + billing phase
plan, err := sdk.Merchant.CreatePlanV2(ctx, &merchant.CreatePlanV2Request{
    Name:          "Pro Plan",
    TrialDuration: "P14D", // 14-day free trial
    Variations: []merchant.PlanVariation{
        {
            Name: "Monthly",
            Phases: []merchant.PlanPhase{
                {Ordinal: 1, CycleDuration: "P1M", CycleCount: intPtr(1), Amount: 0,   Currency: "GBP"}, // trial
                {Ordinal: 2, CycleDuration: "P1M",                       Amount: 999,  Currency: "GBP"}, // £9.99/mo
            },
        },
        {
            Name: "Yearly",
            Phases: []merchant.PlanPhase{
                {Ordinal: 1, CycleDuration: "P1Y", Amount: 9900, Currency: "GBP"}, // £99/yr
            },
        },
    },
})

// Subscribe a customer (with hosted payment page redirect)
sub, err := sdk.Merchant.CreateSubscriptionV2(ctx, &merchant.CreateSubscriptionV2Request{
    PlanVariationID:       plan.Variations[0].ID, // monthly
    CustomerID:            "cust_abc",
    SetupOrderRedirectURL: "https://example.com/subscription/success",
})
// sub.SetupOrderID → use GetOrder(sub.SetupOrderID) to get checkout_url

// List billing cycles
cycles, err := sdk.Merchant.ListBillingCycles(ctx, sub.ID, types.PageRequest{Limit: 10})

Fast Checkout address validation

// Register your HTTPS endpoint to receive shipping address validation requests
sw, err := sdk.Merchant.RegisterAddressValidation(ctx, &merchant.RegisterAddressValidationRequest{
    EventType: "fast_checkout.validate_address",
    URL:       "https://your-backend.com/validate-address",
})
// sw.SigningKey → store this to verify incoming Revolut-Pay-Payload-Signature headers
log.Printf("signing key: %s", sw.SigningKey)

// List all registered synchronous webhooks
hooks, err := sdk.Merchant.ListSynchronousWebhooks(ctx)

Business API webhooks v2 with secret rotation

// Create v2 webhook (recommended version)
wh, err := sdk.Business.CreateWebhookV2(ctx, &business.CreateWebhookV2Request{
    URL:    "https://example.com/business-events",
    Events: []types.WebhookEventType{
        business.BizEventTransactionCreated,
        business.BizEventTransactionStateChanged,
        business.BizEventPayoutLinkCreated,
    },
})

// Rotate signing secret (grace period: 1 day)
rotated, err := sdk.Business.RotateWebhookSigningSecretV2(ctx, wh.ID,
    &business.RotateWebhookSigningSecretV2Request{
        ExpirationPeriod: "P1D", // old secret valid for 1 day during transition
    })
log.Printf("new secret: %s", rotated.SigningSecret)

// Retrieve failed delivery events
events, err := sdk.Business.GetFailedWebhookEvents(ctx, wh.ID,
    business.ListFailedWebhookEventsRequest{Limit: 20})

Incremental authorisation (pre-auth orders)

// Create a pre-auth order (e.g. for hotel holds)
order, err := sdk.Merchant.CreateOrder(ctx, &merchant.CreateOrderRequest{
    Amount:            10000, // initial authorised amount
    Currency:          "GBP",
    CaptureMode:       types.CaptureModeManual,
    // authorisation_type: pre_authorisation is set in the raw request body
})

// Increase the authorised amount (e.g. minibar charges added at checkout)
order, err = sdk.Merchant.IncrementalAuthorise(ctx, order.ID,
    &merchant.IncrementalAuthorisationRequest{
        Amount:    15000, // new TOTAL authorised amount (not delta)
        Currency:  "GBP",
        Reference: "invoice_123",
    })
// Fires: ORDER_INCREMENTAL_AUTHORISATION_AUTHORISED webhook

Pagination

req := merchant.ListOrdersRequest{Page: types.PageRequest{Limit: 50}}
for {
    page, err := client.ListOrders(ctx, req)
    if err != nil {
        return err
    }
    for _, order := range page.Items {
        process(order)
    }
    if !page.HasNextPage() {
        break
    }
    req.Page.Cursor = page.NextCursor
}

Retry & rate limiting

import "github.com/iamkanishka/revolut-go/internal/retry"

sdk, _ := revolut.New(
    revolut.WithMerchantKey("sk_live_..."),
    revolut.WithRetryPolicy(retry.Policy{
        MaxAttempts:     5,
        InitialInterval: 200 * time.Millisecond,
        MaxInterval:     30 * time.Second,
        Multiplier:      2.0,
        JitterFactor:    0.5,
    }),
    revolut.WithRateLimit(100, 200),
)

Telemetry / observability

import "github.com/iamkanishka/revolut-go/internal/telemetry"

sdk, _ := revolut.New(
    revolut.WithMerchantKey("sk_live_..."),
    revolut.WithTelemetry(telemetry.Hook{
        OnRequest:  func(ctx context.Context, e telemetry.RequestEvent)  { /* log */ },
        OnResponse: func(ctx context.Context, e telemetry.ResponseEvent) { /* metrics */ },
        OnError:    func(ctx context.Context, e telemetry.ErrorEvent)    { /* alert */ },
    }),
)

Package structure

revolut-go/
├── revolut.go                     # Unified SDK entry point
├── merchant/merchant.go           # Merchant API — 58 methods
├── business/business.go           # Business API — 53 methods
├── openbanking/openbanking.go     # Open Banking API — 31 methods
├── cryptoramp/cryptoramp.go       # Crypto Ramp API — 13 methods
├── cryptoexchange/cryptoexchange.go  # Crypto Exchange REST API — 12 methods
├── webhook/webhook.go             # Webhook handler + typed events
├── types/types.go                 # Shared enums, structs, pagination
├── errors/errors.go               # APIError, ValidationError, SDKError
├── client/client.go               # Core HTTP transport
└── internal/
    ├── ratelimit/ratelimit.go     # Token-bucket rate limiter
    ├── retry/retry.go             # Exponential backoff with jitter
    ├── signature/signature.go     # HMAC-SHA256 (plain + Revolut v1 format)
    └── telemetry/telemetry.go     # Observability hook interfaces

Running tests

go test ./... -v -race -count=1

License

MIT

Documentation

Overview

Package revolut is the top-level entry point for the Revolut Go SDK.

It provides a unified Client that composes all API sub-clients:

  • Merchant – online payment orders, customers, subscriptions, disputes
  • Business – accounts, transfers, FX, payment drafts, payout links
  • OpenBanking – consent-based account info and payment initiation (TPPs)
  • CryptoRamp – fiat-to-crypto on-ramp for partners
  • CryptoExchange – Revolut X trading: orders, balances, market data

Quick Start

sdk, err := revolut.New(
    revolut.WithMerchantKey("sk_live_..."),
    revolut.WithBusinessKey("business_sk_..."),
    revolut.WithEnvironment(types.EnvProduction),
    revolut.WithRateLimit(50, 100),
)
order, err := sdk.Merchant.CreateOrder(ctx, &merchant.CreateOrderRequest{
    Amount:   1000,
    Currency: "GBP",
})

Sandbox

sdk, err := revolut.New(
    revolut.WithMerchantKey("sk_sandbox_..."),
    revolut.WithSandbox(),
)

Telemetry

sdk, err := revolut.New(
    revolut.WithMerchantKey("..."),
    revolut.WithTelemetry(telemetry.Hook{
        OnRequest:  func(ctx context.Context, e telemetry.RequestEvent) { /* log */ },
        OnResponse: func(ctx context.Context, e telemetry.ResponseEvent) { /* metrics */ },
        OnError:    func(ctx context.Context, e telemetry.ErrorEvent) { /* alert */ },
    }),
)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type SDK

type SDK struct {
	// Merchant is the Revolut Merchant API client.
	Merchant *merchant.Client

	// Business is the Revolut Business API client.
	Business *business.Client

	// OpenBanking is the Revolut Open Banking API client (TPP use).
	OpenBanking *openbanking.Client

	// CryptoRamp is the Revolut Crypto Ramp API client (partner use).
	CryptoRamp *cryptoramp.Client

	// CryptoExchange is the Revolut X Crypto Exchange REST API client.
	CryptoExchange *cryptoexchange.Client
}

SDK is the unified Revolut client that composes all API sub-clients. Construct it with New() and functional options. All sub-clients are safe for concurrent use.

func New

func New(opts ...SDKOption) (*SDK, error)

New constructs an SDK with only the sub-clients whose API keys are provided. Un-keyed sub-clients are nil — accessing them without initialisation will panic. At least one API key must be supplied.

sdk, err := revolut.New(
    revolut.WithMerchantKey("sk_live_..."),
    revolut.WithSandbox(),
)

type SDKOption

type SDKOption func(*sdkConfig)

SDKOption configures the top-level SDK.

func WithBusinessKey

func WithBusinessKey(key string) SDKOption

WithBusinessKey sets the access token for the Business API.

func WithCryptoExchangeKey

func WithCryptoExchangeKey(key string) SDKOption

WithCryptoExchangeKey sets the API key for the Crypto Exchange REST API.

func WithCryptoRampKey

func WithCryptoRampKey(key string) SDKOption

WithCryptoRampKey sets the X-API-KEY for the Crypto Ramp API.

func WithEnvironment

func WithEnvironment(env types.Environment) SDKOption

WithEnvironment sets the API environment (prod or sandbox) for all clients.

func WithMerchantKey

func WithMerchantKey(key string) SDKOption

WithMerchantKey sets the secret key for the Merchant API.

func WithNoRetry

func WithNoRetry() SDKOption

WithNoRetry disables retries for all sub-clients.

func WithOpenBankingKey

func WithOpenBankingKey(key string) SDKOption

WithOpenBankingKey sets the bearer token for the Open Banking API.

func WithRateLimit

func WithRateLimit(perSecond, burst float64) SDKOption

WithRateLimit configures a shared token-bucket rate limiter applied to all sub-clients. perSecond is the sustained rate; burst is the max burst size.

func WithRetryPolicy

func WithRetryPolicy(p retry.Policy) SDKOption

WithRetryPolicy sets the retry policy for all sub-clients.

func WithSandbox

func WithSandbox() SDKOption

WithSandbox is a convenience alias for WithEnvironment(types.EnvSandbox).

func WithTelemetry

func WithTelemetry(h telemetry.Hook) SDKOption

WithTelemetry attaches observability hooks to all sub-clients.

func WithUserAgent

func WithUserAgent(ua string) SDKOption

WithUserAgent sets a custom User-Agent on all sub-clients.

Directories

Path Synopsis
Package business implements the complete Revolut Business API.
Package business implements the complete Revolut Business API.
Package client implements the core HTTP transport layer for the Revolut Go SDK.
Package client implements the core HTTP transport layer for the Revolut Go SDK.
Package cryptoexchange implements the complete Revolut X Crypto Exchange REST API.
Package cryptoexchange implements the complete Revolut X Crypto Exchange REST API.
Package cryptoramp implements the complete Revolut Crypto Ramp API.
Package cryptoramp implements the complete Revolut Crypto Ramp API.
Package errors provides structured error types for the Revolut Go SDK.
Package errors provides structured error types for the Revolut Go SDK.
internal
ratelimit
Package ratelimit implements a thread-safe token-bucket rate limiter using only the Go standard library.
Package ratelimit implements a thread-safe token-bucket rate limiter using only the Go standard library.
retry
Package retry implements exponential backoff with full jitter for transient HTTP failures.
Package retry implements exponential backoff with full jitter for transient HTTP failures.
signature
Package signature provides HMAC-SHA256 webhook payload verification using constant-time comparison to prevent timing attacks.
Package signature provides HMAC-SHA256 webhook payload verification using constant-time comparison to prevent timing attacks.
telemetry
Package telemetry defines hook interfaces for request/response observability.
Package telemetry defines hook interfaces for request/response observability.
Package merchant implements the complete Revolut Merchant API.
Package merchant implements the complete Revolut Merchant API.
Package openbanking implements the complete Revolut Open Banking API.
Package openbanking implements the complete Revolut Open Banking API.
Package types provides all shared value types, enumerations, and pagination primitives used across every Revolut API sub-package.
Package types provides all shared value types, enumerations, and pagination primitives used across every Revolut API sub-package.
Package webhook provides HTTP middleware and typed event parsing for Revolut webhook payloads.
Package webhook provides HTTP middleware and typed event parsing for Revolut webhook payloads.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL