curl -X POST https://api.payonproof.com/api/generate-proof \
-H "Content-Type: application/json" \
-d '{
"transactionId": "POP-1709467200-A3F9B2",
"stellarTxHash": "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889",
"route": "MoneyGram → Philippines Anchor",
"originAmount": 100,
"originCurrency": "USD",
"destinationAmount": 5450,
"destinationCurrency": "PHP",
"exchangeRate": 54.5,
"totalFees": 2.5
}'
POST /api/generate-proof
Generates a cryptographic proof of payment after verifying the transaction exists on the Stellar blockchain via Horizon.
This endpoint:
- Verifies the transaction exists on Horizon
- Generates a proof payload with transaction metadata
- Returns a verifiable proof object
Request body
PayOnProof transaction ID (e.g., “POP-1709467200-A3F9B2”)
Stellar transaction hash (64-character hex string)
Human-readable route description (e.g., “MoneyGram → Philippines Anchor”)
Amount sent in origin currency
Origin currency code (e.g., “USD”)
Amount received in destination currency
Destination currency code (e.g., “PHP”)
Exchange rate applied (destination/origin)
Total fees charged in origin currency
Response
Proof of payment object
Unique proof ID (e.g., “POP-PROOF-1709467200”)
PayOnProof transaction ID
ISO 8601 timestamp when proof was generated
Sender description (“Wallet Holder”)
Receiver description (“Anchor Settlement”)
“verified” after Horizon verification
StellarExpert URL for blockchain verification
Response example
{
"proof": {
"id": "POP-PROOF-1709467200",
"transactionId": "POP-1709467200-A3F9B2",
"timestamp": "2026-03-03T10:15:00.000Z",
"sender": "Wallet Holder",
"receiver": "Anchor Settlement",
"originAmount": 100,
"originCurrency": "USD",
"destinationAmount": 5450,
"destinationCurrency": "PHP",
"exchangeRate": 54.5,
"totalFees": 2.5,
"route": "MoneyGram → Philippines Anchor",
"stellarTxHash": "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889",
"status": "verified",
"verificationUrl": "https://stellar.expert/explorer/public/tx/3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889"
}
}
Error responses
400 Bad Request - Missing field
{
"error": "Missing field: stellarTxHash"
}
405 Method Not Allowed
{
"error": "Method not allowed"
}
502 Bad Gateway - Horizon verification failed
{
"error": "Transaction not found on Horizon (404): {\"type\":\"https://stellar.org/horizon-errors/not_found\",\"title\":\"Resource Missing\"}"
}
502 Bad Gateway - Network error
{
"error": "Horizon request failed (https://horizon.stellar.org/transactions/...): fetch failed"
}
Verification process
The endpoint verifies transactions by:
- Querying Horizon:
GET https://horizon.stellar.org/transactions/{hash}
- Checking response: Must return 200 OK
- Generating proof: Creates proof payload with verified data
Horizon verification example
curl https://horizon.stellar.org/transactions/3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889
If transaction exists:
{
"id": "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889",
"successful": true,
"ledger": 12345678,
...
}
Use cases
Generate proof after transfer completion
// After status polling shows completed=true
const statusResponse = await fetch('/api/execute-transfer', {
method: 'POST',
body: JSON.stringify({
phase: 'status',
transactionId,
statusRef
})
});
const { stellarTxHash, completed } = await statusResponse.json();
if (completed && stellarTxHash) {
const proofResponse = await fetch('/api/generate-proof', {
method: 'POST',
body: JSON.stringify({
transactionId,
stellarTxHash,
originAmount: 100,
originCurrency: 'USD',
destinationAmount: 5450,
destinationCurrency: 'PHP',
exchangeRate: 54.5,
totalFees: 2.5,
route: 'MoneyGram → Philippines Anchor'
})
});
const { proof } = await proofResponse.json();
console.log('Proof generated:', proof.id);
console.log('Verify at:', proof.verificationUrl);
}
Display proof certificate
function ProofCertificate({ proof }) {
return (
<div className="proof-certificate">
<h2>Payment Verified</h2>
<p>Proof ID: {proof.id}</p>
<p>Amount: {proof.originAmount} {proof.originCurrency} → {proof.destinationAmount} {proof.destinationCurrency}</p>
<p>Exchange Rate: {proof.exchangeRate}</p>
<p>Fees: {proof.totalFees} {proof.originCurrency}</p>
<p>Status: {proof.status}</p>
<a href={proof.verificationUrl} target="_blank">Verify on Blockchain</a>
</div>
);
}
Implementation notes
- Proof generation requires successful Horizon verification
- Transaction hash must be valid 64-character hex string
- Optional fields default to sensible values (0, “USDC”, etc.)
- Verification URL points to StellarExpert for easy blockchain verification
- Horizon timeout is 5 seconds (inherited from internal config)