Credit Purchase Integration: USDC Settled Directly to a Solana Contract
This page is for advanced / cryptocurrency-native companies. If that’s not you, head back to the Quickstart for the standard flows.
Setup
Complete account setup first
This integration assumes you’ve completed the Account Setup prerequisites — sandbox merchant account, API key, team access, and any product-specific configuration (settlement location, chargeback protection, or wallet funding).
Developer Resources
Quick Links:
- How does settlement to Solana Contract work
- Testing Card Numbers to use on Sandbox
- Listening to checkout webhooks
- Customize the UI to match your company branding guidelines if using Coinflow’s SDK or Checkout link
Authorization Headers:
Authorization— Your API key from the merchant dashboard.x-coinflow-auth-user-id— A unique customer ID from your own systems identifying the payer or payee.x-coinflow-auth-session-key— A JWT that authorizes the payer. Valid for 24 hours; refresh after expiry.
Checkout Link Implementation
-
Share payer events with Coinflow
Sharing major events that a payer makes throughout their lifecycle on your website prior to them making a purchase will allow us to collect more information about them and improve your approval rates.curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignUp", "customerId": "user-123-abc", "country": "US", "username": "therock72", "email": "dwaynejohnson@gmail.com", "firstName": "Dwayne", "lastName": "Johnson" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOU_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignIn", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignInFailure", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com", "failureReason": "Password Failed" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "BuyerChallenge", "type": "thirdPartyKyc", "status": "successfullyFulfilled", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com" } ' -
Get a checkout link
This endpoint will generate a link which you can embed in an iframe or redirect users directly to.curl --request POST \ --url https://api-sandbox.coinflow.cash/api/checkout/link \ --header 'Authorization: YOUR_API_KEY' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'x-coinflow-auth-blockchain: solana' \ --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt' \ --data ' { "webhookInfo": { "example": "{\"depositId\": \"123-abc-456\"}" }, // Add any webhook info you want to receive here "subtotal": { "currency": "USD", "cents": 100 }, "settlementType": "Credits", "email": "user@gmail.com", // the purchasers email address "blockchain": "solana", "chargebackProtectionData": [ { "productType": "", // Get this value from Coinflow after completing chargeback protection questionnaire "rawProductData": { "example": "{\"description\": \"something about the purchase\"}" }, // Pass as much descriptive data detailing the purchase. "productName": "Product Name", "quantity": 1 } ], "deviceId": "123456789", // Get this from: /guides/checkout/payment-security-risk-management/fraud-protection/implement-chargeback-protection#how-to-add-chargeback-protection "supportEmail": "support@mycompany.com" } '{"link":"https://sandbox.coinflow.cash/solana/purchase-v2/testtest?sessionKey=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzE5MDQsImV4cCI6MTczNzc1ODMwNH0.zpCD3yH6eeEQHfDHzj2lLeD4-irLz61bgcwcp0gTi_Y¢s=100¤cy=USD&customerInfo=N4IgdghgtgpiBcIAiB3CBPMMAEApA9gBZgDO%2BYIANCAG4wBOAlgGaMDGEALo%2BQJIAmCECU5MADjAC0dJqw7dykxv0kBGAEwBmACwBWKiH6MSYgDYYActDiJOhBvjYBrAOzqDEfv3owSJIQAcutgAotgA6hDODAZsjJzoQgDChOwQAOb4BiJcNiC8ADIGAF6MYkIAbAAM1aqx%2BACuYKKJiACqAMoGZUIamgB0fYNaw5oG5pxC2qr9AQEuAeNg6YEu-RXqutogAL5AA&email=user%40gmail.com&jwtToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoi456C4oKW26LXguCngOaMgeGgleiEg-OAh8iO7IGm0IXjj4DYvOeCqO6XkNOG6ZGy5IC246Oh4pCA5qGE4oC70ILngInugIHsgIvqhJpEyJroupPQgualse2HpOyegOCspkzko6Hih4Dhhp_mtaLokLTqi47ohLbomInuvqXmoZ3hjKTuobPimpjmmqHokofriJDqiKHjgpHjiavmoarWhOKHguGEoe6ImOqDkOKCouGDoeOKpeKGkuGnoeyCouaDouqXg-ShqeKImOatieKJlOmEouaImuqjk-aulO2DouOksuGlu-qoklx1ZGE2MOqGuOaqqeKDkumQoOmOoOakqOatqeuLteODkeOJo-Smq-OJhOGFuuGOmuWZo-qhqO2Okdeg66ib7Zmq76iZ4aK77pSh4oGG5oKQ5rOg5qGp6YKi676j6ZKi4aKR4qmp7ISz6L2I7oqH4qaY5K-h5IyK7qOw7Yif4KyD4qGi4aKU5KCv5Ii96LeA5pGh7JSW6JGp45KX6r6C7YSg5YmV55CK4Yii7IWL6oO07pCw6q2HzYHimrTko4fioazlvYfkmIftlbzjoanjmofcgeyCkO6DpOO2k-GzhOybkei2jOC1iuSIg-SegeSMqe6YpOGote2el-6couOCkOGouOC0ieaTgeaOoeuEg-SCjeGFpueWsuGGvOqNseiIkO6pi-aNqO-UseamluWLmuGHheOGteW5t-KAr-C4quGQoumHmuSwo-WPruiCl-2JieyVuei0vuGGo-Cki-OApOyduuiEjOmJo-SnheGnp-u5kuKKh-2eqeyYm-a0oeGMgemLi-e0sO-pg-KiqeS2p-eio-CzmuWFrumSluSEr-SOpu-hgeW4ku2Ml-Ojq8WX4pmn5IKA7J6N5LGI55Wt4rmB5YmA7YOh7qyK76uC7YGY5Imk56Gu45Gl56-e7ria7IqE76mG4YKV5IKm7Y-15oej5pGY6Liq67GG6Y-m446k4KSE5KiV4L2I5rCy7r2p4by74KOx6ri05JC85ouj5KCp4KSH7Yma66qP4pWT5omR6LiF5aKw5KSJ4pCy5aGh4YuJ6aOE76iR3ILmgIbiu4_jiozkirHoiYDlgo7hraPmh6DhhIPusLPkoaPjga7qgornqJrgsLHvqZXisq7ro6DqlqXik7Dmm6fio4DsgYpcdWQ4YWXqp4flo7noqo3nj6rupqfhhqLho6vokpXjroHvnLjivpjho7Lrpovui7TqvL_ogaLloYjqi43qhKjstJfsjovti7PojITpr6jhmL0w6YOa45qH5IiK7La46q2E7qmjyIDljJTriZfor6LRruG2nuGkpOGQtu68huGru-Cyn-Snuuy8suChg-ipsuqYi-uEsOOYheiHo-qDs-qshumlpOKEsuS-ouqAguqOqOiDjuegleSNg-GQkuOOiO2FoOCsm-ifkO6roeq7i-iGlFx1ZGUzZOmzs--psMOA666Y5paL4KKB4LuR5IiE7Iiu4YqE6p2J47C04oSM5Yia4aC35JqD6Km64bOP7ZOi6ryG5JG47ZG05oiC6Imo5KGGXHVkY2Mw5YKM46Gj7Ka15pSO6K2k66Ko4LeB74eK4paz5oKQ5KmF55OG6YeQ47ik4ZOR44u-4Yiu2LrgvpvlvoHqkYTnsYLsipbssLfkmYPnsKrrpI3miKDskIDqqZnosovrvKfrh7zvsrzuroLhs4bjtobgspDptp7kgZDrgrrpk6TohqTosLronZDvlZDmqZXlrbLjqJTitbfho7TjiIbkh6DQnMiAwr7kgIAiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpZGVtcG90ZW5jeUtleSI6IklLYmNhNjg5OWUtNTY0NS00MTQ2LWIyMzUtNDdiMjNmMjlkY2QzIiwic3VidG90YWwiOnsiY3VycmVuY3kiOiJVU0QiLCJjZW50cyI6MTAwfSwiaWF0IjoxNzM3NjcxOTA0LCJleHAiOjE3Mzc3NTgzMDR9.GP4zCoLBpw8hKiLrU-0WZtxMh_6GPJYvICUjsw-QQjw"} -
Submit a purchase through the provided link and go to the merchant dashboard to see the purchase record.
📘 At this point, the purchase for credits is complete, and the payer has credits in their wallet.
After the user has credits, they can use their credits for use at anytime.
-
curl --request POST \ --url https://api-sandbox.coinflow.cash/api/redeem \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'x-coinflow-auth-blockchain: solana' \ --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt' \ --data ' { "subtotal": { "currency": "USD", "cents": 100 }, "merchantId": "YOUR_MERCHANT_ID", // replace with your merchant id "transaction": "GLeC6hHyQoBUhGbVe6x6XHJKdXFeJauEqP8XfVpqz4eN16VZmFnDeHundU6JndUDpADijtuEycFhSzkr9wfBXacQwK6ZzEWM1RvddNKE4JTRgyV8zs5cLd37kT9yzc554F6Um293UDjEYJmygb21x3iSH5qszjdZvRvHZJ95bfkvU8MDWx9YAihG7BaC8JfK3YBvZ6uJD2damLJRRhy4XTDmsToMxnCsR6rKEtk2E88yTuPHXATzXyKeXUJZ6D53rBTF9yJy1rwNgHhXUn9kshU77dVt7TaS8orrBpujgAKpxnhMfjWi2rWGQhUvGLLYbn9ny42YxWXuXMKUstDt8wKCxNGH6u1Re7yspnpCbRXavvFSgzF7MveJvN7maA7q8cNw7Zq1x9nBFMQKp23Ra1VrXD1oziUC7JZVkU4HCw8eDsEKJy9udRofzopvnFzd1cqEseJF945YDAfAY4hjUcN5syZZg5EsSk1yBXa2nJaDhEwBn8zxQ8p7GEn5TVj8iVSYnfwr4534eSd1z1gunYdANtewVZFgUCRanXTTsNJucFu5HWTTYci2urT3G2fR3UmoNm5cK", // This should be a base58 encoded tx "chargebackProtectionData": [ { "productType": "", //Get this from completing chargeback questionnaire "productName": "product name", "quantity": 1, "rawProductData": { "example": "{\"description\": \"something about the purchase\"}" }, // Pass as much descriptive data detailing the purchase. "productName": "Product Name", "quantity": 1 } } ] } '{ "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEdnssu5ihuBbYXnay6AysBCyiQBbo1rHkC7sqKn56zgoLmFDTAcK6f9UyX4cReT2c671UzhdG4Wa6jZh2BYCMu78nSesoeMSS9XQ6jXvRyA2fs1wRiMwRCaCEe8StVHmQVvwpof6Tv9WoTcQAAn4nYWqNMgBHLnpk5KAEj6QtBcub6fBW9hRsHDj6bW1XdhuokCVyoayg9KywYjva7cbPLJRZM9aNywUv41og9Jr1pvV6qqCcehXJ4kyFEuayAqhn1Zku4oFaoMrKe3uydjbpy2Pu1nv4wz4JQHa7yeaNWcQysKdEKsqi5dJSkGkaoRBKdM3nhCdTRLAvik4AZYSeBDP5unqd73aRekzX9Z7PmfzTC7FVTWLqtJA3Z3dze2QqHr7yLvgvZAhtPZgjXhW9U4YmLFsBwAfFy4T1GZUwBQirfmwYAhV9pBxnqLLHvfGTizmZLU22EGVrFAz6RDD4mogcUgxjFa56irwL3v5dd6BrpwZcwCDf35ad5AeeKx2JSJ5XmbKr7xmDATMFMqfGPu37mCwo8t6MUsdoqYFTAUhy6gvp4XKwouLMpQU4UnykXubFnUHkYZBkR9yurSExM835A6mtk1ufcVpYc1bc148ciM5w1ZPpC7W1M28u17jaECCnGSERfNettZNmkrQCK8rJ42bSqYa7dnnfnyFer7Exv8mFcFmFs4Br9k568wUHyUvQMrT4WTaY1EiQtc6WmWzHvmUxgc2ppNKRNXa7YFxQfNYbP4diA3s26cKymTqmGmuR8pEPoV5aabm8dmAtZhmVNuoF8S3M7WUVnMuWToFa8quKM4uVPgg4xWShnFdjv4MmsAbPpFcbfTeMDMfRXKAQLw2C6q2dgoJredwaG843HEgAjVmTN1H2Evnezc3cMXFuJUWdSwL22AEUsZJJwS6jNTLmGZBbgtPJVn3Wg4PGtJTky2uxWx3uL1B6AJxYEfh" } -
Have the user wallet sign and send the transaction. Below is an example of how you can sign it. You may use Coinflow’s endpoint to then send the transaction to the solana blockchain.
const { Connection, Keypair, VersionedTransaction } = require('@solana/web3.js'); const bs58 = require('bs58'); const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const privateKeyString = 'YOUR_BASE58_PRIVATE_KEY'; const privateKey = bs58.decode(privateKeyString); const keypair = Keypair.fromSecretKey(privateKey); const base58Transaction = 'REPLACE_WITH_REDEEM_TX'; //replace with tx returned from step 3 // return a signed tx async function signTransaction() { try { const decodedTransactionBytes = bs58.decode(base58Transaction); const versionedTransaction = VersionedTransaction.deserialize(decodedTransactionBytes); versionedTransaction.sign([keypair]); // wallet signs tx const serializedTransaction = versionedTransaction.serialize(); const base58SignedTransaction = bs58.encode(serializedTransaction); // encode signed tx to base58 console.log(signed tx:', signedTransaction); return base58SignedTransaction; // This is what youll send to the blockchain } catch (err) { console.error('Error signing the transaction:', err); } }curl --request POST \ --url https://api-sandbox.coinflow.cash/api/utils/send-coinflow-tx \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "merchantId": "testtest", "signedTransaction": "5gkDhvbf4ntXpmmN5pWqBRMLumB7z9En6tfgS19sdDZaXKzEMPRoP7DYZ1bMvqwS9xTQnw6AsR8ucnEtx35zqBryNmCKjWYGf1VW8WpeXYuqHhYHdWgEPxxXXY4iqNhexrodYWeyH2eXpAwNPFKo1wfLkVJsxARhdYu9o9HJU1Ba6x4ZZWmWoLFRL3yWZ2H1GytsubAmj7fzArjGuoSCUkHNzsSZpvAFux7Mstie5JuzvzGJqGc9tVTcUjrCmjkij8mdbN4rP3C6VFwyxDRt64DCJvc4A3epX8YhqW84wj7WXuxQVWcyjRHmyuaD4nhaHeyFMWYCjTo8ZywcoZJ3n7dvrzqQTXTSY2V2UmkApBE5Qkni2WiekTfjryQBKLUDFFAcHtZXE1gy1X4wCFgvbyi8USVAhqTH8Y86h62nhjVEcXqLxbwm48F7Fqq8QLtoBNg3j7BRLEdwXvjK7y6f7WF1iSnL2Q4b4fwVUwU37UZchBPKt1GcRw1pF2ohwZ9krK4dbfjUpa2w5HsrBgGfVttBaBUXaSvaxkJQmWwM1bfVtBHXJf8rCBt5uTDfvyPJjtzkZDE3irFQWXiJ2bA9HodZnz4myPM6AWFiCJXVcKjLsmTnYkUvQwZ84nzx7jvPp7ZXLeJ2fa5uMxdnHsSdjwoQeuaHPapDfCoawSSVoTtFMYPjREiaMqckCht7u2LLeedbdMvLsQt5btM8R9uCSFzYbpKQLZEwZ4XMmfxoqdTCagjoEe7Yg3o3XB7KqUJma6LwFJJwG24yprCEveYCrkD8GiqXmphmx2Q4M1Drk1ygKGDqLn246UWt9nxoZusqDSnzruHh7gaE8tgx1iH7z29Bkm6UAqDMLY3BnVgYJxuQkH4PcD2E2yrgrZDJuqQtMxyB2uFLe3eb75mnZjfshL4wYD54BScEmybHxjA2ee1T7ZUv8VJZ53c74wzZ8BdGM4NASnjtcVh5yWWWkURekMXPHFkrxytsoc4PjXwF7NaNaT" } '
React SDK Implementation
- Share payer events with Coinflow
Sharing major events that a payer makes throughout their lifecycle on your website prior to them making a purchase will allow us to collect more information about them and improve your approval rates.curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignUp", "customerId": "user-123-abc", "country": "US", "username": "therock72", "email": "dwaynejohnson@gmail.com", "firstName": "Dwayne", "lastName": "Johnson" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOU_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignIn", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignInFailure", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com", "failureReason": "Password Failed" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "BuyerChallenge", "type": "thirdPartyKyc", "status": "successfullyFulfilled", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com" } ' - Install Coinflow package
npm i @coinflowlabs/react-native - Below is an example of how to implement the
CoinflowPurchasemodal so a user can purchase credits with their payment method.
<CoinflowPurchase
wallet={{
publicKey: new PublicKey('USER_PUBLIC_KEY'),
signMessage: (message: UInt8Array) => Promise,
sendTransaction: (transaction: Transaction | VersionedTransaction) => Promise
}}
connection={connection} // solana rpc connection
blockchain={'solana'}
merchantId={'testtest'} // Replace with your merchant id
env={'sandbox || prod'}
onSuccess={(...args) => {
console.log('Purchase Success', args); // Provide your own function after payment success
}}
subtotal={{currency: Currency.USD,
cents: 100}} // purchase amount in USD
webhookInfo={{
productId: '123abc',
item: 'sword',
}} // Pass additional webhook info youd like to receive
email="user@test.com" // payer's email address
chargebackProtectionData={[
{
productName: "Product Name",
productType: "gameOfSkill", // Get this value from Coinflow after filling out chargeback questionnaire
quantity: 1,
rawProductData: {
productID: "sword12345",
productDescription: "A legendary sword with magical powers.",
productCategory: "Weapon",
weight: "15 lbs",
dimensions: "40 in x 5 in",
origin: "Ancient Kingdom",
craftedBy: "Master Blacksmith",
craftingDate: "2024-06-19",
}, // Customize with as much info you have on the purchase
},
]}
settlementType={SettlementType.Credits}
/>
- Then, when the customer wants to redeem their credits, you can implement the
CoinflowPurchaselike below:<CoinflowPurchase wallet={{ publicKey: new PublicKey('USER_PUBLIC_KEY'), signMessage: (message: UInt8Array) => Promise, sendTransaction: (transaction: Transaction | VersionedTransaction) => Promise }} connection={connection} // solana rpc connection blockchain={'solana'} merchantId={'testtest'} // Replace with your merchant id env={'sandbox || prod'} onSuccess={(...args) => { console.log('Purchase Success', args); // Provide your own function after payment success }} subtotal={{currency: Currency.USD, cents: 100}} // purchase amount in USD webhookInfo={{ productId: '123abc', item: 'sword', }} // Pass additional webhook info youd like to receive email="user@test.com" // payer's email address chargebackProtectionData={[ { productName: "Product Name", productType: "gameOfSkill", // Get this value from Coinflow after filling out chargeback questionnaire quantity: 1, rawProductData: { productID: "sword12345", productDescription: "A legendary sword with magical powers.", productCategory: "Weapon", weight: "15 lbs", dimensions: "40 in x 5 in", origin: "Ancient Kingdom", craftedBy: "Master Blacksmith", craftingDate: "2024-06-19", }, // Customize with as much info you have on the purchase }, ]} settlementType={SettlementType.Credits} transaction={tx} // This should be a base58 encoded tx created by the merchant. // Only pass a transaction when a customer wants to REDEEM their credits, after purchasing. DO NOT pass the tx when a customer is purchasing credits. /> - Add Chargeback protection on EVERY PAGE of your app
- Note: This is required!
API Implementation
-
Share payer events with Coinflow
Sharing major events that a payer makes throughout their lifecycle on your website prior to them making a purchase will allow us to collect more information about them and improve your approval rates.curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignUp", "customerId": "user-123-abc", "country": "US", "username": "therock72", "email": "dwaynejohnson@gmail.com", "firstName": "Dwayne", "lastName": "Johnson" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOU_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignIn", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "SignInFailure", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com", "failureReason": "Password Failed" } 'curl --request POST \ --url https://api-sandbox.coinflow.cash/api/events \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --data ' { "eventType": "BuyerChallenge", "type": "thirdPartyKyc", "status": "successfullyFulfilled", "customerId": "user-123-abc", "country": "US", "email": "dwaynejohnson@gmail.com" } ' -
Generate an API Key from Merchant Dashboard > API Keys > Create.
-
Get a Session Key
This creates a JWT for the payer and must be refreshed every 24 hours.curl --request GET \ --url https://api-sandbox.coinflow.cash/api/auth/session-key \ --header 'Authorization: YOUR_API_KEY' \ --header 'accept: application/json' \ --header 'x-coinflow-auth-blockchain: solana' \ --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt'{ "key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY" }Note: Session keys are valid for 24 hours and must be refreshed upon expiration.
-
Get the Totals for the checkout
This will return the total price inclusive of all fees for the purchase.
curl --location 'https://api-sandbox.coinflow.cash/api/checkout/totals/YOUR_MERCHANT_ID' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY' \
--data '
{
"subtotal": {
"cents": 200
}
}
'
//Response
{
"card": {
"subtotal": {
"cents": 200
},
"creditCardFees": {
"cents": 0
},
"chargebackProtectionFees": {
"cents": 0
},
"gasFees": {
"cents": 0
},
"total": {
"cents": 200
},
"merchantPaidCreditCardFees": {
"cents": 36
},
"merchantPaidGasFees": {
"cents": 0
},
"merchantPaidChargebackProtectionFees": {
"cents": 0
}
},
"ach": {
"subtotal": {
"cents": 200
},
"creditCardFees": {
"cents": 0
},
"chargebackProtectionFees": {
"cents": 0
},
"gasFees": {
"cents": 0
},
"total": {
"cents": 200
},
"merchantPaidCreditCardFees": {
"cents": 100
},
"merchantPaidGasFees": {
"cents": 0
},
"merchantPaidChargebackProtectionFees": {
"cents": 0
}
}
}
- Tokenize the Credit Card Number. See tab:
Tokenize New Card - Enable a New Card Checkout
This endpoint will enable a new user who has never made a purchase to complete their purchase using the tokenized credit card retrieved from Step 4. Below is an example of how you’d call the card checkout endpoint:
curl --location 'https://api-sandbox.coinflow.cash/api/checkout/card/testtest' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY' \
--data-raw '
{
"subtotal": {
"currency": "USD",
"cents": 100
},
"webhookInfo": {
"example": "{\"description\": \"whatever webhooks info you want to receive\"}"
}, // pass whatever webhook info you want to receive
"card": {
"expYear": "29",
"expMonth": "10",
"email": "dwayne@therock.com",
"firstName": "dwayne",
"lastName": "johnson",
"address1": "123 Rock Road",
"city": "Chicago",
"zip": "60606",
"state": "IL",
"country": "US",
"cardToken": "230377JSUM3F0275" // Get this from: /recipes/recipes/pci-compliant-card-tokenization
},
"settlementType": "Credits",
"authentication3DS": {
"colorDepth": 30,
"screenHeight": 1000,
"screenWidth": 2000,
"timeZone": 5
}, // Get this from: /recipes/complete-checkout-with-3ds-challenge
"chargebackProtectionData": [
{
"productType": "inGameProduct", // Get this after completing chargeback protection questionnaire
"rawProductData": {
"example": "{\"description\": \"pass data about the purchase\"}"
},
"productName": "Product Name",
"quantity": 1
}
]
}
'
{"paymentId":"bdc22a87-fb72-4f9d-a445-f26c04c8376c"}
- Re-tokenize a saved card number. See tab:
Refresh Token w/ CVV - Enable a Saved Card Checkout
This endpoint will enable a returning user to complete a purchase with a previously saved card. The returning user will need to enter their CVV before confirming the purchase.
Once you’ve retrieved the refreshed card token, pass it into the Saved Card Checkout endpoint. Below is an example request:
curl --location 'https://api-sandbox.coinflow.cash/api/checkout/token/testtest' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY' \
--header 'x-device-id: 123456789' \
--data '
{
"settlementType": "Credits",
"subtotal": {
"currency": "USD",
"cents": 100
},
"webhookInfo": {
"example": "{\"description\": \"whatever webhooks info you want to receive\"}"
},
"authentication3DS": {
"colorDepth": 30,
"screenHeight": 1000,
"screenWidth": 2000,
"timeZone": 5
},
"chargebackProtectionData": [
{
"productType": "gameOfSkill",
"rawProductData": {
"example": "{\"description\": \"pass data about the purchase\"}"
},
"productName": "Product Name",
"quantity": 1
}
],
"token": "230377JSUM3F0275"
}
'
{"paymentId":"e416a462-33a3-4e80-ab8d-ffa2de666a2b"}
-
curl --request POST \ --url https://api-sandbox.coinflow.cash/api/redeem \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'x-coinflow-auth-blockchain: solana' \ --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt' \ --data ' { "subtotal": { "currency": "USD", "cents": 100 }, "merchantId": "YOUR_MERCHANT_ID", // replace with your merchant id "transaction": "GLeC6hHyQoBUhGbVe6x6XHJKdXFeJauEqP8XfVpqz4eN16VZmFnDeHundU6JndUDpADijtuEycFhSzkr9wfBXacQwK6ZzEWM1RvddNKE4JTRgyV8zs5cLd37kT9yzc554F6Um293UDjEYJmygb21x3iSH5qszjdZvRvHZJ95bfkvU8MDWx9YAihG7BaC8JfK3YBvZ6uJD2damLJRRhy4XTDmsToMxnCsR6rKEtk2E88yTuPHXATzXyKeXUJZ6D53rBTF9yJy1rwNgHhXUn9kshU77dVt7TaS8orrBpujgAKpxnhMfjWi2rWGQhUvGLLYbn9ny42YxWXuXMKUstDt8wKCxNGH6u1Re7yspnpCbRXavvFSgzF7MveJvN7maA7q8cNw7Zq1x9nBFMQKp23Ra1VrXD1oziUC7JZVkU4HCw8eDsEKJy9udRofzopvnFzd1cqEseJF945YDAfAY4hjUcN5syZZg5EsSk1yBXa2nJaDhEwBn8zxQ8p7GEn5TVj8iVSYnfwr4534eSd1z1gunYdANtewVZFgUCRanXTTsNJucFu5HWTTYci2urT3G2fR3UmoNm5cK", // This should be a base58 encoded tx } '{ "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEdnssu5ihuBbYXnay6AysBCyiQBbo1rHkC7sqKn56zgoLmFDTAcK6f9UyX4cReT2c671UzhdG4Wa6jZh2BYCMu78nSesoeMSS9XQ6jXvRyA2fs1wRiMwRCaCEe8StVHmQVvwpof6Tv9WoTcQAAn4nYWqNMgBHLnpk5KAEj6QtBcub6fBW9hRsHDj6bW1XdhuokCVyoayg9KywYjva7cbPLJRZM9aNywUv41og9Jr1pvV6qqCcehXJ4kyFEuayAqhn1Zku4oFaoMrKe3uydjbpy2Pu1nv4wz4JQHa7yeaNWcQysKdEKsqi5dJSkGkaoRBKdM3nhCdTRLAvik4AZYSeBDP5unqd73aRekzX9Z7PmfzTC7FVTWLqtJA3Z3dze2QqHr7yLvgvZAhtPZgjXhW9U4YmLFsBwAfFy4T1GZUwBQirfmwYAhV9pBxnqLLHvfGTizmZLU22EGVrFAz6RDD4mogcUgxjFa56irwL3v5dd6BrpwZcwCDf35ad5AeeKx2JSJ5XmbKr7xmDATMFMqfGPu37mCwo8t6MUsdoqYFTAUhy6gvp4XKwouLMpQU4UnykXubFnUHkYZBkR9yurSExM835A6mtk1ufcVpYc1bc148ciM5w1ZPpC7W1M28u17jaECCnGSERfNettZNmkrQCK8rJ42bSqYa7dnnfnyFer7Exv8mFcFmFs4Br9k568wUHyUvQMrT4WTaY1EiQtc6WmWzHvmUxgc2ppNKRNXa7YFxQfNYbP4diA3s26cKymTqmGmuR8pEPoV5aabm8dmAtZhmVNuoF8S3M7WUVnMuWToFa8quKM4uVPgg4xWShnFdjv4MmsAbPpFcbfTeMDMfRXKAQLw2C6q2dgoJredwaG843HEgAjVmTN1H2Evnezc3cMXFuJUWdSwL22AEUsZJJwS6jNTLmGZBbgtPJVn3Wg4PGtJTky2uxWx3uL1B6AJxYEfh" } -
Have the user wallet sign and send the transaction. Below is an example of how you can sign it. You may use Coinflow’s endpoint to then send the transaction to the solana blockchain.
const { Connection, Keypair, VersionedTransaction } = require('@solana/web3.js'); const bs58 = require('bs58'); const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); const privateKeyString = 'YOUR_BASE58_PRIVATE_KEY'; const privateKey = bs58.decode(privateKeyString); const keypair = Keypair.fromSecretKey(privateKey); const base58Transaction = 'REPLACE_WITH_REDEEM_TX'; //replace with tx returned from step 3 // return a signed tz async function signTransaction() { try { const decodedTransactionBytes = bs58.decode(base58Transaction); const versionedTransaction = VersionedTransaction.deserialize(decodedTransactionBytes); versionedTransaction.sign([keypair]); // wallet signs tx const serializedTransaction = versionedTransaction.serialize(); const base58SignedTransaction = bs58.encode(serializedTransaction); // encode signed tx to base58 console.log(signed tx:', signedTransaction); return base58SignedTransaction; // This is what youll send to the blockchain } catch (err) { console.error('Error signing the transaction:', err); } }curl --request POST \ --url https://api-sandbox.coinflow.cash/api/utils/send-coinflow-tx \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "merchantId": "testtest", "signedTransaction": "5gkDhvbf4ntXpmmN5pWqBRMLumB7z9En6tfgS19sdDZaXKzEMPRoP7DYZ1bMvqwS9xTQnw6AsR8ucnEtx35zqBryNmCKjWYGf1VW8WpeXYuqHhYHdWgEPxxXXY4iqNhexrodYWeyH2eXpAwNPFKo1wfLkVJsxARhdYu9o9HJU1Ba6x4ZZWmWoLFRL3yWZ2H1GytsubAmj7fzArjGuoSCUkHNzsSZpvAFux7Mstie5JuzvzGJqGc9tVTcUjrCmjkij8mdbN4rP3C6VFwyxDRt64DCJvc4A3epX8YhqW84wj7WXuxQVWcyjRHmyuaD4nhaHeyFMWYCjTo8ZywcoZJ3n7dvrzqQTXTSY2V2UmkApBE5Qkni2WiekTfjryQBKLUDFFAcHtZXE1gy1X4wCFgvbyi8USVAhqTH8Y86h62nhjVEcXqLxbwm48F7Fqq8QLtoBNg3j7BRLEdwXvjK7y6f7WF1iSnL2Q4b4fwVUwU37UZchBPKt1GcRw1pF2ohwZ9krK4dbfjUpa2w5HsrBgGfVttBaBUXaSvaxkJQmWwM1bfVtBHXJf8rCBt5uTDfvyPJjtzkZDE3irFQWXiJ2bA9HodZnz4myPM6AWFiCJXVcKjLsmTnYkUvQwZ84nzx7jvPp7ZXLeJ2fa5uMxdnHsSdjwoQeuaHPapDfCoawSSVoTtFMYPjREiaMqckCht7u2LLeedbdMvLsQt5btM8R9uCSFzYbpKQLZEwZ4XMmfxoqdTCagjoEe7Yg3o3XB7KqUJma6LwFJJwG24yprCEveYCrkD8GiqXmphmx2Q4M1Drk1ygKGDqLn246UWt9nxoZusqDSnzruHh7gaE8tgx1iH7z29Bkm6UAqDMLY3BnVgYJxuQkH4PcD2E2yrgrZDJuqQtMxyB2uFLe3eb75mnZjfshL4wYD54BScEmybHxjA2ee1T7ZUv8VJZ53c74wzZ8BdGM4NASnjtcVh5yWWWkURekMXPHFkrxytsoc4PjXwF7NaNaT" } ' -
Add Chargeback protection on EVERY PAGE of your app
- Note: This is required!