This endpoint uses a three-phase flow: prepare, authorize, status. Each phase requires a separate POST request.
curl -X POST https://api.payonproof.com/api/execute-transfer \
-H "Content-Type: application/json" \
-d '{
"phase": "prepare",
"route": {
"id": "route_abc123",
"originAnchor": {"id": "anchor_us_1"},
"destinationAnchor": {"id": "anchor_ph_1"},
"originCurrency": "USD",
"destinationCurrency": "PHP",
"available": true
},
"amount": 100,
"senderAccount": "GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}'
POST /api/execute-transfer
Executes cross-border transfers using Stellar anchors via SEP-10 authentication and SEP-24 interactive flows.
Three-phase execution flow
- prepare: Generate SEP-10 challenges for both anchors
- authorize: Exchange signed challenges for JWTs, start SEP-24 interactive flows
- status: Poll transaction status without exposing anchor JWTs to frontend
Phase 1: Prepare
Generates SEP-10 authentication challenges for the selected route’s origin and destination anchors.
Request body (prepare)
Route object from /api/compare-routes
Destination currency code
Transfer amount in origin currency (must be > 0)
Stellar public key (G…) of sender
Response (prepare)
Client domain used for SEP-10
Unique transaction ID (e.g., “POP-1234567890-ABC123”)
Array of anchor auth objects (origin and destination)
“origin” or “destination”
Asset code (e.g., “USD”, “USDC”)
Asset issuer public key (if applicable)
SEP-10 challenge XDR (sign this!)
Stellar network passphrase
Example response (prepare)
{
"status": "needs_signature",
"meta": {
"clientDomain": "app.payonproof.com"
},
"prepared": {
"transactionId": "POP-1709467200-A3F9B2",
"routeId": "route_abc123",
"senderAccount": "GXXXXXXXXXXXXXXX",
"amount": 100,
"createdAt": "2026-03-03T10:00:00.000Z",
"anchors": [
{
"role": "origin",
"anchorId": "anchor_us_1",
"anchorName": "MoneyGram",
"domain": "stellar.moneygram.com",
"assetCode": "USDC",
"assetIssuer": "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
"amount": 100,
"account": "GXXXXXXXXXXXXXXX",
"webAuthEndpoint": "https://stellar.moneygram.com/auth",
"transferServerSep24": "https://stellar.moneygram.com/sep24",
"challengeXdr": "AAAAAgAAAAC...",
"networkPassphrase": "Public Global Stellar Network ; September 2015"
},
{
"role": "destination",
"anchorId": "anchor_ph_1",
"anchorName": "Philippines Anchor",
"domain": "anchor.example.ph",
"assetCode": "PHP",
"amount": 100,
"account": "GXXXXXXXXXXXXXXX",
"webAuthEndpoint": "https://anchor.example.ph/auth",
"transferServerSep24": "https://anchor.example.ph/sep24",
"challengeXdr": "AAAAAgAAAAD...",
"networkPassphrase": "Public Global Stellar Network ; September 2015"
}
]
}
}
Phase 2: Authorize
Exchanges signed SEP-10 challenges for JWT tokens and initiates SEP-24 interactive flows.
Request body (authorize)
The entire prepared object from the prepare phase response
Signed challenge XDRs for each anchor role
Signed challenge XDR for origin anchor
Signed challenge XDR for destination anchor
Response (authorize)
Encrypted status reference (save this!)
Webhook URL for anchor callbacks
Environment (“staging” or “production”)
Interactive flow URL (open in browser/iframe)
Same structure as originDeposit
Example response (authorize)
{
"status": "processing",
"transaction": {
"id": "POP-1709467200-A3F9B2",
"routeId": "route_abc123",
"amount": 100,
"status": "processing",
"createdAt": "2026-03-03T10:00:00.000Z",
"senderAccount": "GXXXXXXXXXXXXXXX",
"statusRef": "aGVsbG8ud29ybGQ.dGFn.ZW5jcnlwdGVk",
"callbackUrl": "https://api.payonproof.com/api/anchors/sep24/callback?transactionId=POP-1709467200-A3F9B2&callbackToken=abc123&secret=...",
"popEnv": "production",
"anchorFlows": {
"originDeposit": {
"id": "mg_dep_12345",
"url": "https://stellar.moneygram.com/sep24/interactive?token=...",
"type": "interactive_customer_info_needed",
"anchorName": "MoneyGram"
},
"destinationWithdraw": {
"id": "ph_wd_67890",
"url": "https://anchor.example.ph/sep24/interactive?token=...",
"type": "interactive_customer_info_needed",
"anchorName": "Philippines Anchor"
}
}
}
}
Phase 3: Status
Polls transaction status from both anchors without exposing JWTs to the frontend.
Request body (status)
Transaction ID from authorize phase
Encrypted status reference from authorize phase
Response (status)
Stellar transaction hash (if available)
Whether transaction is complete
“callback” if from anchor callback, otherwise from polling
Per-anchor status results
”origin” or “destination”
Whether status fetch succeeded
Transaction status (e.g., “pending_user_transfer_start”, “completed”)
Stellar transaction hash (if available)
Error message if ok=false
Example response (status)
{
"status": "ok",
"transactionId": "POP-1709467200-A3F9B2",
"stellarTxHash": "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889",
"completed": true,
"source": "polling",
"anchors": [
{
"role": "origin",
"anchorName": "MoneyGram",
"interactiveId": "mg_dep_12345",
"ok": true,
"status": "completed",
"stellarTxHash": "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889",
"externalTransactionId": "MG123456789"
},
{
"role": "destination",
"anchorName": "Philippines Anchor",
"interactiveId": "ph_wd_67890",
"ok": true,
"status": "completed"
}
]
}
Error responses
400 Bad Request - Invalid phase
{
"error": "Invalid phase. Use 'prepare', 'authorize', or 'status'."
}
400 Bad Request - Route not operational
{
"error": "Selected route is not operational. Choose an available route (anchors with valid SEP-10/SEP-24)."
}
400 Bad Request - Missing client domain
{
"error": "Unable to resolve client_domain for SEP-10. Set SEP10_CLIENT_DOMAIN in API env."
}
502 Bad Gateway - Anchor service failure
{
"error": "SEP-10 challenge failed at https://anchor.example.com/auth (404): Not Found"
}
Implementation notes
Security features
- Status polling state is encrypted using
EXECUTION_STATE_SECRET
- Anchor JWTs never exposed to frontend
- Client domain signatures handled server-side
- SEP-24 callbacks authenticated via
ANCHOR_CALLBACK_SECRET
MoneyGram-specific behavior
- Requires
MONEYGRAM_USER_ID memo for identification
- Uses special USDC issuer:
GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN
- Automatically routes to preview/ext environments based on
MONEYGRAM_USE_PREVIEW and POP_ENV
SEP-10 challenge caching
- Challenges cached for 30 seconds to avoid duplicate requests
- Multiple fallback strategies for challenge parameters (memo, home_domain, client_domain)
Asset resolution
- Automatically resolves asset codes from SEP-24 /info endpoint
- Falls back to first enabled asset if requested asset not found
- Prefers assets with issuer over fiat-like codes