GOAT Network
GOAT FlowReference

SDK Reference

GOAT Flow provides server and browser SDKs, along with PayKit SDKs and tools, for Checkout, QuickPay, and API Payments integrations.

Package Matrix

PackageRuntimePrimary use
goatflow-sdk-serverNode.js backendOrders, Checkout Sessions, status, server-issued payment records, eligible Crypto-order cancellation, and authenticated merchant API calls
goatflow-checkoutBrowserRedirect to a complete Hosted Page, or open it in a new tab or window
@goatx402/quickpay-reactReactPayKit Hosted Page, Embedded Checkout, and Payment Element surfaces; package publishing pending
goatflow-sdkBrowser / Node.jsCustom buyer wallet transfers, ERC-20 helpers, and MPP buyer flows
goatflow-paykitNode.js / CLIPayKit SDK and CLI for manifest-driven QuickPay flows used by programmatic buyers and agents

Server SDK

Use the Server SDK whenever an integration needs merchant credentials, server-authoritative pricing, order management, or verified fulfillment. It is the primary integration for Custom Checkout and custom API Payments.

npm install goatflow-sdk-server@0.4.0
import { GoatFlowClient } from 'goatflow-sdk-server'

const client = new GoatFlowClient({
  baseUrl: process.env.GOATX402_API_URL!,
  apiKey: process.env.GOATX402_API_KEY!,
  apiSecret: process.env.GOATX402_API_SECRET!,
})

The reference below targets the published Node.js Server SDK 0.4.0, which requires Node.js 18 or later. Merchant API requests are signed with timestamps and nonces; signatures authenticate the request, not the payment records returned by the API.

Main Methods

The methods below return promises. The named return types are the SDK's TypeScript exports; a type name containing Proof does not itself imply a cryptographic signature.

MethodParametersResolved valueLimits and important behavior
createOrder(params)CreateOrderParams: dappOrderId, chainId, tokenSymbol, fromAddress, amountWei; optional configured tokenContractOrder, including orderId, fromChainId, payToAddress, amountWei, and expiresAtCreates an ordinary Crypto order. Duplicate dappOrderId is rejected; no general idempotencyKey parameter
createOrderRaw(params)The same CreateOrderParamsX402PaymentRequired, the raw payment requirements with order_idHTTP 402 is the expected creation response. The raw ID is order_id, not orderId; the same duplicate rule applies
createCheckoutSession(params)CreateCheckoutSessionParams: public checkoutType: 'DIRECT', payment rails and their price fields, optional reference/metadata/return URLsCheckoutSession, including checkoutId, url, and expiresAtDuplicate non-empty clientReferenceId for the same merchant returns 409; optional return URLs need an allowlist; Card has additional prerequisites
getOrderStatus(orderId, options?)Saved GOAT Flow order ID; optional { timeoutMs } request deadlineOrderProof, an order-status/details recordRead the explicit status; this return type is not a signed MPP receipt
waitForConfirmation(orderId, options?)Saved order ID; { timeout, interval, onStatusChange }OrderProof on a success or failure terminal stateResolves for PAYMENT_CONFIRMED, INVOICED, FAILED, EXPIRED, or CANCELLED. Resolution alone does not authorize fulfillment
getOrderProof(orderId)Saved order ID with an available payment recordOrderProofResponse: { payload, signature }The historical signature field is an unsigned hash, not a platform signature; see payment-record limits
cancelOrder(orderId)Eligible Crypto order IDvoid after the request succeedsOnly CHECKOUT_VERIFIED orders are eligible. FIAT_STRIPE is rejected; this is not a refund or on-chain reversal
getMerchant(merchantId)Merchant ID in the selected environmentMerchantInfo, including mapped supported-token configurationPublic lookup; this call does not send HMAC merchant credentials. Configuration is environment-specific

Order Creation and Retry Rules

For ordinary createOrder() and createOrderRaw() calls, save your business request, a unique dappOrderId, the returned order ID, and payment requirements. The SDK neither accepts nor sends a general idempotencyKey on these methods. Repeating an existing dappOrderId is rejected as order already exists, not returned as the original order.

Checkout Session creation has a different contract: repeating a non-empty clientReferenceId for the same merchant returns 409, not the original session. Neither create operation should be blindly retried after an unknown outcome. Keep the original attempt and reconcile it before creating another payable order/session. See ordinary-order recovery and Checkout Session recovery.

Status and proof reads can be retried after transient failures without creating a new payment. An HTTP authentication nonce must still be fresh for each authenticated request; let the SDK generate it. Do not generalize these read semantics to create or cancellation operations.

Waiting for a Payment Result

waitForConfirmation() defaults to a 300,000 ms overall timeout and a 3,000 ms poll interval. Its option names are timeout and interval, both in milliseconds; timeoutMs belongs to the single-request getOrderStatus() option and is not a waitForConfirmation() option.

The helper resolves normally on all five of these states:

Returned statusApplication action
PAYMENT_CONFIRMEDPayment evidence is confirmed, not a general fulfillment permission. Card can be held here; query the same order until platform completion or reconcile its restriction
INVOICEDPlatform order completion; verify the saved purchase, current business eligibility, and idempotent delivery
FAILED / EXPIRED / CANCELLEDDo not fulfill. Preserve the order and any transaction evidence for reconciliation; do not automatically take another payment

Always branch on the returned status. This conservative, cross-method example reports platform order completion, not merely payment confirmation:

export async function readPaymentResult(orderId: string) {
  const order = await client.waitForConfirmation(orderId, {
    timeout: 120_000,
    interval: 2_000,
  })

  return { platformCompleted: order.status === 'INVOICED', order }
}

A resolved { platformCompleted: false } is an application result, not an SDK exception and not proof of non-payment. waitForConfirmation() stops at PAYMENT_CONFIRMED; it does not wait through a Card fulfillment hold until INVOICED. Continue safe getOrderStatus() reads or use the applicable authenticated completion event; do not start another payment. Card Checkout Session completion is COMPLETED, a different state contract. See platform fulfillment gates. Even platformCompleted: true does not replace purchase ownership, expected terms, current refund/dispute and business checks, or idempotent delivery.

The helper throws when its overall deadline is reached or a non-retryable request error occurs, such as 401 or 404. Transient read failures are retried within the remaining deadline. A timeout is not proof of an unpaid order: preserve the mapping and query the same order before any replacement payment. A poller can see INVOICED without ever seeing PAYMENT_CONFIRMED.

Payment Records and MPP Receipts

getOrderProof() returns a server-issued payment record. Its historical signature field is the Keccak256 hash of these seven values concatenated in order without separators:

order_id, tx_hash, log_index, from_addr, to_addr, amount_wei, from_chain_id

No platform private key signs this value. Anyone with those fields can recompute it, and it does not cover status or the rest of the response. It is not an independently verifiable attestation, nor is it a hash of the entire record. Use the authenticated API response as a platform-reported record and verify payload.tx_hash and its payment details on-chain when independent evidence is required.

This is different from the GOAT Flow MPP Payment-Receipt, whose signed contents are checked by the deployment-matched verifier with its trusted key and additional audience, route, and expiry checks. Do not use the MPP public key to verify the signature returned by getOrderProof(), or substitute an order proof for a Payment-Receipt. Also distinguish the OrderProof status/details type returned by getOrderStatus() and waitForConfirmation() from the OrderProofResponse payment-record type returned by getOrderProof(). See MPP receipt verification.

Cancellation Limits

cancelOrder() is for eligible unpaid Crypto orders that are still in CHECKOUT_VERIFIED. The backend rejects orders in other states and rejects FIAT_STRIPE orders through this endpoint regardless of their state. Card orders must follow the platform's Stripe-aware lifecycle, not generic Crypto cancellation.

Successful cancellation does not send money back to the payer, cancel a blockchain transaction, or reverse an already-broadcast transfer. Do not use it as a refund API. If cancellation times out or races with payment, read the original order and reconcile any submitted transaction before taking further action.

Checkout Session Example

This example is Crypto-only and assumes the merchant meets the DIRECT Crypto session prerequisites. For Card-only or combined Card-and-Crypto sessions, see Checkout Session payment methods.

const session = await client.createCheckoutSession({
  checkoutType: 'DIRECT',
  paymentRails: ['crypto'],
  price: '19.95',
  lineItems: [{ name: 'Coffee mug', quantity: 1, amount: '19.95' }],
  clientReferenceId: 'cart_9f31',
  expiresIn: 1800,
})

Save the returned checkoutId, url, and expiresAt against your internal order and reference, then give the browser the session data it needs. Never expose the API secret or other server credentials. Repeated non-empty clientReferenceId values return 409, not the original session. Follow the session recovery rules.

The example omits successUrl and cancelUrl; include them only after the merchant's redirect allowlist has been configured. Always use the returned expiresAt, particularly for Card sessions whose lifetime and initialization window differ from Crypto-only sessions.

Go Server SDK

The codebase also contains this source-only Go module, requiring Go 1.25 or later:

github.com/goatnetwork/goatflow-sdk-server

The logical module path is not published from a standalone source repository. Do not assume go get github.com/goatnetwork/goatflow-sdk-server will work. Clone GOATNetwork/x402 and bind that module path to its checked-in directory with a local replace directive.

Run the following from your application's existing Go module. This example puts the source checkout at ../x402 and pins the reviewed public source snapshot; adjust the local path if your directory layout differs:

git clone https://github.com/GOATNetwork/x402.git ../x402
git -C ../x402 checkout --detach bd0eff522ca887c61d8f4afefc5478f0534324d4
go mod edit -require=github.com/goatnetwork/goatflow-sdk-server@v0.0.0
go mod edit -replace=github.com/goatnetwork/goatflow-sdk-server=../x402/goatx402-sdk-server-go

v0.0.0 here is a local module requirement satisfied by replace, not an announced SDK release. Add the SDK import to your application, for example:

goat_flow_client.go
package payments

import (
    "os"

    goatflow "github.com/goatnetwork/goatflow-sdk-server"
)

func newGoatFlowClient() *goatflow.Client {
    return goatflow.NewClient(goatflow.Config{
        BaseURL:   os.Getenv("GOATX402_API_URL"),
        APIKey:    os.Getenv("GOATX402_API_KEY"),
        APISecret: os.Getenv("GOATX402_API_SECRET"),
    })
}

Then resolve the local module:

go mod tidy

The Go source covers authenticated merchant API access, orders, supported Checkout Session creation, status retrieval, payment records, and eligible cancellation. Pin and review the Go source separately from npm versions: the public snapshot above does not expose the TypeScript 0.4.0 Card request fields in CreateCheckoutSessionParams. Use the published TypeScript SDK for the Card examples on this site unless an approved Go source version exposes the corresponding fields. See the upstream Go installation and capability notes.

Browser SDK

Browser packages handle buyer interaction. Merchant credentials and final fulfillment decisions remain on a trusted backend.

Hosted Checkout

goatflow-checkout opens a complete, standalone Hosted Page through a redirect or in a new tab or window. It is optional: React applications can use the PayKit React SDK Hosted Page link, and any application can navigate directly to the backend-returned session.url.

The display option accepts redirect for current-tab navigation, tab for a new tab, or popup for a separate browser window. These are SDK opening options, not separate Checkout UI types.

npm install goatflow-checkout
import { GoatCheckout } from 'goatflow-checkout'

export function openCheckout(session: { checkoutId: string; url: string }) {
  const checkout = GoatCheckout({ origin: new URL(session.url).origin })

  checkout.open({
    checkoutId: session.checkoutId,
    display: 'tab',
    onSuccess(result) {
      // Update the UI; verify fulfillment on the backend.
      console.log(result.status)
    },
  })
}

Use the Checkout Session ID and URL returned by your backend, and call openCheckout(session) synchronously from a click or tap handler after loading the session. Checkout does not require a Merchant Portal product link.

The same SDK also supports merchant + productKey for QuickPay; see the optional product-link integration.

Open a Product with the Checkout SDK

The shared goatflow-checkout browser SDK can also open a QuickPay product. The merchant + productKey example below is the Crypto product entry; do not use it as a generic Card entry. For Card, use the generated buyer link or create a Card checkout link. This QuickPay integration is separate from opening a server-created Checkout Session.

npm install goatflow-checkout

Copy the product link from the Merchant Portal and use its origin. Supply the merchant ID and product key for that same product; do not construct the service origin from the merchant ID.

import { GoatCheckout } from 'goatflow-checkout'

export function openProduct(
  productLink: string,
  merchantId: string,
  productKey: string,
) {
  const checkout = GoatCheckout({ origin: new URL(productLink).origin })

  checkout.open({
    merchant: merchantId,
    productKey,
    display: 'popup',
    onSuccess(result) {
      // Update the UI only. Confirm fulfillment on the backend.
      console.log(result.status, result.tx_hash)
    },
  })
}

Call openProduct() synchronously from a click or tap handler so the browser does not block the popup. The product price is resolved by GOAT Flow, not supplied by this browser call. To share the product without an SDK integration, use the copied product link directly.

PayKit React SDK

The PayKit React SDK supports three checkout UI options:

UI optionWhat it providesSource export
Hosted PageA link to the complete, standalone hosted payment pagePayKitHostedPageLink (alias of QuickPayHostedPageLink), or quickPayHostedPageHref
Embedded CheckoutA complete checkout block embedded inside your applicationQuickPayEmbeddedCheckout
Payment ElementThe payment section embedded alongside your own page, product, or cart UIQuickPayPaymentElement

The Hosted Page link accepts a server-created session through source: { type: 'checkout-session', checkoutId, checkoutType: 'direct' }. Set basePath to the hosted origin from the session response; otherwise the generated link is relative to your site. The helper builds the standard hosted session route, not an arbitrary session URL. Use the complete session.url directly if your deployment uses a custom route, prefix, or additional URL parameters. The link does not need QuickPayProvider or apiBase and does not emit a payment-success callback. See the Hosted Page React example.

The embedded components use QuickPayProvider and support appearance options and lifecycle callbacks. The draft package name is @goatx402/quickpay-react.

The React package is not currently published to npm. This applies to all three UI options, including the Hosted Page link. Treat it as unavailable to general integrations until a formal package version and release channel are announced. Do not copy an npm install @goatx402/quickpay-react command into a production integration before that release.

Custom Wallet Payment

npm install goatflow-sdk ethers

PaymentHelper submits buyer-authorized ERC-20 transfers for server-created orders. MPPClient supports the buyer side of GOAT Flow MPP integrations.

PayKit SDK for Programmatic Buyers and Agents

This reference is for custom payer and agent software. Merchants using the QuickPay portal and hosted links do not need to install these tools.

goatflow-paykit loads a merchant's agent document and manifest, inspects payment capabilities, executes Crypto purchases, creates hosted Card checkout links, and supports the GOAT Flow MPP buyer flow. Card-link creation prepares a payment entry point for a customer; the customer completes the Card payment.

The CLI also provides goatflow-quickpay as a compatibility executable; new tooling should use goatflow-paykit.

Agent Discovery

QuickPay exposes an agent-readable entry point and manifest. Copy the agent.md and manifest.json links shown in the Merchant Portal rather than constructing them manually.

The manifest can describe merchant information, eligible Crypto chain/Token options, Card availability and currency, amount limits, fixed-price products, custom-amount support, and API Payments routes included for agent discovery. Check the products and custom-amount capability for the chosen payment method; availability on one method does not imply availability on the other.

The Card capability declares human_action_required: true: an agent may create and return a checkout link, but does not supply card credentials or complete the card payment. Treat the generated link as the trust anchor and reject a manifest that identifies another merchant or redirects payment requests to an unrelated host.

Installation

Install PayKit, the public payer and agent package for QuickPay integrations:

npm install goatflow-paykit

Inspect Available Payment Methods

Inspect the capabilities advertised by a merchant. Inspection needs network access to the public manifest, but does not need a wallet, private key, or blockchain RPC:

npx goatflow-paykit inspect \
  "PASTE_AGENT_MD_URL_FROM_MERCHANT_PORTAL" --json

Crypto Payment Prerequisites

pay-product and pay-x402 execute Crypto payments. Before starting a new transfer, provide both a payer wallet and an RPC URL for the selected chain. Set the RPC through one of:

  • --rpc <url> on the command;
  • a chain-specific variable, such as PAYKIT_RPC_2345;
  • PAYKIT_RPC as a fallback for the selected chain.

The current resolution order is the chain-specific variable, then --rpc, then the general variable. Use an RPC that serves the requested chain. Without one, a transfer on chain 2345 fails with no RPC URL configured for chain 2345. Replace the RPC and Token placeholders below with the configuration for your selected environment.

Prefer PAYKIT_PRIVATE_KEY supplied out of band or a permission-restricted --wallet-file. The legacy QUICKPAY_PRIVATE_KEY name remains a compatibility alias. A private key in command-line arguments can be exposed through shell history, process listings, CI logs, or agent transcripts.

Amount Encoding

For Crypto, decimal prices and --amount values are in units of the selected Token, not automatically converted from USD. For example, 12.50 in USDC is 12.50 USDC, or 12500000 smallest units for a 6-decimal Token. Check the manifest's Token precision and amount limits. QuickPay Card amounts use USD; 12.50 means 12.50 USD (1250 minor units), not a Token quantity.

Pay with Crypto

Buy a fixed-price product using a stable key for this purchase:

npx goatflow-paykit pay-product \
  "PASTE_AGENT_MD_URL_FROM_MERCHANT_PORTAL" \
  --product logo-design \
  --token-contract 0xToken \
  --chain 2345 \
  --rpc "YOUR_CHAIN_2345_RPC_URL" \
  --idempotency-key purchase_2026_00042

Pay a custom amount:

npx goatflow-paykit pay-x402 \
  "PASTE_AGENT_MD_URL_FROM_MERCHANT_PORTAL" \
  --amount 12.50 \
  --token-contract 0xToken \
  --chain 2345 \
  --rpc "YOUR_CHAIN_2345_RPC_URL" \
  --idempotency-key invoice_901

Generate and save the idempotency key before the first attempt. Retry the same purchase with the same key, payer, product or custom amount, chain, and Token. Use a new key for a genuinely new purchase, even of the same product. See Crypto recovery before retrying an interrupted payment.

Create a Card link for a product advertised as available on the Card method:

npx goatflow-paykit create-card-checkout \
  "PASTE_AGENT_MD_URL_FROM_MERCHANT_PORTAL" \
  --product logo-design

Alternatively, create a custom-amount Card link for 12.50 USD:

npx goatflow-paykit create-card-checkout \
  "PASTE_AGENT_MD_URL_FROM_MERCHANT_PORTAL" \
  --amount 12.50 \
  --memo invoice_902

Use exactly one of --product or --amount. Product mode takes its price and product identity from the merchant configuration and does not accept --memo. For a custom amount, supply --memo when the merchant requires a reference.

This command needs neither a Crypto wallet nor a blockchain RPC. It returns checkout_id, url, currency, expires_at, and human_action_required: true. Send the returned URL to the customer, who opens the hosted page and completes the Card payment. Command success means a link was created, not that the customer paid. Never ask an agent to collect card credentials.

Library Usage

import { QuickPayClient } from 'goatflow-paykit'

const client = new QuickPayClient(
  'PASTE_AGENT_MD_URL_FROM_MERCHANT_PORTAL',
)

const manifest = await client.loadManifest()
const capabilities = await client.inspect()

For Card, use the same client to create a product checkout link:

const cardLink = await client.createFiatCheckoutLink({
  productKey: 'logo-design',
})

// Send cardLink.url to the customer through your application, not a debug log.
// cardLink.human_action_required is true; no Card payment has been completed.

For a custom amount, pass { amount: '12.50', memo: 'invoice_902' } instead of productKey. Do not combine a product with a custom amount or memo. Neither Card-link creation nor inspection needs an on-chain payment backend. The published Card-link options do not include an idempotencyKey.

Payment and Recovery

Crypto Recovery

  • Keep one explicit idempotency key for one logical purchase; keep the original payer, product, chain, and Token when recovering it.
  • A reused session is resumed or polled; it is not automatically paid again.
  • Use a force option only after confirming that the first transfer was never submitted.
  • Preserve the session ID, transaction hash, and payment requirement when verification is pending.
  • Reconcile an expired-looking session after a known broadcast; the transaction may be observed later.
  • Never rebroadcast only because the browser closed or a status request timed out.

When no explicit key is supplied, the backend derives a key using a 120-second time bucket. This is short-term duplicate protection, not a durable purchase identifier. Crossing a bucket can change the automatic key, and a removed or disabled product may prevent automatic recovery. An explicit key lets the backend recover the original stored product session before resolving its current price or availability; it is still subject to the session record being available. Do not treat recovery as permission to make a fresh transfer.

Save the returned checkout_id, URL, currency, and expires_at against your internal purchase. Reopen the same link while that session remains valid and payable rather than creating a new Card link on every refresh. Use the returned expiry and the Card initialization window.

The public QuickPay Card-link command and SDK method do not expose the Crypto --idempotency-key option or promise that repeated creates return the same checkout. Do not assume the Crypto recovery rules or the authenticated Checkout Session duplicate-reference rules apply to this public link-creation endpoint. If creation or payment has an unknown outcome, reconcile the saved session and any order before offering another payable link.

MPP Tooling

GOAT Flow also provides TypeScript and Go MPP middleware and a verification sidecar for protecting API routes with signed receipts. The TypeScript package @goatnetwork/mpp-middleware was not available from public npm when verified; source availability or a public publish configuration does not establish a published release. Obtain a deployment-approved build or source archive from the platform team and follow the middleware build and installation instructions. Use deployment-matched GOAT Flow MPP clients and verifiers rather than assuming arbitrary MPP packages share the same wire format.

Security Rules

  • Never place merchant API keys or secrets in browser code.
  • Follow each operation's documented retry contract; an application request ID does not make ordinary order creation replay-safe.
  • Treat callbacks, redirects, and success pages as interface signals.
  • Bind priced purchases to merchant products or server-created sessions.
  • Fulfill only from verified backend status, authenticated webhooks, or verified receipts.
  • Pin package versions and keep each environment's credentials and generated links separate.

See Checkout, QuickPay, API Payments, and API Reference.

On this page