Skip to main content

v0 to v1 Migration Guide

This guide covers what changed between the previous checkout integration (v0) and the current integration (v1).

Use it if your existing merchant integration already uses v0 SDK methods or v0 webhook events.

Required SDK Upgrade

Before applying the migration steps below, upgrade both packages to 1.0.0:

npm install @zkp2p/pay-sdk@1.0.0 @zkp2p/pay-shared@1.0.0

Summary

  • The integration model is order-first in v1.
  • The canonical SDK creation method is createCheckout.
  • Fiat payments support multi-currency selection in checkout.
  • Webhook events moved from dotted lowercase names to uppercase lifecycle events.
  • Final order state handling should use PAYMENT_SETTLED, PAYMENT_FAILED, PAYMENT_EXPIRED, and ORDER_FULFILLED.
  • Crypto payout lifecycle is represented with PAYMENT_BRIDGE_* events.

New Features in v1

1. Referral Split Support

  • You can now configure referral splits directly in the checkout flow.
  • Settlement processing applies referral allocations automatically.
  • This makes net settlement and referral attribution easier to reconcile.

2. Partial Order Fulfillment

  • Orders can now be partially settled and remain open with status PARTIALLY_FULFILLED.
  • Additional payment attempts can continue until the order reaches FULFILLED.
  • The checkout experience supports completing the remaining amount in follow-up attempts.

3. Fee Modes (MERCHANT vs PAYEE)

feePayer controls quote behavior and settlement contribution accounting:

  • MERCHANT:
    • Buyer pays the displayed fiat amount.
    • Merchant absorbs fees.
  • PAYEE:
    • Buyer pays enough to cover both requested net and fees.
    • Merchant receives net settlement amount.

4. Custom Webhook Headers

  • Webhook endpoints now support merchant-defined custom headers.
  • Up to 10 headers are supported per webhook.
  • Header keys are normalized and validated as HTTP header names.

5. Dashboard Improvements

The merchant dashboard now includes:

  • Improved order and volume analytics (including order trend views).
  • Better webhook management UX (event selection, active toggles, header editing).
  • Expanded settings surfaces for account/profile and wallet configuration.

6. Better Team Management

  • Owners can invite team members directly by email from dashboard settings.
  • Invite email delivery and resend flows are built in.
  • Invited users can accept and join on first login without first creating their own separate merchant account.

Feature Changes

Previous Integration (v0)Current Integration (v1)Migration Action
Session-first flow (CheckoutSession, then order)Order-first flow (CheckoutOrder, payments attached to order)Store and reconcile by order.id
Exact-token and exact-fiat checkout modesXOR create request (requestedUsdcAmount OR requestedFiatAmount + requestedFiatCurrency)Migrate request payload builders to XOR amount mode
Session-level fiat currency defaultsMerchant config defaultPaymentCurrency + checkout geolocation fallbackMove default currency logic to merchant config + checkout
enabledPaymentPlatforms request fieldenabledRails request fieldRename the request field
metadata request fieldnotes request fieldRename and update payload shape (Record<string, unknown>)
URL shape /checkout?session=...&token=...URL shape /?order=...&token=...Update any URL parsing or validation logic

SDK Integration Changes

Canonical SDK Methods

Use these as the only public integration methods:

  • createCheckout
  • getMerchant
  • getCheckoutUrl
  • redirectToCheckout
  • createCheckoutAndRedirect

If your integration still uses createCheckoutSession or createSessionAndRedirect, migrate to the v1 methods above.

Method Mapping

Previous SDK (v0)Current SDK (v1)
createCheckoutSession(params, opts)createCheckout(params, opts)
createSessionAndRedirect(params, opts)createCheckoutAndRedirect(params, opts)
getMerchant(merchantId, opts)getMerchant(opts)
getCheckoutUrl(sessionId, opts, sessionToken)getCheckoutUrl(orderId, orderToken, opts)
redirectToCheckout(sessionId, sessionToken, opts)redirectToCheckout(orderId, orderToken, opts)

Request Parameter Mapping

createCheckoutSession (v0) -> createCheckout (v1)

Previous field (v0)Current field (v1)Notes
merchantIdRemovedMerchant context comes from apiKey
amountUsdcrequestedUsdcAmountRequired in v1
recipientAddressdestinationAddressOptional in v1 (merchant defaults can apply)
destinationChainIddestinationChainIdSame meaning
destinationTokendestinationTokenSame meaning (alias/address support)
enabledPaymentPlatformsenabledRailsRename
metadatanotesRename + broader value type
successUrlsuccessUrlSame field; nullable in API shape
cancelUrlcancelUrlSame field; nullable in API shape
checkoutModeRemovedNo exact-fiat request mode in v1 API
fiatAmount + fiatCurrencyrequestedFiatAmount + requestedFiatCurrencyFiat create mode in v1
maxFeePercentageRemovedConfigure fee limits from the Merchant Dashboard settings

Response Mapping

Previous response (v0)Current response (v1)
session.idorder.id
sessionTokenorderToken
checkoutUrlcheckoutUrl (still returned)
bridgeBridge lifecycle represented in webhook events (PAYMENT_BRIDGE_*)

API Endpoint Mapping

Previous endpoint (v0)Current endpoint (v1)
POST /api/checkout/sessionsPOST /api/v1/orders
GET /api/merchants/{merchantId}GET /api/v1/merchants/me

Before/After SDK Example

// v0
import { createCheckoutSession } from '@zkp2p/pay-sdk';

const session = await createCheckoutSession(
{
merchantId: 'merchant_123',
amountUsdc: '50.00',
destinationChainId: 8453,
destinationToken: 'USDC',
recipientAddress: '0xYourWalletAddress',
metadata: { orderId: 'order_123' },
},
{ apiBaseUrl: 'https://api.pay.peer.xyz', apiKey: process.env.ZKPAY_API_KEY! }
);
// v1
import { createCheckout } from '@zkp2p/pay-sdk';

const checkout = await createCheckout(
{
requestedFiatAmount: '50.00',
requestedFiatCurrency: 'EUR',
destinationChainId: 8453,
destinationToken: 'USDC',
destinationAddress: '0xYourWalletAddress',
notes: { orderId: 'order_123' },
},
{ apiBaseUrl: 'https://api.pay.peer.xyz', apiKey: process.env.ZKPAY_API_KEY! }
);

Webhook Changes

Event Name Migration

Previous event (v0)Current event(s) (v1)Notes
order.createdORDER_CREATEDOrder lifecycle creation
order.payment_sentNo direct equivalent (PAYMENT_CREATED is the closest lifecycle signal)v1 does not expose a dedicated payment_sent event
order.fulfilledPAYMENT_SETTLED and ORDER_FULFILLEDSubscribe to both for final success handling
order.failedPAYMENT_FAILEDTerminal payment failure signal
order.expiredPAYMENT_EXPIREDExpiration signal; cancellation flows can also emit cancel events
session.completedORDER_FULFILLEDUse ORDER_FULFILLED as the canonical checkout-complete event
session.startedORDER_CREATEDUse ORDER_CREATED as the canonical checkout-start event
session.abandonedNo equivalentWe no longer expire orders
payout.submittedPAYMENT_BRIDGE_SUBMITTEDCrypto payout/bridge lifecycle
payout.completedPAYMENT_BRIDGE_COMPLETEDCrypto payout complete
payout.failedPAYMENT_BRIDGE_FAILEDCrypto payout failed

Payload Shape Migration

Previous payload path (v0)Current payload path (v1)
data.session.iddata.order.id (and data.payment.orderId when payment is present)
data.session.statusdata.order.status and data.payment.status
data.order.paymentPlatformdata.payment.rail
data.order.fiatCurrencydata.payment.currency
data.order.fulfillTxdata.payment.fulfillTransaction
data.order.errorCode / data.order.errorMessageNo direct payload field in v1 (use PAYMENT_FAILED / PAYMENT_EXPIRED and data.payment.status as failure signals)
Relay payout info on order/session objectsdata.paymentBridge on PAYMENT_BRIDGE_* events
[
"PAYMENT_SETTLED",
"PAYMENT_FAILED",
"PAYMENT_EXPIRED",
"ORDER_CREATED",
"ORDER_FULFILLED",
"ORDER_CANCELLED",
"PAYMENT_CREATED",
"PAYMENT_CANCELLED",
"PAYMENT_BRIDGE_PENDING",
"PAYMENT_BRIDGE_SUBMITTED",
"PAYMENT_BRIDGE_COMPLETED",
"PAYMENT_BRIDGE_FAILED"
]

For merchant order state transitions, treat PAYMENT_SETTLED, PAYMENT_FAILED, PAYMENT_EXPIRED, and ORDER_FULFILLED as the final-state event set.

Migration Checklist

  1. Replace createCheckoutSession with createCheckout.
  2. Replace createSessionAndRedirect with createCheckoutAndRedirect.
  3. Update getMerchant calls to getMerchant(opts).
  4. Rename request fields: amountUsdc -> requestedUsdcAmount, recipientAddress -> destinationAddress, metadata -> notes, enabledPaymentPlatforms -> enabledRails.
  5. Update create-order payload builders to use XOR amount mode (requestedUsdcAmount OR requestedFiatAmount + requestedFiatCurrency).
  6. Update webhook subscriptions from dotted v0 names to uppercase v1 event names.
  7. Update webhook handlers to use data.order, data.payment, and data.paymentBridge.
  8. Verify one happy-path payment (PAYMENT_SETTLED + ORDER_FULFILLED), one failed/expired path, and one bridge payout path (PAYMENT_BRIDGE_*).

Additional v1 Integrator Features

  • For iframe-based checkout, use SDK embedded helpers from @zkp2p/pay-sdk/embedded plus parent-window checkout.success / checkout.failed events.
  • For crypto payout tracking, subscribe to bridge lifecycle webhooks: PAYMENT_BRIDGE_PENDING, PAYMENT_BRIDGE_SUBMITTED, PAYMENT_BRIDGE_COMPLETED, PAYMENT_BRIDGE_FAILED.