absolutepay

package module
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Jul 13, 2026 License: MIT Imports: 16 Imported by: 0

README

absolutepay-go

Official AbsolutePay API client for Go. Server-side only — your API key and signing secret must never reach a browser.

Every request from an app key is HMAC-signed automatically. Inbound webhooks are verified with one call. Zero third-party dependencies — standard library only.

Install

go get github.com/AbsolutePay/absolutepay-go@latest

Requires Go 1.18+.

import absolutepay "github.com/AbsolutePay/absolutepay-go"

Environments

Option Base URL
default https://api.absolutepay.io (production)
WithSandbox(true) https://sandbox-api.absolutepay.io
WithBaseURL("https://…") your override (wins over sandbox)

Quickstart

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	absolutepay "github.com/AbsolutePay/absolutepay-go"
)

func main() {
	ap, err := absolutepay.New(
		os.Getenv("ABSOLUTEPAY_API_KEY"), // ap_live_… / ap_test_…
		absolutepay.WithSigningSecret(os.Getenv("ABSOLUTEPAY_SIGNING_SECRET")), // apisign_…
		// absolutepay.WithSandbox(true),
	)
	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()
	balances, err := ap.Balances.List(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(balances)

	inv, err := ap.Invoices.Create(ctx, absolutepay.InvoiceParams{
		Reference:   "order-123",
		Amount:      absolutepay.Money{Amount: "25.00", Currency: "USDT"},
		Chain:       "MATIC", // REQUIRED — mints the deposit address up front
		RedirectURL: "https://shop.example.com/thanks", // payer returns here after checkout (?token=…&status=…)
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(inv["token"], inv["address"])
}

Checkouts vs. invoices

Two symmetric resources create a payable link:

  • ap.Checkouts — a hosted page where the payer picks the asset and network at pay time. No chain; you get a checkoutUrl to redirect the customer to.
  • ap.Invoices — an up-front flow: you pass a required chain and get a fixed deposit address back immediately.

Both expose the same lifecycle: Create / List / Get / Update / Delete. Update pauses/resumes or edits the link; Delete voids it. Confirm payment via the payment.succeeded webhook or by polling Get(ctx, token).

link, err := ap.Checkouts.Create(ctx, absolutepay.CheckoutParams{
	Reference: "order-123",
	Amount:    absolutepay.Money{Amount: "25.00", Currency: "USDT"},
})
if err != nil {
	log.Fatal(err)
}
fmt.Println(link["checkoutUrl"]) // send the payer here; they choose how to pay

// Pause the link, then void it.
paused := true
_, _ = ap.Checkouts.Update(ctx, link["token"].(string), absolutepay.ResourceUpdate{Paused: &paused})
_ = ap.Checkouts.Delete(ctx, link["token"].(string))

Idempotency

Money-moving POSTs (Payouts.Create, Refunds.Create, Conversions.Execute, OffRamp.Withdraw, GiftCards.Create, Subscriptions.Create, Subscriptions.Plans.Create) accept WithIdempotencyKey, which sets the Idempotency-Key header. Replaying with the same key returns the original result instead of acting twice; a 409 (in-progress or conflicting replay) surfaces as a normal *absolutepay.Error you can inspect via .Code.

_, err := ap.Refunds.Create(ctx, absolutepay.RefundParams{
	MerchantTradeNo: "order-123",
	Amount:          absolutepay.Money{Amount: "10.00", Currency: "USDT"},
}, absolutepay.WithIdempotencyKey("refund-order-123-1"))

Errors

Non-2xx responses return an *absolutepay.Error:

_, err := ap.Payouts.Create(ctx, items)
var apErr *absolutepay.Error
if errors.As(err, &apErr) {
	fmt.Println(apErr.Status, apErr.Code, apErr.Detail, apErr.RequestID)
	if apErr.IsRateLimited() { /* 429 — back off and retry */ }
	if apErr.IsAuth()        { /* 401/403 — check key, scope, or signature */ }
}

Pagination

Lists return a generic Page[T] with { Items, NextCursor } (the ledger lists — Refunds.List, Conversions.List — and reconciliation also carry Total). Pass a prior page's NextCursor back as the query's Before; it is "" on the last page. Loosely-typed lists come back as Page[JSON] (JSON = map[string]any); read fields by key.

var before string
for {
	page, err := ap.Invoices.List(ctx, absolutepay.ListQuery{
		Limit:  50,
		Before: before,
		Order:  absolutepay.OrderDesc,
		Status: "OPEN", // optional filter
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, item := range page.Items {
		fmt.Println(item["token"], item["amount"])
	}
	if page.NextCursor == "" {
		break
	}
	before = page.NextCursor
}

Webhooks

Verify the signature and parse the event in one call. Pass the raw request body:

func handler(w http.ResponseWriter, r *http.Request) {
	raw, _ := io.ReadAll(r.Body) // RAW bytes — do not re-serialize
	event, err := absolutepay.ConstructEvent(raw, r.Header, os.Getenv("ABSOLUTEPAY_WEBHOOK_SECRET"))
	if err != nil {
		http.Error(w, "bad signature", http.StatusBadRequest)
		return
	}
	if event.Type == "payment.succeeded" {
		// json.Unmarshal(event.Data, &yourType)
	}
	w.WriteHeader(http.StatusOK)
}

The freshness (replay) window defaults to 5 minutes; pass absolutepay.WithTolerance(0) to disable it.

Security

  • Server-side only. The API key + signing secret authenticate as your workspace.
  • Requests go over HTTPS only (except localhost for local development).
  • The Idempotency-Key header (on money POSTs) is intentionally not part of the signed canonical string.

License

MIT

Documentation

Overview

Package absolutepay is the official Go client for the AbsolutePay API.

It signs every request from an app key automatically (HMAC-SHA512) and verifies inbound webhooks. Server-side only — your API key and signing secret must never reach a browser. Zero third-party dependencies (standard library only).

Typical use:

ap, err := absolutepay.New("ap_live_...", absolutepay.WithSigningSecret("apisign_..."))
if err != nil {
	log.Fatal(err)
}
balances, err := ap.Balances.List(ctx)

Every list of scopes required by a call is documented on the service type that exposes it (for example BalancesService needs balances:read).

Index

Constants

View Source
const (
	// ProductionBaseURL is the live API origin (real funds).
	ProductionBaseURL = "https://api.absolutepay.io"
	// SandboxBaseURL is the public sandbox API origin (mock funds); select it with WithSandbox.
	SandboxBaseURL = "https://sandbox-api.absolutepay.io"
)

Base URLs for the public API. Pass any other origin through WithBaseURL.

View Source
const DefaultWebhookTolerance = 5 * time.Minute

DefaultWebhookTolerance is the default freshness window enforced on webhook timestamps (replay defense): a callback older than this is rejected.

Variables

View Source
var ErrInvalidSignature = errors.New("absolutepay: invalid webhook signature")

ErrInvalidSignature is returned by ConstructEvent (and reported by VerifySignature) when a webhook fails signature or freshness verification.

Functions

func VerifySignature

func VerifySignature(secret string, rawBody []byte, timestamp, signature string) bool

VerifySignature reports whether the HMAC-SHA512 of "{timestamp}.{rawBody}" keyed by secret equals signature, compared in constant time. secret is your app's callback secret (whsec_...); rawBody is the exact request body bytes; timestamp and signature come from the X-AbsolutePay-Timestamp and X-AbsolutePay-Signature headers. It returns false if any input is empty or the signatures differ. This is the low-level check; most callers use ConstructEvent, which also enforces freshness.

Types

type AddressQuery added in v0.5.0

type AddressQuery struct {
	// Chain filters to a single blockchain network, e.g. "TRX". "" = all chains.
	Chain string
	// Limit is the maximum number of items per page. 0 means the server default.
	Limit int
	// Before is the opaque cursor from a previous page's Page.NextCursor.
	Before string
	// Order is the sort direction, OrderAsc or OrderDesc.
	Order Order
}

AddressQuery filters the workspace's minted deposit addresses (Deposits.Addresses). All fields are optional; zero values are omitted.

type Balance

type Balance struct {
	// Currency is the asset code, e.g. "USDT".
	Currency string `json:"currency"`
	// Available is the spendable amount as a decimal string.
	Available string `json:"available"`
	// Locked is the amount reserved/held (unavailable) as a decimal string.
	Locked string `json:"locked"`
}

Balance is a single asset balance for the workspace.

type BalancesService

type BalancesService struct {
	// contains filtered or unexported fields
}

BalancesService reads workspace asset balances. Requires the balances:read scope.

func (*BalancesService) List

func (s *BalancesService) List(ctx context.Context) (*Page[Balance], error)

List returns every asset balance for the workspace as a Page[Balance] (one item per asset; the list is not cursor-paged, so NextCursor is empty), or an error.

type BankMaterialsParams added in v0.2.0

type BankMaterialsParams struct {
	// Certificate holds proof-of-account / certificate documents.
	Certificate []DocFile `json:"certificate"`
	// Passport holds identity (passport) documents.
	Passport []DocFile `json:"passport"`
}

BankMaterialsParams submits additional compliance documents for a registered bank account (e.g. when off-ramp review requests more materials).

type BankParams added in v0.2.0

type BankParams struct {
	// BankAccountName is the account holder's name as it appears at the bank.
	BankAccountName string `json:"bankAccountName"`
	// BankName is the destination bank's name.
	BankName string `json:"bankName"`
	// CountryID is the numeric id of the bank's country (from OffRampService.Countries).
	CountryID int `json:"countryId"`
	// IBAN is the destination account's IBAN.
	IBAN string `json:"iban"`
	// Swift is the bank's SWIFT/BIC code. Optional.
	Swift string `json:"swift,omitempty"`
	// Address is the account holder's address. Optional.
	Address string `json:"address,omitempty"`
	// RemittanceLineNumber is an optional remittance reference line required by some corridors.
	RemittanceLineNumber string `json:"remittanceLineNumber,omitempty"`
	// File is the proof-of-account document uploaded inline (see DocFile).
	File DocFile `json:"file"`
}

BankParams registers a fiat destination bank account for off-ramp withdrawals.

type CheckoutParams

type CheckoutParams struct {
	// Reference is your unique checkout reference.
	Reference string `json:"reference"`
	// Amount is the amount and currency to bill.
	Amount Money `json:"amount"`
	// Description is an optional human-readable line item / memo.
	Description string `json:"description,omitempty"`
	// CustomerEmail is the payer's email, used for receipts/notifications. Optional.
	CustomerEmail string `json:"customerEmail,omitempty"`
	// ExpiresAt is the expiry time in epoch milliseconds. Optional (0 = no explicit expiry).
	ExpiresAt int64 `json:"expiresAt,omitempty"`
	// RedirectURL is an http(s) URL the payer's browser is sent to once the hosted
	// checkout reaches a terminal state. AbsolutePay appends
	// ?token=<token>&status=<SUCCESS|EXPIRED|CANCELED> (preserving any existing query).
	// Optional.
	RedirectURL string `json:"redirectUrl,omitempty"`
}

CheckoutParams is the request body for CheckoutsService.Create.

type CheckoutsService added in v0.5.0

type CheckoutsService struct {
	// contains filtered or unexported fields
}

CheckoutsService creates and manages hosted checkout links, where the payer picks the asset and network at pay time. Writes require invoices:write; reads require invoices:read.

func (*CheckoutsService) Create added in v0.5.0

Create creates a hosted checkout link and returns it as JSON (including token and checkoutUrl — send the payer to checkoutUrl). It returns an error if rejected.

func (*CheckoutsService) Delete added in v0.5.0

func (s *CheckoutsService) Delete(ctx context.Context, token string) error

Delete voids a checkout link, making it permanently unpayable. token identifies the link. It returns an error if the request is rejected.

func (*CheckoutsService) Get added in v0.5.0

func (s *CheckoutsService) Get(ctx context.Context, token string) (JSON, error)

Get looks up a checkout link by its token and returns it as JSON, or an error. Use it as a settlement-confirmation fallback alongside the payment.succeeded webhook.

func (*CheckoutsService) List added in v0.5.0

func (s *CheckoutsService) List(ctx context.Context, q ListQuery) (*Page[JSON], error)

List returns a cursor-paginated page of checkout links. q sets page size, cursor, order, and optional status/search filters; pass a prior Page.NextCursor as q.Before ("" means the last page). See ListQuery.

func (*CheckoutsService) Update added in v0.5.0

func (s *CheckoutsService) Update(ctx context.Context, token string, patch ResourceUpdate) (JSON, error)

Update patches an open checkout link (pause/resume, redirect, expiry, description) and returns the updated state as JSON, or an error. See ResourceUpdate.

type Client

type Client struct {

	// Balances exposes workspace asset balances (scope: balances:read).
	Balances *BalancesService
	// Fees exposes fee previews (scope: balances:read).
	Fees *FeesService
	// Payouts exposes batch on-chain payouts (scopes: payouts:write / payouts:read).
	Payouts *PayoutsService
	// Refunds exposes refunds and the settled refund ledger (scopes: payments:write / ledger:read).
	Refunds *RefundsService
	// Conversions exposes currency conversions and the settled convert ledger (scopes: convert:write / ledger:read).
	Conversions *ConversionsService
	// Checkouts exposes hosted checkout links where the payer picks asset + network (scopes: invoices:write / invoices:read).
	Checkouts *CheckoutsService
	// Invoices exposes up-front fixed-address invoices (scopes: invoices:write / invoices:read).
	Invoices *InvoicesService
	// Subscriptions exposes recurring plans and subscriptions (scopes: subscriptions:write / subscriptions:read).
	Subscriptions *SubscriptionsService
	// GiftCards exposes gift-card issuance and lookup (scopes: balances:read / payments:write).
	GiftCards *GiftCardsService
	// OffRamp exposes crypto-to-fiat off-ramp (scopes: payouts:write / payouts:read).
	OffRamp *OffRampService
	// Reconciliation exposes settled payment/withdrawal reconciliation reports (scope: ledger:read).
	Reconciliation *ReconciliationService
	// Deposits exposes deposit chains, own-balance receive addresses, and history (scope: balances:read).
	Deposits *DepositsService
	// contains filtered or unexported fields
}

Client is the AbsolutePay API client. Construct it once with New and reuse it across goroutines; each resource service hangs off it as a field.

func New

func New(apiKey string, opts ...Option) (*Client, error)

New builds a Client. apiKey is required and identifies your workspace (ap_live_... for production, ap_test_... for sandbox/test). Pass Options to set the signing secret, choose sandbox/base URL, or supply a custom HTTP client. It returns an error if apiKey is empty or the resolved base URL is invalid or a non-https, non-localhost origin. Example:

ap, err := absolutepay.New(
	"ap_live_...",
	absolutepay.WithSigningSecret("apisign_..."),
)
if err != nil {
	return err
}
balances, err := ap.Balances.List(ctx)

type ConversionsService

type ConversionsService struct {
	// contains filtered or unexported fields
}

ConversionsService quotes and executes currency conversions and reads the settled convert ledger. Quoting/executing require convert:write; List requires ledger:read.

func (*ConversionsService) Execute

Execute runs a previously quoted conversion (this moves funds) and returns the result as JSON, or an error. Pass WithIdempotencyKey to make retries safe.

func (*ConversionsService) List added in v0.5.0

List returns a cursor-paginated page of the settled CONVERT ledger history (the page carries Total, the true count for the filtered range). See LedgerQuery.

func (*ConversionsService) Quote

Quote previews a conversion without moving any funds and returns a *ConvertQuote (rate and both legs), or an error. Follow with Execute to commit it.

type ConvertExecuteParams

type ConvertExecuteParams struct {
	// QuoteID is the id from the ConvertQuote returned by Quote.
	QuoteID string `json:"quoteId"`
	// Sell is the amount and currency to sell (must match the quote).
	Sell Money `json:"sell"`
	// Buy is the amount and currency to buy (must match the quote).
	Buy Money `json:"buy"`
}

ConvertExecuteParams executes a previously obtained conversion quote.

type ConvertQuote

type ConvertQuote struct {
	// QuoteID identifies this quote; pass it to Execute.
	QuoteID string `json:"quoteId"`
	// Rate is the quoted exchange rate as a decimal string.
	Rate string `json:"rate"`
	// SellCurrency is the currency being sold.
	SellCurrency string `json:"sellCurrency"`
	// SellAmount is the amount to be sold, as a decimal string.
	SellAmount string `json:"sellAmount"`
	// BuyCurrency is the currency being bought.
	BuyCurrency string `json:"buyCurrency"`
	// BuyAmount is the amount to be bought, as a decimal string.
	BuyAmount string `json:"buyAmount"`
}

ConvertQuote is a conversion quote returned by Quote. It is short-lived; pass its QuoteID to Execute to lock in the trade.

type DepositHistoryQuery added in v0.5.0

type DepositHistoryQuery struct {
	// Chain filters to a single blockchain network, e.g. "TRX". "" = all chains.
	Chain string
	// From is the inclusive start of the time range, in epoch milliseconds (0 = unbounded).
	From int64
	// To is the inclusive end of the time range, in epoch milliseconds (0 = unbounded).
	To int64
	// Before is the opaque cursor from a previous page's Page.NextCursor.
	Before string
	// Order is the sort direction, OrderAsc or OrderDesc.
	Order Order
}

DepositHistoryQuery filters the settled deposit history (Deposits.List). All fields are optional; zero values are omitted.

type DepositsService added in v0.2.0

type DepositsService struct {
	// contains filtered or unexported fields
}

DepositsService lists deposit chains, mints own-balance receive addresses, and reads settled deposit history. Requires the balances:read scope.

func (*DepositsService) Addresses added in v0.5.0

func (s *DepositsService) Addresses(ctx context.Context, q AddressQuery) (*Page[JSON], error)

Addresses returns a cursor-paginated page of the workspace's minted deposit addresses. q filters by chain and pages; pass a prior Page.NextCursor as q.Before ("" means the last page). See AddressQuery.

func (*DepositsService) Chains added in v0.2.0

func (s *DepositsService) Chains(ctx context.Context) (*Page[JSON], error)

Chains returns the blockchain networks available for deposits as a Page (one item per chain), or an error. Use a returned chain code with CreateAddress.

func (*DepositsService) CreateAddress added in v0.2.0

func (s *DepositsService) CreateAddress(ctx context.Context, chain string) (JSON, error)

CreateAddress mints (or returns the existing) deposit address on chain (e.g. "TRX", "ETH") that credits the workspace balance. It is idempotent per chain and returns the address as JSON, or an error.

func (*DepositsService) GetAddress added in v0.5.0

func (s *DepositsService) GetAddress(ctx context.Context, chain string) (JSON, error)

GetAddress returns the workspace's deposit address for a single chain as JSON, or an error.

func (*DepositsService) List added in v0.5.0

List returns a cursor-paginated page of settled deposit history. q filters by chain/time range and pages; pass a prior Page.NextCursor as q.Before ("" means the last page). See DepositHistoryQuery.

type DocFile added in v0.2.0

type DocFile struct {
	// Filename is the original file name, e.g. "passport.pdf".
	Filename string `json:"filename"`
	// ContentType is the file's MIME type, e.g. "application/pdf" or "image/png".
	ContentType string `json:"contentType"`
	// DataBase64 is the file's bytes, base64-encoded (standard encoding, no data: URI prefix).
	DataBase64 string `json:"dataBase64"`
}

DocFile is a base64-encoded document uploaded inline with an off-ramp bank registration or compliance submission (e.g. a proof-of-address certificate or a passport scan).

type Error

type Error struct {
	// Status is the HTTP status code, or 0 for a transport/network failure.
	Status int
	// Code is the stable, machine-readable error code; branch on this in your code.
	Code string
	// Title is a short human-readable summary of the problem.
	Title string
	// Detail is optional extra context about the specific failure (may be empty).
	Detail string
	// RequestID is the server's x-request-id; include it when reporting a problem.
	RequestID string
}

Error is returned when the API responds with a non-2xx status (or a transport failure occurs). It carries the platform's problem+json fields. Every resource method returns this concrete type via the error interface; type-assert to *Error to inspect the fields or call IsAuth / IsRateLimited.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface, formatting the status, title, and code.

func (*Error) IsAuth

func (e *Error) IsAuth() bool

IsAuth reports whether the error is a 401 or 403 — bad or insufficient credentials, a missing scope, or an invalid request signature.

func (*Error) IsRateLimited

func (e *Error) IsRateLimited() bool

IsRateLimited reports whether the error is a 429 — you are being throttled; back off and retry after a moment.

type Event

type Event struct {
	// ID is the unique event identifier (use it to de-duplicate deliveries).
	ID string `json:"id"`
	// Type is the event name, e.g. "payment.succeeded".
	Type string `json:"type"`
	// Data is the event-specific payload as raw JSON; unmarshal it into your target type.
	Data json.RawMessage `json:"data"`
}

Event is a delivered webhook callback: the JSON the platform POSTs to your configured callback URL. Type identifies the event; Data is the event-specific payload as raw JSON that you unmarshal into the shape you expect.

Known Type values include: "payment.succeeded", "charge.refunded", "payout.settled", "payout.partial", and "payout.failed".

func ConstructEvent

func ConstructEvent(rawBody []byte, headers http.Header, secret string, opts ...EventOption) (*Event, error)

ConstructEvent verifies a webhook callback's signature and freshness, then parses and returns the Event. Pass the RAW request body bytes (not a re-encoded copy), the request headers, and your app's callback secret (whsec_...). By default it rejects callbacks whose timestamp is more than DefaultWebhookTolerance old; tune or disable that with WithTolerance. It returns ErrInvalidSignature if the signature or freshness check fails, or a JSON error if the body cannot be parsed. Example (net/http handler):

body, _ := io.ReadAll(r.Body)
evt, err := absolutepay.ConstructEvent(body, r.Header, "whsec_...")
if err != nil {
	http.Error(w, "bad signature", http.StatusBadRequest)
	return
}
switch evt.Type {
case "payment.succeeded":
	// json.Unmarshal(evt.Data, &payload)
}

type EventOption

type EventOption func(*eventOptions)

EventOption customizes ConstructEvent (currently the freshness tolerance).

func WithTolerance

func WithTolerance(d time.Duration) EventOption

WithTolerance sets the freshness window used for replay defense. d is the maximum allowed age of a webhook timestamp; pass WithTolerance(0) to disable the freshness check entirely (signature is still verified). Defaults to DefaultWebhookTolerance.

type FeePreview

type FeePreview struct {
	// Amount is the input amount the fee was computed on, as a decimal string.
	Amount string `json:"amount"`
	// Currency is the currency code of Amount.
	Currency string `json:"currency"`
	// PaymentType is the operation kind the fee applies to (see the Payment* constants).
	PaymentType PaymentType `json:"paymentType"`
	// Fee is the total fee charged on the amount, as a decimal string.
	Fee string `json:"fee"`
	// Net is the amount remaining after the fee, as a decimal string.
	Net string `json:"net"`
}

FeePreview is the total fee (and net) for a given amount.

type FeesService

type FeesService struct {
	// contains filtered or unexported fields
}

FeesService previews fees before you commit to an operation. Requires the balances:read scope.

func (*FeesService) Preview

func (s *FeesService) Preview(ctx context.Context, amount, currency string, paymentType PaymentType, chain string) (*FeePreview, error)

Preview returns the fee breakdown for an amount and payment type. amount is the decimal-string value; currency is its code (e.g. "USDT"); paymentType is one of the Payment* constants (pass "" for the default CHECKOUT). chain is the network (e.g. "MATIC"): REQUIRED for PaymentWithdrawal/PaymentPayout (payout fees are per-chain) and ignored for pay-in — pass "" for CHECKOUT. It returns a *FeePreview, or an error (a *Error with Code "chain_required" if chain is missing for a withdrawal/payout).

type GiftCardParams

type GiftCardParams struct {
	// Title is the gift card's display title.
	Title string `json:"title"`
	// TemplateID is the design template id (from Templates) to render the card with.
	TemplateID string `json:"templateId"`
	// Amount is the face value and currency loaded onto the card.
	Amount Money `json:"amount"`
}

GiftCardParams issues a gift card.

type GiftCardsService

type GiftCardsService struct {
	// contains filtered or unexported fields
}

GiftCardsService issues and looks up gift cards. Reads require balances:read; issuing a card requires payments:write.

func (*GiftCardsService) Create

func (s *GiftCardsService) Create(ctx context.Context, p GiftCardParams, opts ...RequestOption) (JSON, error)

Create issues a gift card from p and returns it as JSON (including its card number), or an error. Pass WithIdempotencyKey to make retries safe.

func (*GiftCardsService) Get

func (s *GiftCardsService) Get(ctx context.Context, cardNum string) (JSON, error)

Get looks up an issued gift card by its card number (cardNum) and returns it as JSON, or an error.

func (*GiftCardsService) List

func (s *GiftCardsService) List(ctx context.Context, q ListQuery) (*Page[JSON], error)

List returns a cursor-paginated page of issued gift cards. q sets page size, cursor, order, and optional status/search filters; pass a prior Page.NextCursor as q.Before ("" means the last page). See ListQuery.

func (*GiftCardsService) Templates

func (s *GiftCardsService) Templates(ctx context.Context) (*Page[JSON], error)

Templates returns the available gift-card design templates as a Page (one item per template), or an error. Use a returned template's id as GiftCardParams.TemplateID.

type InvoiceParams

type InvoiceParams struct {
	// Reference is your unique invoice reference.
	Reference string `json:"reference"`
	// Amount is the amount and currency to bill.
	Amount Money `json:"amount"`
	// Chain is the blockchain network; REQUIRED. It mints the deposit address up front.
	Chain string `json:"chain"`
	// Description is an optional human-readable line item / memo.
	Description string `json:"description,omitempty"`
	// CustomerEmail is the payer's email, used for receipts/notifications. Optional.
	CustomerEmail string `json:"customerEmail,omitempty"`
	// ExpiresAt is the expiry time in epoch milliseconds. Optional (0 = no explicit expiry).
	ExpiresAt int64 `json:"expiresAt,omitempty"`
	// RedirectURL is an http(s) URL the payer's browser returns to at a terminal
	// state (?token=…&status=…). Optional.
	RedirectURL string `json:"redirectUrl,omitempty"`
}

InvoiceParams is the request body for InvoicesService.Create. Chain is REQUIRED — it mints the deposit address up front. For a payer-picks-the-network flow, use CheckoutsService instead.

type InvoicesService

type InvoicesService struct {
	// contains filtered or unexported fields
}

InvoicesService creates and manages up-front invoices: the deposit address is minted at create time on a fixed Chain. Writes require invoices:write; reads require invoices:read.

func (*InvoicesService) Create

func (s *InvoicesService) Create(ctx context.Context, p InvoiceParams) (JSON, error)

Create creates a fixed-asset invoice (Chain required) and returns it as JSON (including its token, address, chain, and amount), or an error.

func (*InvoicesService) Delete added in v0.5.0

func (s *InvoicesService) Delete(ctx context.Context, token string) error

Delete voids an invoice, making it permanently unpayable. token identifies the invoice. It returns an error if the request is rejected.

func (*InvoicesService) Get added in v0.5.0

func (s *InvoicesService) Get(ctx context.Context, token string) (JSON, error)

Get looks up an invoice by its token and returns it as JSON, or an error.

func (*InvoicesService) List

func (s *InvoicesService) List(ctx context.Context, q ListQuery) (*Page[JSON], error)

List returns a cursor-paginated page of invoices. q sets page size, cursor, order, and optional status/search filters; pass a prior Page.NextCursor as q.Before ("" means the last page). See ListQuery.

func (*InvoicesService) Update added in v0.5.0

func (s *InvoicesService) Update(ctx context.Context, token string, patch ResourceUpdate) (JSON, error)

Update patches an open invoice (pause/resume, redirect, expiry, description) and returns the updated state as JSON, or an error. See ResourceUpdate.

type JSON

type JSON = map[string]any

JSON is a loosely-typed object returned by endpoints that have no dedicated response struct. It is an alias for map[string]any; read fields by key, e.g. resp["token"]. Values follow encoding/json defaults (numbers decode to float64).

type LedgerQuery added in v0.5.0

type LedgerQuery struct {
	// From is the inclusive start of the time range, in epoch milliseconds (0 = unbounded).
	From int64
	// To is the inclusive end of the time range, in epoch milliseconds (0 = unbounded).
	To int64
	// Currency filters to a single asset code, e.g. "USDT". "" = all currencies.
	Currency string
	// Limit is the maximum number of items per page. 0 means the server default.
	Limit int
	// Before is the opaque cursor from a previous page's Page.NextCursor.
	Before string
	// Order is the sort direction, OrderAsc or OrderDesc.
	Order Order
}

LedgerQuery filters the settled ledger-history lists (Refunds.List and Conversions.List). All fields are optional; zero values are omitted.

type ListQuery added in v0.5.0

type ListQuery struct {
	// Limit is the maximum number of items per page. 0 means the server default.
	Limit int
	// Before is the opaque cursor from a previous page's Page.NextCursor. "" fetches
	// the first page.
	Before string
	// Order is the sort direction, OrderAsc or OrderDesc. "" means the server default.
	Order Order
	// Status is an optional, endpoint-specific status filter. "" means no filter.
	Status string
	// Q is an optional free-text search filter. "" means no filter.
	Q string
}

ListQuery holds the shared cursor-pagination + filter options for the resource lists that support a status/search filter: Checkouts, Invoices, GiftCards, Subscriptions, and OffRamp.Orders. All fields are optional.

type Money

type Money struct {
	// Amount is the decimal value as a string, e.g. "10.00" (≤6 dp). Never a float.
	Amount string `json:"amount"`
	// Currency is the asset/currency code, e.g. "USDT", "BTC", "USD".
	Currency string `json:"currency"`
}

Money is a monetary value: a decimal-string amount together with its currency code, e.g. Money{Amount: "10.00", Currency: "USDT"}. Amounts are ALWAYS strings (never floats) so no precision is lost on the money path.

type OffRampQuoteParams

type OffRampQuoteParams struct {
	// CryptoCurrency is the asset code being sold, e.g. "USDT".
	CryptoCurrency string `json:"cryptoCurrency"`
	// FiatCurrency is the target fiat currency code, e.g. "USD", "EUR".
	FiatCurrency string `json:"fiatCurrency"`
	// CryptoAmount is the amount of crypto to sell, as a decimal string.
	CryptoAmount string `json:"cryptoAmount"`
}

OffRampQuoteParams requests a crypto-to-fiat quote.

type OffRampService

type OffRampService struct {
	// contains filtered or unexported fields
}

OffRampService converts crypto to fiat and pays out to a registered bank account. Reads require payouts:read; quoting/withdrawing require payouts:write.

func (*OffRampService) Banks

func (s *OffRampService) Banks(ctx context.Context) (*Page[JSON], error)

Banks returns the workspace's registered destination bank accounts as a Page (one item per account), or an error. Use a returned account's id as OffRampWithdrawParams.BankAccountID.

func (*OffRampService) Countries

func (s *OffRampService) Countries(ctx context.Context) (*Page[JSON], error)

Countries returns the fiat destination countries supported for off-ramp as a Page (one item per country), or an error.

func (*OffRampService) Orders

func (s *OffRampService) Orders(ctx context.Context, q ListQuery) (*Page[JSON], error)

Orders returns a cursor-paginated page of off-ramp orders. q sets page size, cursor, order, and optional status/search filters; pass a prior Page.NextCursor as q.Before ("" means the last page). See ListQuery.

func (*OffRampService) Quote

Quote returns a crypto-to-fiat quote (including a quote token and fiat amount) for p as JSON, or an error. Follow with Withdraw to execute it.

func (*OffRampService) RegisterBank added in v0.2.0

func (s *OffRampService) RegisterBank(ctx context.Context, p BankParams) (JSON, error)

RegisterBank registers a fiat destination bank account (see BankParams, including the inline proof document) and returns the created account as JSON (with its id, usable as OffRampWithdrawParams.BankAccountID), or an error.

func (*OffRampService) RemoveBank added in v0.5.0

func (s *OffRampService) RemoveBank(ctx context.Context, bankAccountID string) error

RemoveBank removes a registered destination bank account. bankAccountID is the account's id (from RegisterBank or Banks). It returns an error if rejected.

func (*OffRampService) SubmitBankMaterials added in v0.2.0

func (s *OffRampService) SubmitBankMaterials(ctx context.Context, bankAccountID string, p BankMaterialsParams) (JSON, error)

SubmitBankMaterials uploads additional compliance documents for a registered bank account. bankAccountID identifies the account; p carries the certificate/passport documents (see BankMaterialsParams). It returns the updated review state as JSON, or an error.

func (*OffRampService) Withdraw

Withdraw executes an off-ramp against a quote and registered bank account (see OffRampWithdrawParams) and returns the order as JSON, or an error. Pass WithIdempotencyKey to make retries safe.

type OffRampWithdrawParams

type OffRampWithdrawParams struct {
	// QuoteToken is the token from the OffRampService.Quote response.
	QuoteToken string `json:"quoteToken"`
	// BankAccountID identifies the registered destination bank account.
	BankAccountID string `json:"bankAccountId"`
	// CryptoCurrency is the asset code being sold (must match the quote).
	CryptoCurrency string `json:"cryptoCurrency"`
	// FiatCurrency is the target fiat currency code (must match the quote).
	FiatCurrency string `json:"fiatCurrency"`
	// CryptoAmount is the crypto amount to sell, as a decimal string (must match the quote).
	CryptoAmount string `json:"cryptoAmount"`
	// FiatAmount is the fiat amount to receive, as a decimal string (from the quote).
	FiatAmount string `json:"fiatAmount"`
}

OffRampWithdrawParams executes an off-ramp against a prior quote and a registered bank account.

type Option

type Option func(*Client)

Option customizes a Client during New. Options are applied in order.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL overrides the API origin entirely, e.g. a local dev server. It takes precedence over WithSandbox. baseURL must use https unless the host is localhost or 127.0.0.1; a non-https, non-local URL makes New return an error.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient sets a custom *http.Client, letting you control timeouts, transport, proxy, and TLS. It replaces the default 30s-timeout client.

func WithSandbox

func WithSandbox(sandbox bool) Option

WithSandbox targets the public sandbox host instead of production when sandbox is true. It is ignored if WithBaseURL is also set (WithBaseURL wins).

func WithSigningSecret

func WithSigningSecret(secret string) Option

WithSigningSecret sets the request signing secret (apisign_...). It is required for app keys: when set, the client HMAC-SHA512-signs every request automatically. secret is the raw signing secret string. Keep it server-side only.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout replaces the HTTP client with a fresh *http.Client whose per-request timeout is d. Use WithHTTPClient instead if you need to configure more than the timeout.

type Order added in v0.5.0

type Order = string

Order is the sort direction for list endpoints. It is a string alias; use OrderAsc / OrderDesc (or pass "asc" / "desc" directly).

const (
	// OrderAsc sorts oldest-first.
	OrderAsc Order = "asc"
	// OrderDesc sorts newest-first.
	OrderDesc Order = "desc"
)

Sort directions accepted by list endpoints via the order query parameter.

type Page

type Page[T any] struct {
	// Items holds this page's rows.
	Items []T `json:"items"`
	// NextCursor is the opaque cursor for the next page. Pass it back as the list
	// query's Before. It is "" (null on the wire) on the last page.
	NextCursor string `json:"nextCursor"`
	// Total is the true count for the filtered range, independent of paging. It is
	// only populated by the ledger lists (refunds, conversions) and reconciliation.
	Total int `json:"total,omitempty"`
}

Page is one page of a cursor-paginated list. T is the element type; loosely typed lists use Page[JSON]. Callers page by echoing NextCursor back as the query's Before; an empty NextCursor means the last page.

type PaymentType

type PaymentType = string

PaymentType enumerates the fee-bearing operation kinds. It is an alias for string; use the Payment* constants for the accepted values.

const (
	// PaymentCheckout is a pay-in (customer pays the merchant).
	PaymentCheckout PaymentType = "CHECKOUT"
	// PaymentWithdrawal is an on-chain payout/withdrawal.
	PaymentWithdrawal PaymentType = "WITHDRAWAL"
	// PaymentPayout is an alias for PaymentWithdrawal (payouts and withdrawals share one fee).
	PaymentPayout PaymentType = "PAYOUT"
	// PaymentOffRamp is a crypto-to-fiat off-ramp withdrawal.
	PaymentOffRamp PaymentType = "OFFRAMP"
	// PaymentGiftCard is a gift-card issuance.
	PaymentGiftCard PaymentType = "GIFTCARD"
)

The set of PaymentType values accepted by fee/preview. Conversions and subscriptions are not previewable (their cost is a live quote / settled per cycle) and are rejected with 400.

type PayoutItem

type PayoutItem struct {
	// RecipientAddress is the destination on-chain wallet address.
	RecipientAddress string `json:"recipientAddress"`
	// Chain is the blockchain network to send over, e.g. "TRX", "ETH".
	Chain string `json:"chain"`
	// Amount is the amount and currency to send to this recipient.
	Amount Money `json:"amount"`
	// Memo is an optional destination memo/tag (required by some chains/exchanges).
	Memo string `json:"memo,omitempty"`
}

PayoutItem is one recipient in a batch payout.

type PayoutsService

type PayoutsService struct {
	// contains filtered or unexported fields
}

PayoutsService sends batch on-chain payouts and reads their status. Creating a payout requires payouts:write; reads require payouts:read.

func (*PayoutsService) Create

func (s *PayoutsService) Create(ctx context.Context, items []PayoutItem, opts ...RequestOption) (JSON, error)

Create submits a batch payout of items and returns the batch details as JSON. Pass WithIdempotencyKey to make retries safe: replaying with the same key returns the original batch instead of paying twice. It returns an error if rejected. Example:

batch, err := ap.Payouts.Create(ctx,
	[]absolutepay.PayoutItem{{
		RecipientAddress: "T...",
		Chain:            "TRX",
		Amount:           absolutepay.Money{Amount: "5.00", Currency: "USDT"},
	}},
	absolutepay.WithIdempotencyKey("payout-2026-06-01-001"),
)

func (*PayoutsService) Get

func (s *PayoutsService) Get(ctx context.Context, id string) (JSON, error)

Get looks up a payout batch by its id and returns its status as JSON, or an error.

func (*PayoutsService) Options

func (s *PayoutsService) Options(ctx context.Context, currency string) (*Page[JSON], error)

Options lists the supported chains plus the per-chain withdraw fee and limits for a currency, as a Page (one item per chain option). currency is the asset code (e.g. "USDT"). It returns the options, or an error.

type PlanParams

type PlanParams struct {
	// MerchantPlanNo is your unique plan reference.
	MerchantPlanNo string `json:"merchantPlanNo"`
	// Name is the human-readable plan name.
	Name string `json:"name"`
	// Amount is the amount and currency charged each cycle.
	Amount Money `json:"amount"`
	// Interval is the billing interval unit, e.g. "DAY", "WEEK", "MONTH", "YEAR".
	Interval string `json:"interval"`
	// IntervalCount is the number of Interval units between charges (e.g. 3 with "MONTH" = quarterly).
	IntervalCount int `json:"intervalCount"`
	// TotalCycles is the number of charges before the subscription ends (0 = unlimited).
	TotalCycles int `json:"totalCycles"`
}

PlanParams defines a recurring billing plan.

type QuoteParams

type QuoteParams struct {
	// SellCurrency is the currency code you are converting from.
	SellCurrency string `json:"sellCurrency"`
	// BuyCurrency is the currency code you are converting to.
	BuyCurrency string `json:"buyCurrency"`
	// SellAmount fixes the amount to sell, as a decimal string. Optional (set this OR BuyAmount).
	SellAmount string `json:"sellAmount,omitempty"`
	// BuyAmount fixes the amount to buy, as a decimal string. Optional (set this OR SellAmount).
	BuyAmount string `json:"buyAmount,omitempty"`
}

QuoteParams requests a conversion quote. Set exactly one of SellAmount or BuyAmount to fix that side; the other is computed from the rate.

type ReconciliationQuery added in v0.2.0

type ReconciliationQuery struct {
	// From is the inclusive start of the time range, in epoch milliseconds (0 = unbounded).
	From int64
	// To is the inclusive end of the time range, in epoch milliseconds (0 = unbounded).
	To int64
	// Limit is the maximum number of rows per page. 0 means the server default.
	Limit int
	// Before is the opaque cursor from a previous page's Page.NextCursor.
	Before string
	// Order is the sort direction, OrderAsc or OrderDesc.
	Order Order
}

ReconciliationQuery filters a settlement reconciliation report by time range and page. All fields are optional; zero values are omitted.

type ReconciliationService added in v0.2.0

type ReconciliationService struct {
	// contains filtered or unexported fields
}

ReconciliationService reads settlement reconciliation reports that pair each settled payment/withdrawal with its network fee and net amount. Requires the ledger:read scope.

func (*ReconciliationService) Payments added in v0.2.0

Payments returns a cursor-paginated page of the settled pay-in reconciliation report matching q (the page carries Total, the true count for the filtered range), or an error. See ReconciliationQuery.

func (*ReconciliationService) Withdrawals added in v0.2.0

Withdrawals returns a cursor-paginated page of the settled withdrawal/payout reconciliation report matching q (the page carries Total), or an error. See ReconciliationQuery.

type RefundParams

type RefundParams struct {
	// MerchantTradeNo is the order reference of the checkout being refunded.
	MerchantTradeNo string `json:"merchantTradeNo"`
	// Amount is the amount and currency to refund (may be a partial amount).
	Amount Money `json:"amount"`
	// Reason is an optional human-readable refund reason.
	Reason string `json:"reason,omitempty"`
}

RefundParams is the request body for Create.

type RefundsService

type RefundsService struct {
	// contains filtered or unexported fields
}

RefundsService issues refunds against settled checkout orders and reads the settled refund ledger. Issuing requires payments:write; reads require ledger:read.

func (*RefundsService) Create

func (s *RefundsService) Create(ctx context.Context, p RefundParams, opts ...RequestOption) (JSON, error)

Create issues a refund against a settled checkout order and returns the refund details as JSON (including a refundRequestId), or an error. Pass WithIdempotencyKey to make retries safe. Example:

refund, err := ap.Refunds.Create(ctx, absolutepay.RefundParams{
	MerchantTradeNo: "order-123",
	Amount:          absolutepay.Money{Amount: "10.00", Currency: "USDT"},
	Reason:          "customer request",
}, absolutepay.WithIdempotencyKey("refund-order-123-1"))

func (*RefundsService) Get

func (s *RefundsService) Get(ctx context.Context, id string) (JSON, error)

Get looks up a refund by its refundRequestId and returns its status as JSON, or an error.

func (*RefundsService) List added in v0.5.0

func (s *RefundsService) List(ctx context.Context, q LedgerQuery) (*Page[JSON], error)

List returns a cursor-paginated page of the settled REFUND ledger history (the page carries Total, the true count for the filtered range). q filters by time range/currency and pages; pass a prior Page.NextCursor as q.Before for the next page ("" means the last page). See LedgerQuery.

type RequestOption

type RequestOption func(map[string]string)

RequestOption sets per-request extras such as an idempotency key. The resulting headers are merged AFTER request signing and are therefore NOT part of the signed canonical string.

func WithIdempotencyKey

func WithIdempotencyKey(key string) RequestOption

WithIdempotencyKey makes a money-moving POST retry-safe: replaying a request with the same key returns the original result instead of performing the action twice (a 409 surfaces an in-progress/conflicting replay as a normal *Error). key is a caller-chosen unique string (e.g. a UUID) that you reuse across retries of the same logical operation.

type ResourceUpdate added in v0.5.0

type ResourceUpdate struct {
	// Paused pauses (true) or resumes (false) the link. nil leaves it unchanged.
	Paused *bool `json:"paused,omitempty"`
	// RedirectURL replaces the post-checkout redirect URL. nil leaves it unchanged.
	RedirectURL *string `json:"redirectUrl,omitempty"`
	// ExpiresAt replaces the expiry (epoch ms). nil leaves it unchanged.
	ExpiresAt *int64 `json:"expiresAt,omitempty"`
	// Description replaces the description. nil leaves it unchanged.
	Description *string `json:"description,omitempty"`
}

ResourceUpdate patches an open checkout or invoice. Only set fields are sent; a pointer left nil is omitted. To explicitly clear RedirectURL/Description, send an empty string; to change Paused, set the pointer.

type SubscribeParams

type SubscribeParams struct {
	// MerchantSubNo is your unique subscription reference.
	MerchantSubNo string `json:"merchantSubNo"`
	// PlanNo is the plan's reference (MerchantPlanNo) to subscribe to.
	PlanNo string `json:"planNo"`
	// CallbackURL is an optional per-subscription webhook override URL.
	CallbackURL string `json:"callbackUrl,omitempty"`
}

SubscribeParams subscribes a customer to an existing plan.

type SubscriptionPlansService added in v0.5.0

type SubscriptionPlansService struct {
	// contains filtered or unexported fields
}

SubscriptionPlansService manages the recurring billing plan catalog. Reach it via ap.Subscriptions.Plans. Creating a plan requires subscriptions:write; listing requires subscriptions:read.

func (*SubscriptionPlansService) Create added in v0.5.0

Create creates a recurring billing plan from p and returns it as JSON, or an error. Pass WithIdempotencyKey to make retries safe.

func (*SubscriptionPlansService) List added in v0.5.0

List returns the workspace's recurring billing plans as a Page (one item per plan), or an error.

type SubscriptionsService

type SubscriptionsService struct {

	// Plans manages the recurring billing plan catalog (ap.Subscriptions.Plans.*).
	Plans *SubscriptionPlansService
	// contains filtered or unexported fields
}

SubscriptionsService manages recurring subscriptions. Reach the plan catalog via the nested Plans sub-service (ap.Subscriptions.Plans). Writes require subscriptions:write; reads require subscriptions:read.

func (*SubscriptionsService) Cancel

func (s *SubscriptionsService) Cancel(ctx context.Context, merchantSubNo string) (JSON, error)

Cancel cancels a subscription identified by merchantSubNo and returns the updated state as JSON, or an error.

func (*SubscriptionsService) Create

Create subscribes a customer to a plan (see SubscribeParams) and returns the new subscription as JSON, or an error. Pass WithIdempotencyKey to make retries safe.

func (*SubscriptionsService) Deductions

func (s *SubscriptionsService) Deductions(ctx context.Context, merchantSubNo string) (*Page[JSON], error)

Deductions returns the per-cycle charge history for a subscription as a Page (one item per cycle). merchantSubNo is the subscription reference. It returns an error if rejected.

func (*SubscriptionsService) List

List returns a cursor-paginated page of subscriptions. q sets page size, cursor, order, and optional status/search filters; pass a prior Page.NextCursor as q.Before ("" means the last page). See ListQuery.

Jump to

Keyboard shortcuts

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