Skip to main content

Base URL

EnvironmentBase URL
Productionhttps://api.pay.grain.inc
Sandboxhttps://api.sandbox.pay.grain.inc

Payment Sessions

Create Payment Session

POST /payment-sessions
Create a new payment session. Returns a session ID and token for the client-side SDK. Headers:
HeaderValue
AuthorizationBearer {CUBEPAY_API_KEY}
Content-Typeapplication/json
Request Body:
ParameterTypeRequiredDescription
amountstringYesPayment amount as a decimal string (e.g., "50.00")
currencystringYesCurrency code (e.g., "USD")
requestIdstringNoIdempotency key — your own UUID to prevent duplicate sessions
Example:
curl -X POST https://api.pay.grain.inc/payment-sessions \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"amount": "50.00", "currency": "USD", "requestId": "ord_12345"}'
Response 200 OK:
{
  "paymentSessionId": "ps_abc123def456",
  "paymentSessionToken": "eyJhbGciOiJIUzI1NiIs...",
  "amount": "50.00",
  "currency": "USD",
  "network": "ETHEREUM",
  "tokenSymbol": "USDC",
  "oneTimeWalletAddress": "0x1234...abcd",
  "userAddress": null,
  "fundingTransactionHash": null,
  "status": "PENDING",
  "createdAt": "2026-03-20T12:00:00Z"
}

Get Payment Session

GET /payment-sessions/{paymentSessionId}
Retrieve the current state of a payment session. Headers:
HeaderValue
AuthorizationBearer {paymentSessionToken}
Example:
curl https://api.pay.grain.inc/payment-sessions/ps_abc123def456 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Response 200 OK:
{
  "paymentSessionId": "ps_abc123def456",
  "status": "FUNDED",
  "amount": "50.00",
  "currency": "USD",
  "network": "ETHEREUM",
  "tokenSymbol": "USDC",
  "userAddress": "0xCustomerWallet...",
  "oneTimeWalletAddress": "0xOTW...",
  "fundingTransactionHash": "0xabc123...",
  "userSubmittedTransactionHash": "0xdef456...",
  "createdAt": "2026-03-20T12:00:00Z"
}

Captures

Create Capture

POST /api/v1/payment-sessions/{paymentSessionId}/captures
Transfer funds from the one-time wallet (OTW) to your treasury wallet. Supports partial and final captures. Only available when the session status is FUNDED. Headers:
HeaderValue
AuthorizationBearer {CUBEPAY_API_KEY}
Content-Typeapplication/json
Request Body:
ParameterTypeRequiredDescription
requestIdstringYesIdempotency key to prevent duplicate captures
captureAmountstringYesAmount to capture (e.g., "50.00")
isFinalCapturebooleanNoDefault false. When true, remaining balance is refunded to the customer and session moves to SUCCEEDED
Example:
curl -X POST https://api.pay.grain.inc/api/v1/payment-sessions/ps_abc123def456/captures \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"requestId": "cap_ord_12345", "captureAmount": "50.00", "isFinalCapture": true}'
Response 202 Accepted:
{
  "captureId": "cap_xyz789",
  "captureAmount": "50.00",
  "refundAmount": "0.00",
  "status": "CAPTURING"
}

Get Capture

GET /api/v1/payment-sessions/{paymentSessionId}/captures/{captureId}
Check the status of a capture operation. Headers:
HeaderValue
AuthorizationBearer {CUBEPAY_API_KEY}
Example:
curl https://api.pay.grain.inc/api/v1/payment-sessions/ps_abc123def456/captures/cap_xyz789 \
  -H "Authorization: Bearer your-api-key"
Response 200 OK:
{
  "captureId": "cap_xyz789",
  "status": "CAPTURED",
  "captureAmount": "50.00",
  "refundAmount": "0.00",
  "captureTransferTransactionHash": "0xcapture123...",
  "refundTransferTransactionHash": null
}

Capture Object

FieldTypeDescription
captureIdstringUnique capture identifier
statusstringCAPTURING (in progress) or CAPTURED (complete)
captureAmountstringAmount captured
refundAmountstringAmount refunded to customer (on final capture)
captureTransferTransactionHashstring | nullOn-chain hash of the capture transfer
refundTransferTransactionHashstring | nullOn-chain hash of the refund transfer (if applicable)

Webhooks

Payment Status Update

POST {your-webhook-url}
Grain sends payment status updates to your registered webhook URL as JSON-RPC 2.0 requests. Payload:
{
  "jsonrpc": "2.0",
  "id": "1770947403693",
  "method": "cubepay_paymentStatusUpdate",
  "params": [
    {
      "merchantId": "your-merchant-id",
      "paymentSessionId": "ps_abc123def456",
      "status": "FUNDED",
      "updatedAt": "2026-03-20T12:05:00Z"
    }
  ]
}
Status Values:
StatusDescription
CREATEDSession created, customer has not connected a wallet yet
PENDINGWallet connected, awaiting funding transaction
FUNDEDFunds received at the one-time wallet — ready to capture
CAPTURINGCapture in progress (funds being transferred)
SUCCEEDEDFinal capture complete — funds settled to your treasury
CANCELEDSession expired or was cancelled (not funded within 24 hours)
ERRORAn error occurred during processing
Expected Response: Return 200 with a JSON-RPC acknowledgment:
{
  "jsonrpc": "2.0",
  "result": "ok"
}

Response Fields Reference

Payment Session Object

FieldTypeDescription
paymentSessionIdstringUnique session identifier
paymentSessionTokenstringShort-lived token for client-side operations
amountstringPayment amount
currencystringCurrency code
networkstringBlockchain network (e.g., ETHEREUM, SEPOLIA)
tokenSymbolstringToken used for payment (e.g., USDC)
oneTimeWalletAddressstringUnique receiving address for this session
userAddressstring | nullCustomer’s wallet address (populated after connection)
fundingTransactionHashstring | nullTransaction hash of the funding transfer
userSubmittedTransactionHashstring | nullTransaction hash as submitted by the user’s wallet
capturableAmountstringRemaining balance available for capture
capturedAmountstringTotal amount captured so far
capturesarrayArray of capture operations with their statuses and transaction hashes
statusstringCurrent session status
createdAtstringISO 8601 creation timestamp
All endpoints require authentication. See Error Codes for error response formats.