Mersi

Checkout

Initiate a Crossmint USDC payment order for a single cart item.

Requires a valid crossmint-jwt cookie and completed onboarding. The user must have an active EVM wallet and a complete shipping address. Rate-limited at 30 req/min per user.

POST /api/checkout

Creates a Crossmint payment order for a single cart item. On success, records the order in the database with status = awaiting_approval and returns details needed for the approval flow.

Auth required: Yes + onboarding complete

Request Body

FieldTypeRequiredDescription
cartItemIdUUIDYesID of the cart item to purchase
{ "cartItemId": "c1d2e3f4-a5b6-7890-cdef-123456789012" }

Response 201 Created

{
  "orderId": "d1e2f3a4-b5c6-7890-defg-234567890123",
  "crossmintOrderId": "ed34a579-7fbc-4509-b8d8-9e61954cd555",
  "phase": "awaiting-approval",
  "serializedTransaction": "0x02f901...",
  "walletAddress": "0xDeAdBeEf00000000000000000000000000000001"
}
FieldTypeDescription
orderIdUUIDInternal order ID for tracking via GET /api/orders/:orderId
crossmintOrderIdstringCrossmint's order reference
phasestringInitial phase from Crossmint (e.g. awaiting-approval)
serializedTransactionstringPre-built EVM transaction for Crossmint wallet approval
walletAddressstringEVM wallet address that must approve the transaction

Errors

StatusCodeCause
400CheckoutNoWalletErrorUser's EVM wallet is not provisioned
400CheckoutMissingAddressErrorShipping address is incomplete
404CartItemNotFoundErrorCart item does not exist or belongs to another user
422InsufficientFundsErrorCrossmint wallet has insufficient USDC
502CheckoutOrderCreationErrorCrossmint API error creating the order
502CheckoutPaymentErrorCrossmint API payment error

curl Example

curl -b cookies.txt -X POST http://localhost:3000/api/checkout \
  -H "Content-Type: application/json" \
  -d '{"cartItemId":"c1d2e3f4-a5b6-7890-cdef-123456789012"}'

Checkout Flow

On-Chain Checkout (CART_SERVICE=onchain)

When the on-chain cart is enabled, payment confirmation triggers a Sui Programmable Transaction Block (PTB) that marks the item as purchased in the Move contract:

  1. Webhook-triggered — When Crossmint fires orders.payment.succeeded or orders.delivery.completed, the backend constructs and submits a PTB calling checkout on the Move contract.
  2. The resulting Sui digest is saved to orders.tx_hash.
  3. This step is non-fatal — if the PTB fails, the order status is still updated but the on-chain state may diverge.

How is this guide?

On this page