Credit Purchase Integration: USDC Settled Directly to Coinflow Wallet

Setup

Developer Resources

Quick Links:

Authorization Headers:

  • Authorization is your API Key. You can generate this from the merchant dashboard
  • x-coinflow-auth-user-id is a unique customer ID you use within your systems to identify the user withdrawing funds
  • x-coinflow-auth-blockchain should always be solana if your settlement location is the Coinflow in-app wallet
  • x-coinflow-auth-session-key is a JWT that authorizes the payer. This is valid for 24 hours and must be refreshed anytime after
  1. 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.

    SignUpEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignUp",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "username": "therock72",
    11 "email": "dwaynejohnson@gmail.com",
    12 "firstName": "Dwayne",
    13 "lastName": "Johnson"
    14}
    15'
    SignInEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOU_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignIn",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "email": "dwaynejohnson@gmail.com"
    11}
    12'
    SignInFailureEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignInFailure",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "email": "dwaynejohnson@gmail.com",
    11 "failureReason": "Password Failed"
    12}
    13'
    BuyerChallengeEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "BuyerChallenge",
    8 "type": "thirdPartyKyc",
    9 "status": "successfullyFulfilled",
    10 "customerId": "user-123-abc",
    11 "country": "US",
    12 "email": "dwaynejohnson@gmail.com"
    13}
    14'
  2. Get a checkout link
    This endpoint will generate a link which you can embed in an iframe or redirect users directly to.

    Request
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/checkout/link \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'accept: application/json' \
    5 --header 'content-type: application/json' \
    6 --header 'x-coinflow-auth-blockchain: solana' \
    7 --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt' \
    8 --data '
    9{
    10 "webhookInfo": {
    11 "example": "{\"depositId\": \"123-abc-456\"}"
    12 }, // Add any webhook info you want to receive here
    13 "subtotal": {
    14 "currency": "USD",
    15 "cents": 100
    16 },
    17 "settlementType": "Credits",
    18 "email": "user@gmail.com", // the purchasers email address
    19 "blockchain": "solana",
    20 "chargebackProtectionData": [
    21 {
    22 "productType": "", // Get this value from Coinflow after completing chargeback protection questionnaire
    23 "rawProductData": {
    24 "example": "{\"description\": \"something about the purchase\"}"
    25 }, // Pass as much descriptive data detailing the purchase.
    26 "productName": "Product Name",
    27 "quantity": 1
    28 }
    29 ],
    30 "deviceId": "123456789", // Get this from: https://docs.coinflow.cash/docs/implement-chargeback-protection#how-to-add-chargeback-protection
    31 "supportEmail": "support@mycompany.com"
    32 }
    33'
    Response
    1{"link":"https://sandbox.coinflow.cash/solana/purchase-v2/testtest?sessionKey=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzE5MDQsImV4cCI6MTczNzc1ODMwNH0.zpCD3yH6eeEQHfDHzj2lLeD4-irLz61bgcwcp0gTi_Y&cents=100&currency=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 .

    Request
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/redeem/merchant \
    3 --header 'accept: application/json' \
    4 --header 'content-type: application/json' \
    5 --header 'x-coinflow-auth-blockchain: solana' \
    6 --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt' \
    7 --data '
    8{
    9 "subtotal": {
    10 "cents": 500
    11 },
    12 "merchantId": "YOUR_MERCHANT_ID"
    13}
    14'
    Response
    1{
    2 "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEdnssu5ihuBbYXnay6AysBCyiQBbo1rHkC7sqKn56zgoLmFDTAcK6f9UyX4cReT2c671UzhdG4Wa6jZh2BYCMu78nSesoeMSS9XQ6jXvRyA2fs1wRiMwRCaCEe8StVHmQVvwpof6Tv9WoTcQAAn4nYWqNMgBHLnpk5KAEj6QtBcub6fBW9hRsHDj6bW1XdhuokCVyoayg9KywYjva7cbPLJRZM9aNywUv41og9Jr1pvV6qqCcehXJ4kyFEuayAqhn1Zku4oFaoMrKe3uydjbpy2Pu1nv4wz4JQHa7yeaNWcQysKdEKsqi5dJSkGkaoRBKdM3nhCdTRLAvik4AZYSeBDP5unqd73aRekzX9Z7PmfzTC7FVTWLqtJA3Z3dze2QqHr7yLvgvZAhtPZgjXhW9U4YmLFsBwAfFy4T1GZUwBQirfmwYAhV9pBxnqLLHvfGTizmZLU22EGVrFAz6RDD4mogcUgxjFa56irwL3v5dd6BrpwZcwCDf35ad5AeeKx2JSJ5XmbKr7xmDATMFMqfGPu37mCwo8t6MUsdoqYFTAUhy6gvp4XKwouLMpQU4UnykXubFnUHkYZBkR9yurSExM835A6mtk1ufcVpYc1bc148ciM5w1ZPpC7W1M28u17jaECCnGSERfNettZNmkrQCK8rJ42bSqYa7dnnfnyFer7Exv8mFcFmFs4Br9k568wUHyUvQMrT4WTaY1EiQtc6WmWzHvmUxgc2ppNKRNXa7YFxQfNYbP4diA3s26cKymTqmGmuR8pEPoV5aabm8dmAtZhmVNuoF8S3M7WUVnMuWToFa8quKM4uVPgg4xWShnFdjv4MmsAbPpFcbfTeMDMfRXKAQLw2C6q2dgoJredwaG843HEgAjVmTN1H2Evnezc3cMXFuJUWdSwL22AEUsZJJwS6jNTLmGZBbgtPJVn3Wg4PGtJTky2uxWx3uL1B6AJxYEfh"
    3}
  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.

    Sign Transaction
    1const { Connection, Keypair, VersionedTransaction } = require('@solana/web3.js');
    2const bs58 = require('bs58');
    3
    4const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
    5const privateKeyString = 'YOUR_BASE58_PRIVATE_KEY';
    6const privateKey = bs58.decode(privateKeyString);
    7const keypair = Keypair.fromSecretKey(privateKey);
    8const base58Transaction = 'REPLACE_WITH_REDEEM_TX'; //replace with tx returned from step 3
    9
    10// return a signed tx
    11async function signTransaction() {
    12 try {
    13 const decodedTransactionBytes = bs58.decode(base58Transaction);
    14 const versionedTransaction = VersionedTransaction.deserialize(decodedTransactionBytes);
    15 versionedTransaction.sign([keypair]); // wallet signs tx
    16 const serializedTransaction = versionedTransaction.serialize();
    17 const base58SignedTransaction = bs58.encode(serializedTransaction); // encode signed tx to base58
    18
    19 console.log(signed tx:', signedTransaction);
    20 return base58SignedTransaction; // This is what youll send to the blockchain
    21
    22 } catch (err) {
    23 console.error('Error signing the transaction:', err);
    24 }
    25}
    Send Transaction
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/utils/send-coinflow-tx \
    3 --header 'accept: application/json' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "merchantId": "testtest",
    8 "signedTransaction": "5gkDhvbf4ntXpmmN5pWqBRMLumB7z9En6tfgS19sdDZaXKzEMPRoP7DYZ1bMvqwS9xTQnw6AsR8ucnEtx35zqBryNmCKjWYGf1VW8WpeXYuqHhYHdWgEPxxXXY4iqNhexrodYWeyH2eXpAwNPFKo1wfLkVJsxARhdYu9o9HJU1Ba6x4ZZWmWoLFRL3yWZ2H1GytsubAmj7fzArjGuoSCUkHNzsSZpvAFux7Mstie5JuzvzGJqGc9tVTcUjrCmjkij8mdbN4rP3C6VFwyxDRt64DCJvc4A3epX8YhqW84wj7WXuxQVWcyjRHmyuaD4nhaHeyFMWYCjTo8ZywcoZJ3n7dvrzqQTXTSY2V2UmkApBE5Qkni2WiekTfjryQBKLUDFFAcHtZXE1gy1X4wCFgvbyi8USVAhqTH8Y86h62nhjVEcXqLxbwm48F7Fqq8QLtoBNg3j7BRLEdwXvjK7y6f7WF1iSnL2Q4b4fwVUwU37UZchBPKt1GcRw1pF2ohwZ9krK4dbfjUpa2w5HsrBgGfVttBaBUXaSvaxkJQmWwM1bfVtBHXJf8rCBt5uTDfvyPJjtzkZDE3irFQWXiJ2bA9HodZnz4myPM6AWFiCJXVcKjLsmTnYkUvQwZ84nzx7jvPp7ZXLeJ2fa5uMxdnHsSdjwoQeuaHPapDfCoawSSVoTtFMYPjREiaMqckCht7u2LLeedbdMvLsQt5btM8R9uCSFzYbpKQLZEwZ4XMmfxoqdTCagjoEe7Yg3o3XB7KqUJma6LwFJJwG24yprCEveYCrkD8GiqXmphmx2Q4M1Drk1ygKGDqLn246UWt9nxoZusqDSnzruHh7gaE8tgx1iH7z29Bkm6UAqDMLY3BnVgYJxuQkH4PcD2E2yrgrZDJuqQtMxyB2uFLe3eb75mnZjfshL4wYD54BScEmybHxjA2ee1T7ZUv8VJZ53c74wzZ8BdGM4NASnjtcVh5yWWWkURekMXPHFkrxytsoc4PjXwF7NaNaT"
    9}
    10'

React SDK Implementation

  1. 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.
    SignUpEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignUp",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "username": "therock72",
    11 "email": "dwaynejohnson@gmail.com",
    12 "firstName": "Dwayne",
    13 "lastName": "Johnson"
    14}
    15'
    SignInEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOU_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignIn",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "email": "dwaynejohnson@gmail.com"
    11}
    12'
    SignInFailureEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignInFailure",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "email": "dwaynejohnson@gmail.com",
    11 "failureReason": "Password Failed"
    12}
    13'
    BuyerChallengeEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "BuyerChallenge",
    8 "type": "thirdPartyKyc",
    9 "status": "successfullyFulfilled",
    10 "customerId": "user-123-abc",
    11 "country": "US",
    12 "email": "dwaynejohnson@gmail.com"
    13}
    14'
  2. Install Coinflow package
    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.
1<CoinflowPurchase
2 wallet={{
3 publicKey: new PublicKey('USER_PUBLIC_KEY'),
4 signMessage: (message: UInt8Array) => Promise,
5 sendTransaction: (transaction: Transaction | VersionedTransaction) => Promise
6 }}
7 connection={connection} // solana rpc connection
8 blockchain={'solana'}
9 merchantId={'testtest'} // Replace with your merchant id
10 env={'sandbox || prod'}
11 onSuccess={(...args) => {
12 console.log('Purchase Success', args); // Provide your own function after payment success
13 }}
14 subtotal={{currency: Currency.USD,
15 cents: 100}} // purchase amount in USD
16 webhookInfo={{
17 productId: '123abc',
18 item: 'sword',
19 }} // Pass additional webhook info youd like to receive
20 email="user@test.com" // payer's email address
21 chargebackProtectionData={[
22 {
23 productName: "Product Name",
24 productType: "gameOfSkill", // Get this value from Coinflow after filling out chargeback questionnaire
25 quantity: 1,
26 rawProductData: {
27 productID: "sword12345",
28 productDescription: "A legendary sword with magical powers.",
29 productCategory: "Weapon",
30 weight: "15 lbs",
31 dimensions: "40 in x 5 in",
32 origin: "Ancient Kingdom",
33 craftedBy: "Master Blacksmith",
34 craftingDate: "2024-06-19",
35 }, // Customize with as much info you have on the purchase
36 },
37 ]}
38 settlementType={SettlementType.Credits}
39 />
  1. Then, when the customer wants to redeem their credits, you can implement the CoinflowPurchase like below:
    1<CoinflowPurchase
    2 wallet={{
    3 publicKey: new PublicKey('USER_PUBLIC_KEY'),
    4 signMessage: (message: UInt8Array) => Promise,
    5 sendTransaction: (transaction: Transaction | VersionedTransaction) => Promise
    6 }}
    7 connection={connection} // solana rpc connection
    8 blockchain={'solana'}
    9 merchantId={'testtest'} // Replace with your merchant id
    10 env={'sandbox || prod'}
    11 onSuccess={(...args) => {
    12 console.log('Purchase Success', args); // Provide your own function after payment success
    13 }}
    14 subtotal={{currency: Currency.USD,
    15 cents: 100}} // purchase amount in USD
    16 webhookInfo={{
    17 productId: '123abc',
    18 item: 'sword',
    19 }} // Pass additional webhook info youd like to receive
    20 email="user@test.com" // payer's email address
    21 chargebackProtectionData={[
    22 {
    23 productName: "Product Name",
    24 productType: "gameOfSkill", // Get this value from Coinflow after filling out chargeback questionnaire
    25 quantity: 1,
    26 rawProductData: {
    27 productID: "sword12345",
    28 productDescription: "A legendary sword with magical powers.",
    29 productCategory: "Weapon",
    30 weight: "15 lbs",
    31 dimensions: "40 in x 5 in",
    32 origin: "Ancient Kingdom",
    33 craftedBy: "Master Blacksmith",
    34 craftingDate: "2024-06-19",
    35 }, // Customize with as much info you have on the purchase
    36 },
    37 ]}
    38 settlementType={SettlementType.Credits}
    39 transaction={tx} // This should be a base58 encoded tx created by the merchant.
    40 // 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.
    41 />
  2. Add Chargeback protection on EVERY PAGE of your app
    • Note: This is required!

API Implementation

  1. 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.

    SignUpEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignUp",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "username": "therock72",
    11 "email": "dwaynejohnson@gmail.com",
    12 "firstName": "Dwayne",
    13 "lastName": "Johnson"
    14}
    15'
    SignInEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOU_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignIn",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "email": "dwaynejohnson@gmail.com"
    11}
    12'
    SignInFailureEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "SignInFailure",
    8 "customerId": "user-123-abc",
    9 "country": "US",
    10 "email": "dwaynejohnson@gmail.com",
    11 "failureReason": "Password Failed"
    12}
    13'
    BuyerChallengeEvent
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/events \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "eventType": "BuyerChallenge",
    8 "type": "thirdPartyKyc",
    9 "status": "successfullyFulfilled",
    10 "customerId": "user-123-abc",
    11 "country": "US",
    12 "email": "dwaynejohnson@gmail.com"
    13}
    14'
  2. Generate an API Key from Merchant Dashboard > API Keys > Create.

  3. Get a Session Key
    This creates a JWT for the payer and must be refreshed every 24 hours.

    Request
    1curl --request GET \
    2 --url https://api-sandbox.coinflow.cash/api/auth/session-key \
    3 --header 'Authorization: YOUR_API_KEY' \
    4 --header 'accept: application/json' \
    5 --header 'x-coinflow-auth-blockchain: solana' \
    6 --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt'
    Response
    1{
    2 "key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY"
    3}

    Note: Session keys are valid for 30 minutes and must be refreshed upon expiration.

  4. Get the Totals for the checkout
    This will return the total price inclusive of all fees for the purchase.

Request
1curl --location 'https://api-sandbox.coinflow.cash/api/checkout/totals/YOUR_MERCHANT_ID' \
2--header 'accept: application/json' \
3--header 'content-type: application/json' \
4--header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY' \
5--data '
6{
7 "subtotal": {
8 "cents": 200
9 }
10}
11'
Response
1//Response
2{
3 "card": {
4 "subtotal": {
5 "cents": 200
6 },
7 "creditCardFees": {
8 "cents": 0
9 },
10 "chargebackProtectionFees": {
11 "cents": 0
12 },
13 "gasFees": {
14 "cents": 0
15 },
16 "total": {
17 "cents": 200
18 },
19 "merchantPaidCreditCardFees": {
20 "cents": 36
21 },
22 "merchantPaidGasFees": {
23 "cents": 0
24 },
25 "merchantPaidChargebackProtectionFees": {
26 "cents": 0
27 }
28 },
29 "ach": {
30 "subtotal": {
31 "cents": 200
32 },
33 "creditCardFees": {
34 "cents": 0
35 },
36 "chargebackProtectionFees": {
37 "cents": 0
38 },
39 "gasFees": {
40 "cents": 0
41 },
42 "total": {
43 "cents": 200
44 },
45 "merchantPaidCreditCardFees": {
46 "cents": 100
47 },
48 "merchantPaidGasFees": {
49 "cents": 0
50 },
51 "merchantPaidChargebackProtectionFees": {
52 "cents": 0
53 }
54 }
55}
  1. Tokenize the Credit Card Number. See tab: Tokenize New Card
  2. 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:
Request
1curl --location 'https://api-sandbox.coinflow.cash/api/checkout/card/testtest' \
2--header 'accept: application/json' \
3--header 'content-type: application/json' \
4--header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY' \
5--data-raw '
6{
7 "subtotal": {
8 "currency": "USD",
9 "cents": 100
10 },
11 "webhookInfo": {
12 "example": "{\"description\": \"whatever webhooks info you want to receive\"}"
13 }, // pass whatever webhook info you want to receive
14 "card": {
15 "expYear": "29",
16 "expMonth": "10",
17 "email": "dwayne@therock.com",
18 "firstName": "dwayne",
19 "lastName": "johnson",
20 "address1": "123 Rock Road",
21 "city": "Chicago",
22 "zip": "60606",
23 "state": "IL",
24 "country": "US",
25 "cardToken": "230377JSUM3F0275" // Get this from: https://docs.coinflow.cash/recipes/pci-compliant-credit-card-tokenization
26 },
27 "settlementType": "Credits",
28 "authentication3DS": {
29 "colorDepth": 30,
30 "screenHeight": 1000,
31 "screenWidth": 2000,
32 "timeZone": 5
33 }, // Get this from: https://docs.coinflow.cash/recipes/complete-checkout-with-3ds-challenge
34 "chargebackProtectionData": [
35 {
36 "productType": "inGameProduct", // Get this after completing chargeback protection questionnaire
37 "rawProductData": {
38 "example": "{\"description\": \"pass data about the purchase\"}"
39 },
40 "productName": "Product Name",
41 "quantity": 1
42 }
43 ]
44}
45'
Response
1{"paymentId":"bdc22a87-fb72-4f9d-a445-f26c04c8376c"}
  1. Re-tokenize a saved card number. See tab: Refresh Token w/ CVV
  2. 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:
1curl --location 'https://api-sandbox.coinflow.cash/api/checkout/token/testtest' \
2--header 'accept: application/json' \
3--header 'content-type: application/json' \
4--header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3YWxsZXQiOiI5cnB2Mlc2cXlTaHdjd1RnWlhwaUZ1QzVrRkdZcHpoWXVnbXBLSzVMczRLdCIsImJsb2NrY2hhaW4iOiJzb2xhbmEiLCJtZXJjaGFudElkIjoidGVzdHRlc3QiLCJpYXQiOjE3Mzc2NzA5MDgsImV4cCI6MTczNzc1NzMwOH0.muaqSAPV2jrezdUI4GGeP2srlRzb1ZvWcv9yAAZ6zpY' \
5--header 'x-device-id: 123456789' \
6--data '
7{
8 "settlementType": "Credits",
9 "subtotal": {
10 "currency": "USD",
11 "cents": 100
12 },
13 "webhookInfo": {
14 "example": "{\"description\": \"whatever webhooks info you want to receive\"}"
15 },
16 "authentication3DS": {
17 "colorDepth": 30,
18 "screenHeight": 1000,
19 "screenWidth": 2000,
20 "timeZone": 5
21 },
22 "chargebackProtectionData": [
23 {
24 "productType": "gameOfSkill",
25 "rawProductData": {
26 "example": "{\"description\": \"pass data about the purchase\"}"
27 },
28 "productName": "Product Name",
29 "quantity": 1
30 }
31 ],
32 "token": "230377JSUM3F0275"
33}
34'
1{"paymentId":"e416a462-33a3-4e80-ab8d-ffa2de666a2b"}
  1. Create a redeem transaction

    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/redeem/merchant \
    3 --header 'accept: application/json' \
    4 --header 'content-type: application/json' \
    5 --header 'x-coinflow-auth-blockchain: solana' \
    6 --header 'x-coinflow-auth-wallet: 9rpv2W6qyShwcwTgZXpiFuC5kFGYpzhYugmpKK5Ls4Kt' \
    7 --data '
    8{
    9 "subtotal": {
    10 "cents": 500
    11 },
    12 "merchantId": "YOUR_MERCHANT_ID"
    13}
    14'
    1{
    2 "transaction": "5hAzkEBF2jNWz4Yo5mv63p2Nc8HKFyC4PhKmvtE5KbEdnssu5ihuBbYXnay6AysBCyiQBbo1rHkC7sqKn56zgoLmFDTAcK6f9UyX4cReT2c671UzhdG4Wa6jZh2BYCMu78nSesoeMSS9XQ6jXvRyA2fs1wRiMwRCaCEe8StVHmQVvwpof6Tv9WoTcQAAn4nYWqNMgBHLnpk5KAEj6QtBcub6fBW9hRsHDj6bW1XdhuokCVyoayg9KywYjva7cbPLJRZM9aNywUv41og9Jr1pvV6qqCcehXJ4kyFEuayAqhn1Zku4oFaoMrKe3uydjbpy2Pu1nv4wz4JQHa7yeaNWcQysKdEKsqi5dJSkGkaoRBKdM3nhCdTRLAvik4AZYSeBDP5unqd73aRekzX9Z7PmfzTC7FVTWLqtJA3Z3dze2QqHr7yLvgvZAhtPZgjXhW9U4YmLFsBwAfFy4T1GZUwBQirfmwYAhV9pBxnqLLHvfGTizmZLU22EGVrFAz6RDD4mogcUgxjFa56irwL3v5dd6BrpwZcwCDf35ad5AeeKx2JSJ5XmbKr7xmDATMFMqfGPu37mCwo8t6MUsdoqYFTAUhy6gvp4XKwouLMpQU4UnykXubFnUHkYZBkR9yurSExM835A6mtk1ufcVpYc1bc148ciM5w1ZPpC7W1M28u17jaECCnGSERfNettZNmkrQCK8rJ42bSqYa7dnnfnyFer7Exv8mFcFmFs4Br9k568wUHyUvQMrT4WTaY1EiQtc6WmWzHvmUxgc2ppNKRNXa7YFxQfNYbP4diA3s26cKymTqmGmuR8pEPoV5aabm8dmAtZhmVNuoF8S3M7WUVnMuWToFa8quKM4uVPgg4xWShnFdjv4MmsAbPpFcbfTeMDMfRXKAQLw2C6q2dgoJredwaG843HEgAjVmTN1H2Evnezc3cMXFuJUWdSwL22AEUsZJJwS6jNTLmGZBbgtPJVn3Wg4PGtJTky2uxWx3uL1B6AJxYEfh"
    3}
  2. 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.

    Sign Transaction
    1const { Connection, Keypair, VersionedTransaction } = require('@solana/web3.js');
    2const bs58 = require('bs58');
    3
    4const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
    5const privateKeyString = 'YOUR_BASE58_PRIVATE_KEY';
    6const privateKey = bs58.decode(privateKeyString);
    7const keypair = Keypair.fromSecretKey(privateKey);
    8const base58Transaction = 'REPLACE_WITH_REDEEM_TX'; //replace with tx returned from step 3
    9
    10// return a signed tz
    11async function signTransaction() {
    12 try {
    13 const decodedTransactionBytes = bs58.decode(base58Transaction);
    14 const versionedTransaction = VersionedTransaction.deserialize(decodedTransactionBytes);
    15 versionedTransaction.sign([keypair]); // wallet signs tx
    16 const serializedTransaction = versionedTransaction.serialize();
    17 const base58SignedTransaction = bs58.encode(serializedTransaction); // encode signed tx to base58
    18
    19 console.log(signed tx:', signedTransaction);
    20 return base58SignedTransaction; // This is what youll send to the blockchain
    21
    22 } catch (err) {
    23 console.error('Error signing the transaction:', err);
    24 }
    25}
    Send Transaction
    1curl --request POST \
    2 --url https://api-sandbox.coinflow.cash/api/utils/send-coinflow-tx \
    3 --header 'accept: application/json' \
    4 --header 'content-type: application/json' \
    5 --data '
    6{
    7 "merchantId": "testtest",
    8 "signedTransaction": "5gkDhvbf4ntXpmmN5pWqBRMLumB7z9En6tfgS19sdDZaXKzEMPRoP7DYZ1bMvqwS9xTQnw6AsR8ucnEtx35zqBryNmCKjWYGf1VW8WpeXYuqHhYHdWgEPxxXXY4iqNhexrodYWeyH2eXpAwNPFKo1wfLkVJsxARhdYu9o9HJU1Ba6x4ZZWmWoLFRL3yWZ2H1GytsubAmj7fzArjGuoSCUkHNzsSZpvAFux7Mstie5JuzvzGJqGc9tVTcUjrCmjkij8mdbN4rP3C6VFwyxDRt64DCJvc4A3epX8YhqW84wj7WXuxQVWcyjRHmyuaD4nhaHeyFMWYCjTo8ZywcoZJ3n7dvrzqQTXTSY2V2UmkApBE5Qkni2WiekTfjryQBKLUDFFAcHtZXE1gy1X4wCFgvbyi8USVAhqTH8Y86h62nhjVEcXqLxbwm48F7Fqq8QLtoBNg3j7BRLEdwXvjK7y6f7WF1iSnL2Q4b4fwVUwU37UZchBPKt1GcRw1pF2ohwZ9krK4dbfjUpa2w5HsrBgGfVttBaBUXaSvaxkJQmWwM1bfVtBHXJf8rCBt5uTDfvyPJjtzkZDE3irFQWXiJ2bA9HodZnz4myPM6AWFiCJXVcKjLsmTnYkUvQwZ84nzx7jvPp7ZXLeJ2fa5uMxdnHsSdjwoQeuaHPapDfCoawSSVoTtFMYPjREiaMqckCht7u2LLeedbdMvLsQt5btM8R9uCSFzYbpKQLZEwZ4XMmfxoqdTCagjoEe7Yg3o3XB7KqUJma6LwFJJwG24yprCEveYCrkD8GiqXmphmx2Q4M1Drk1ygKGDqLn246UWt9nxoZusqDSnzruHh7gaE8tgx1iH7z29Bkm6UAqDMLY3BnVgYJxuQkH4PcD2E2yrgrZDJuqQtMxyB2uFLe3eb75mnZjfshL4wYD54BScEmybHxjA2ee1T7ZUv8VJZ53c74wzZ8BdGM4NASnjtcVh5yWWWkURekMXPHFkrxytsoc4PjXwF7NaNaT"
    9}
    10'
  3. Add Chargeback protection on EVERY PAGE of your app

    • Note: This is required!