> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.coinflow.cash/guides/checkout/implementation-overview/implementation-guides/advanced-use-cases/credit-purchase-usdc-to-solana-contract/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.coinflow.cash/_mcp/server. # Credit Purchase Integration: USDC Settled Directly to a Solana Contract > **Warning** > > **This page is for advanced / cryptocurrency-native companies.** If that's not you, head back to the [Quickstart](/guides/getting-started/quickstart) for the standard flows. ## Setup > **Complete account setup first** > > This integration assumes you've completed the > [Account Setup](/guides/getting-started/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](/guides/checkout/settlement-locations/settlement-to-contracts/settle-to-solana-contract/implement-settlement-to-solana-contract) * [Testing Card Numbers to use on Sandbox](/guides/checkout/testing/testing-credit-cards) * [Listening to checkout webhooks](/guides/developer-resources/webhooks/checkout-webhooks) * [Customize the UI to match your company branding guidelines if using Coinflow's SDK or Checkout link](/guides/developer-resources/custom-branding) **Authorization Headers:** * `Authorization` — Your API key from the [merchant dashboard](https://sandbox-merchant.coinflow.cash/api-keys). * `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 1. [Share payer events with Coinflow](/guides/checkout/payment-security-risk-management/fraud-protection/sending-payer-events)\ 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. **`SignUpEvent`** ```curl SignUpEvent 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" } ' ``` **`SignInEvent`** ```curl SignInEvent 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" } ' ``` **`SignInFailureEvent`** ```curl SignInFailureEvent 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" } ' ``` **`BuyerChallengeEvent`** ```curl BuyerChallengeEvent 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" } ' ``` 2. [Get a checkout link](/api-reference/api-reference/checkout/get-checkout-link)\ This endpoint will generate a link which you can embed in an iframe or redirect users directly to. **`Request`** ```curl Request 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" } ' ``` **`Response`** ```json Response {"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"} ``` 3. 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. 4. [Create a redeem transaction](/api-reference/api-reference/redeem/get-redeem-transaction) **`Request`** ```curl Request 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 } } ] } ' ``` **`Response`** ```json Response { "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEdnssu5ihuBbYXnay6AysBCyiQBbo1rHkC7sqKn56zgoLmFDTAcK6f9UyX4cReT2c671UzhdG4Wa6jZh2BYCMu78nSesoeMSS9XQ6jXvRyA2fs1wRiMwRCaCEe8StVHmQVvwpof6Tv9WoTcQAAn4nYWqNMgBHLnpk5KAEj6QtBcub6fBW9hRsHDj6bW1XdhuokCVyoayg9KywYjva7cbPLJRZM9aNywUv41og9Jr1pvV6qqCcehXJ4kyFEuayAqhn1Zku4oFaoMrKe3uydjbpy2Pu1nv4wz4JQHa7yeaNWcQysKdEKsqi5dJSkGkaoRBKdM3nhCdTRLAvik4AZYSeBDP5unqd73aRekzX9Z7PmfzTC7FVTWLqtJA3Z3dze2QqHr7yLvgvZAhtPZgjXhW9U4YmLFsBwAfFy4T1GZUwBQirfmwYAhV9pBxnqLLHvfGTizmZLU22EGVrFAz6RDD4mogcUgxjFa56irwL3v5dd6BrpwZcwCDf35ad5AeeKx2JSJ5XmbKr7xmDATMFMqfGPu37mCwo8t6MUsdoqYFTAUhy6gvp4XKwouLMpQU4UnykXubFnUHkYZBkR9yurSExM835A6mtk1ufcVpYc1bc148ciM5w1ZPpC7W1M28u17jaECCnGSERfNettZNmkrQCK8rJ42bSqYa7dnnfnyFer7Exv8mFcFmFs4Br9k568wUHyUvQMrT4WTaY1EiQtc6WmWzHvmUxgc2ppNKRNXa7YFxQfNYbP4diA3s26cKymTqmGmuR8pEPoV5aabm8dmAtZhmVNuoF8S3M7WUVnMuWToFa8quKM4uVPgg4xWShnFdjv4MmsAbPpFcbfTeMDMfRXKAQLw2C6q2dgoJredwaG843HEgAjVmTN1H2Evnezc3cMXFuJUWdSwL22AEUsZJJwS6jNTLmGZBbgtPJVn3Wg4PGtJTky2uxWx3uL1B6AJxYEfh" } ``` 5. 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](/api-reference/api-reference/utilities/send-coinflow-transaction). **`Sign Transaction`** ```javascript Sign Transaction 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); } } ``` **`Send Transaction`** ```curl Send Transaction 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 1. [Share payer events with Coinflow](/guides/checkout/payment-security-risk-management/fraud-protection/sending-payer-events)\ 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. **`SignUpEvent`** ```curl SignUpEvent 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" } ' ``` **`SignInEvent`** ```curl SignInEvent 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" } ' ``` **`SignInFailureEvent`** ```curl SignInFailureEvent 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" } ' ``` **`BuyerChallengeEvent`** ```curl BuyerChallengeEvent 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" } ' ``` 2. [Install Coinflow package](https://www.npmjs.com/package/@coinflowlabs/react-native) ``` npm i @coinflowlabs/react-native ``` 3. Below is an example of how to implement the `CoinflowPurchase` modal so a user can purchase credits with their payment method. ```javascript 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} /> ``` 3. Then, when the customer wants to redeem their credits, you can implement the `CoinflowPurchase` like below: ```javascript 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. /> ``` 4. [Add Chargeback protection on EVERY PAGE of your app](/guides/checkout/payment-security-risk-management/fraud-protection/implement-chargeback-protection#how-to-add-chargeback-protection) * Note: This is required! ## API Implementation 1. [Share payer events with Coinflow](/guides/checkout/payment-security-risk-management/fraud-protection/sending-payer-events)\ 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. **`SignUpEvent`** ```curl SignUpEvent 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" } ' ``` **`SignInEvent`** ```curl SignInEvent 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" } ' ``` **`SignInFailureEvent`** ```curl SignInFailureEvent 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" } ' ``` **`BuyerChallengeEvent`** ```curl BuyerChallengeEvent 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" } ' ``` 2. [Generate an API Key](https://sandbox-merchant.coinflow.cash/api-keys) from Merchant Dashboard > API Keys > Create. 3. [Get a Session Key](/api-reference/api-reference/authentication/get-session-key)\ This creates a JWT for the payer and must be refreshed every 24 hours. **`Request`** ```curl Request 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' ``` **`Response`** ```json Response { "key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY" } ``` **Note: Session keys are valid for 24 hours and must be refreshed upon expiration.** 4. [Get the Totals for the checkout](/api-reference/api-reference/checkout/get-totals)\ This will return the total price inclusive of all fees for the purchase. **`Request`** ```curl Request 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`** ```json Response //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 } } } ``` 4. [Tokenize the Credit Card Number.](/recipes/recipes/pci-compliant-card-tokenization) See tab: `Tokenize New Card` 5. [Enable a New Card Checkout](/api-reference/api-reference/checkout/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: **`Request`** ```curl Request 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 } ] } ' ``` **`Response`** ```json Response {"paymentId":"bdc22a87-fb72-4f9d-a445-f26c04c8376c"} ``` 5. [Re-tokenize a saved card number.](/recipes/recipes/pci-compliant-card-tokenization) See tab: `Refresh Token w/ CVV` 6. [Enable a Saved Card Checkout](/api-reference/api-reference/checkout/token-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](/api-reference/api-reference/checkout/token-checkout). Below is an example request: ```curl 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" } ' ``` ```json {"paymentId":"e416a462-33a3-4e80-ab8d-ffa2de666a2b"} ``` 6. [Create a redeem transaction](/api-reference/api-reference/redeem/get-redeem-transaction) ```curl 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 } ' ``` ```json { "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEdnssu5ihuBbYXnay6AysBCyiQBbo1rHkC7sqKn56zgoLmFDTAcK6f9UyX4cReT2c671UzhdG4Wa6jZh2BYCMu78nSesoeMSS9XQ6jXvRyA2fs1wRiMwRCaCEe8StVHmQVvwpof6Tv9WoTcQAAn4nYWqNMgBHLnpk5KAEj6QtBcub6fBW9hRsHDj6bW1XdhuokCVyoayg9KywYjva7cbPLJRZM9aNywUv41og9Jr1pvV6qqCcehXJ4kyFEuayAqhn1Zku4oFaoMrKe3uydjbpy2Pu1nv4wz4JQHa7yeaNWcQysKdEKsqi5dJSkGkaoRBKdM3nhCdTRLAvik4AZYSeBDP5unqd73aRekzX9Z7PmfzTC7FVTWLqtJA3Z3dze2QqHr7yLvgvZAhtPZgjXhW9U4YmLFsBwAfFy4T1GZUwBQirfmwYAhV9pBxnqLLHvfGTizmZLU22EGVrFAz6RDD4mogcUgxjFa56irwL3v5dd6BrpwZcwCDf35ad5AeeKx2JSJ5XmbKr7xmDATMFMqfGPu37mCwo8t6MUsdoqYFTAUhy6gvp4XKwouLMpQU4UnykXubFnUHkYZBkR9yurSExM835A6mtk1ufcVpYc1bc148ciM5w1ZPpC7W1M28u17jaECCnGSERfNettZNmkrQCK8rJ42bSqYa7dnnfnyFer7Exv8mFcFmFs4Br9k568wUHyUvQMrT4WTaY1EiQtc6WmWzHvmUxgc2ppNKRNXa7YFxQfNYbP4diA3s26cKymTqmGmuR8pEPoV5aabm8dmAtZhmVNuoF8S3M7WUVnMuWToFa8quKM4uVPgg4xWShnFdjv4MmsAbPpFcbfTeMDMfRXKAQLw2C6q2dgoJredwaG843HEgAjVmTN1H2Evnezc3cMXFuJUWdSwL22AEUsZJJwS6jNTLmGZBbgtPJVn3Wg4PGtJTky2uxWx3uL1B6AJxYEfh" } ``` 7. 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](/api-reference/api-reference/utilities/send-coinflow-transaction). **`Sign Transaction`** ```javascript Sign Transaction 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); } } ``` **`Send Transaction`** ```curl Send Transaction 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" } ' ``` 8. [Add Chargeback protection on EVERY PAGE of your app](/guides/checkout/payment-security-risk-management/fraud-protection/implement-chargeback-protection#how-to-add-chargeback-protection) * Note: This is required!