Go SDK
The official Go client — github.com/crylabsorg/suward-sdk-go. A typed client over the full merchant API, with context on every call.
Install
go get github.com/crylabsorg/suward-sdk-goCreate a client
package main
import (
"context"
"os"
"github.com/crylabsorg/suward-sdk-go/client"
"github.com/crylabsorg/suward-sdk-go/option"
)
func main() {
suward := client.NewClient(option.WithAPIKey(os.Getenv("SUWARD_API_KEY")))
ctx := context.Background()
_ = ctx
_ = suward
}The quickstart flow, in Go
// The root package is named api, so alias it on import.
import suwardsdkgo "github.com/crylabsorg/suward-sdk-go"
// ptr returns a pointer to v — the SDK takes *T for every optional field.
func ptr[T any](v T) *T { return &v }
payment, err := suward.Payments.CreatePayment(ctx, &suwardsdkgo.CryptopayCreatePaymentRequest{
Amount: "100000000", // integer string, smallest unit
Asset: ptr(suwardsdkgo.CryptopayAssetIDTeststablecoinOptimism),
ExternalID: ptr(order.ID), // makes the call idempotent
})
if err != nil {
return err
}
// Projects with an activation flow start the payment in pending/created, with no
// address and no way into accepted until it is activated.
if payment.SubStatus == suwardsdkgo.CryptopayPaymentSubStatusEnumCreated {
if _, err = suward.Payments.ActivatePayment(ctx, &suwardsdkgo.PostV1PaymentsPaymentIDActivateRequest{
PaymentID: payment.ID,
}); err != nil {
return err
}
}
// send the customer to payment.PaymentPageURL
// drive the lifecycle while you write the handler (test assets only)
_, err = suward.Payments.SimulatePayment(ctx, &suwardsdkgo.CryptopaySimulatePaymentRequest{
PaymentID: payment.ID,
Status: suwardsdkgo.CryptopayPaymentStatusEnumAccepted,
SubStatus: suwardsdkgo.CryptopayPaymentSubStatusEnumCompleted,
})Quote before you create
quote, err := suward.Payments.QuotePaymentFees(ctx, &suwardsdkgo.CryptopayQuotePaymentRequest{
Asset: suwardsdkgo.CryptopayAssetIDUsdtArbitrum,
Amount: "100000000",
ServiceFeePayer: ptr(suwardsdkgo.CryptopayFeePayerCustomer),
NetworkFeePayer: ptr(suwardsdkgo.CryptopayFeePayerCustomer),
ComplianceLevel: ptr(suwardsdkgo.CryptopayComplianceLevelBasic),
})Static wallets
wallet, err := suward.StaticWallets.CreateStaticWallet(ctx, &suwardsdkgo.CryptopayCreateStaticWalletRequest{
ExternalID: ptr("customer-99"),
AllowedAssets: []suwardsdkgo.CryptopayAssetID{suwardsdkgo.CryptopayAssetIDUsdtEthereum, suwardsdkgo.CryptopayAssetIDUsdtArbitrum},
})
deposits, err := suward.StaticWallets.ListStaticWalletDeposits(ctx, &suwardsdkgo.GetV1StaticWalletsStaticWalletIDDepositsRequest{
StaticWalletID: wallet.ID,
Limit: ptr(100),
})Verify webhooks
Unlike the TypeScript client, the Go SDK does not ship a signature-verification helper — there is no webhooks package in suward-sdk-go. Verify the Ed25519 signature yourself with the standard library's crypto/ed25519: raw body, signature header, public key — verified before parsing, then deduplicated on eventId in your database. webhookPublicKey arrives as a PKIX/SPKI PEM block, so parse it with pem.Decode and x509.ParsePKIXPublicKey. A working example is on the Webhooks page.
Errors
import (
"errors"
"github.com/crylabsorg/suward-sdk-go/core"
)
payment, err := suward.Payments.CreatePayment(ctx, req)
if err != nil {
var apiErr *core.APIError
if errors.As(err, &apiErr) {
// branch on the stable HTTP status, not the message
if apiErr.StatusCode == 409 {
// externalId already used — fetch the existing payment
}
}
return err
}The parsed error body lives on the per-status wrapper types — errors.As(err, &badRequest) with *suwardsdkgo.BadRequestError gives you badRequest.Body.ErrorCode.
Codes and retry rules → Errors & limits.
Something unclear? payments@suward.com — we treat every integration question as a documentation defect.