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

terminal
go get github.com/crylabsorg/suward-sdk-go

Create a client

main.go
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

checkout.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.go
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

wallets.go
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

errors.go
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.