<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Drew Harris</title>
    <description>The latest articles on DEV Community by Drew Harris (@uxdrew).</description>
    <link>https://dev.to/uxdrew</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F420293%2F6b6c2717-87fb-464f-8b8e-d802a02910ee.jpeg</url>
      <title>DEV Community: Drew Harris</title>
      <link>https://dev.to/uxdrew</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uxdrew"/>
    <language>en</language>
    <item>
      <title>Boosting Authorization Rates: Partnering Strategies and Intelligent Retries</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Tue, 09 Dec 2025 18:13:02 +0000</pubDate>
      <link>https://dev.to/rapyd/boosting-authorization-rates-partnering-strategies-and-intelligent-retries-5all</link>
      <guid>https://dev.to/rapyd/boosting-authorization-rates-partnering-strategies-and-intelligent-retries-5all</guid>
      <description>&lt;p&gt;By: Adeyinka Adegbenro&lt;/p&gt;

&lt;p&gt;Authorization rates measure the ratio of successful payments to total attempts. For instance, if a merchant processes one hundred payments and seventy of them are successful, the authorization rate is 70 percent. This metric directly impacts revenue, customer satisfaction, and operational efficiency. High authorization rates mean more revenue captured, while poor rates can signal system issues, like failed authentication, unreliable processors, or friction in the payment flow.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn about the different stages of a payment and where declines typically happen. You'll also learn about strategies that can help boost your approval rates, including smart retries using &lt;a href="https://docs.rapyd.net/en/merchant-advice-codes.html" rel="noopener noreferrer"&gt;merchant advice codes&lt;/a&gt;, implementing artificial intelligence (AI) optimizations, and working with unified platforms like &lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Payment Authorization Funnel
&lt;/h2&gt;

&lt;p&gt;Before you can boost authorization rates, you need to understand how money moves from the customer to the merchant. Each stage is a potential point of failure. Understanding the moving parts helps you anticipate the kinds of authorization errors that may take place at different stages and how to respond strategically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stages of an Online Payment
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7r0k96y5xrfknocbfvk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7r0k96y5xrfknocbfvk.png" alt="Diagram of the stages of an online payment, courtesy of Adeyinka Adegbenro" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The lifecycle of an online payment begins when a customer submits their card details on the merchant's application. That triggers an authorization request that is securely transmitted through a payment gateway (API) to a payment processor. The payment gateway and payment processor are often the same provider. &lt;a href="https://www.rapyd.net/developers/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt; provides both services through one unified solution.&lt;/p&gt;

&lt;p&gt;Next, the payment processor may initiate a 3-D Secure (3DS) flow if required. During this step, the issuer may perform additional checks, like one-time passwords (OTPs) or biometric prompts. Once authentication is complete, the authorization request is then routed through a card network, like &lt;a href="https://visa.com/" rel="noopener noreferrer"&gt;Visa&lt;/a&gt;, &lt;a href="https://www.vervecardinfo.com/" rel="noopener noreferrer"&gt;Verve&lt;/a&gt;, or &lt;a href="https://mastercard.com/" rel="noopener noreferrer"&gt;Mastercard&lt;/a&gt;. The network, in turn, forwards the authorization request to the customer's issuing bank. Based on various signals, such as available balance, fraud checks, and card validity, the issuing bank ultimately decides whether to receive or reject the payment. The decision travels back through the same route to the merchant, where the result is displayed to the customer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Declines and Visibility into the Funnel
&lt;/h3&gt;

&lt;p&gt;Declines can happen at any stage in the payment process, from network outages and expired cards to incorrect PINs or CVVs, fraud alerts, or insufficient funds. However, not all declines are created equal.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.rapyd.net/blog/the-merchants-guide-to-credit-card-decline-codes/" rel="noopener noreferrer"&gt;soft decline&lt;/a&gt; is temporary (&lt;em&gt;eg&lt;/em&gt; network timeouts, insufficient funds) and may succeed on retry. A hard decline (&lt;em&gt;eg&lt;/em&gt; stolen card, invalid number, wrong PIN) usually can't be resolved on retry. Developers need visibility into this funnel to know when and how to respond.&lt;/p&gt;

&lt;p&gt;For example, if a large portion of subscription payments fail due to expired cards, a retry will not be effective, but a card updater or reminder system may. This insight helps developers spot decline patterns and come up with strategies to prevent losing customers you've already spent money acquiring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Smart Retry Logic with MACs
&lt;/h2&gt;

&lt;p&gt;Merchant Advice Codes (MAC) are response indicators issued by banks or card networks that provide specific guidance when a transaction is declined. These responses usually follow a failed payment authorization attempt. The code helps the merchant determine whether the decline is temporary, permanent, or correctable. It can indicate whether to retry the transaction, prompt the customer for more information, or stop further attempts. By adhering to these codes, merchants can avoid needless retries and prevent damaging their authorization rates.&lt;/p&gt;

&lt;p&gt;The following are some common MACs and their meaning:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MAC&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;01&lt;/td&gt;
&lt;td&gt;Updated Information needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;Retry in the next hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;Retry after ten days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;Card reported stolen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;Invalid PIN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7903&lt;/td&gt;
&lt;td&gt;Do not retry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7921&lt;/td&gt;
&lt;td&gt;Do not honor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The examples in this guide are primarily sourced from Mastercard's MAC since MACs were first introduced by Mastercard. It's important to understand the meaning of each code and how to respond effectively. For example, if the code indicates &lt;code&gt;Do not retry&lt;/code&gt;, attempting the transaction again may trigger fraud alerts, chargebacks, fines, blacklisting, and reputational damage. You may forfeit any products or services that have already been delivered to the customer.&lt;/p&gt;

&lt;p&gt;A code like &lt;code&gt;Retry in the next hour&lt;/code&gt; suggests that the issue is temporary (&lt;em&gt;eg&lt;/em&gt; the spending limit has been reached or the cardholder's bank is temporarily unavailable). Some codes may point to missing or invalid data (in cases of an expired card or missing CVV), and if stronger customer authentication is required, merchants can prompt users to reenter or update their payment details or even go through a 3DS check. For subscription-based businesses, a card updater service may help avoid some of these errors entirely by refreshing card information automatically.&lt;/p&gt;

&lt;p&gt;Retrying only when it is appropriate increases your success rate without triggering issuer penalties or risking chargebacks. MAC-aware retry logic helps maintain healthy issuer relationships, reduce failed attempts, and improve overall conversion rates.&lt;/p&gt;

&lt;p&gt;It's important to note that MACs are not standardized across all issuers or payment processors. Different card issuers may return different codes for similar situations or none at all. In some cases, the MAC hints only at the problem without giving the full picture. It may even advise a retry, but that doesn't guarantee a successful retry.&lt;/p&gt;

&lt;p&gt;MACs should be used as part of a broader diagnostic strategy that includes logging, analytics, and close coordination with your payment provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using AI to Predict and Optimize Authorization Outcomes
&lt;/h2&gt;

&lt;p&gt;Like so many other areas, AI is revolutionizing payments by enabling faster, smarter decision-making. For instance, when it comes to payment optimization, AI can detect patterns in payment behavior and adapt in real time by analyzing historical transaction data to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify high-risk combinations that are likely to be declined&lt;/li&gt;
&lt;li&gt;Recommend the best time or method to retry a failed payment&lt;/li&gt;
&lt;li&gt;Predict fraud and proactively block transactions that are likely to be flagged and rejected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI models automate analysis and continuous learning, leading to the discovery of emerging patterns in your data. This helps improve authorization rates and payment efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case: Training Models on Transaction Data
&lt;/h3&gt;

&lt;p&gt;A common method for training AI models to predict authorization outcomes involves using a combination of historical and real-time transaction metadata. Here are some useful features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transaction amount&lt;/li&gt;
&lt;li&gt;Card bank identification number (BIN)&lt;/li&gt;
&lt;li&gt;Geolocation&lt;/li&gt;
&lt;li&gt;Timestamp&lt;/li&gt;
&lt;li&gt;Network quality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With enough data, you can train a model to predict success probability for each available payment route or method. This makes it possible to implement &lt;a href="https://arxiv.org/pdf/2111.00783" rel="noopener noreferrer"&gt;smart routing&lt;/a&gt;. For any incoming payment, the system calculates the route with the highest likelihood of approval and uses it. On failure, the system retries the transaction through the next most optimal route. This approach helps merchants increase authorization rates while reducing unnecessary retries.&lt;/p&gt;

&lt;h3&gt;
  
  
  How a Data-Driven Approach Boosts Success Rates
&lt;/h3&gt;

&lt;p&gt;AI enables the following intelligent mechanisms within payment systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data enrichment&lt;/strong&gt; augments payment requests by adding personally identifiable information (PII) that issuers have historically valued in approval decisions (&lt;em&gt;eg&lt;/em&gt; device information, geolocation).  Issuers are more likely to make better approval decisions when they have more contextual information about the cardholder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic retry&lt;/strong&gt; automates retries based on an evidence-based understanding of MACs or with a different payment service provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart filtering&lt;/strong&gt; filters out avoidable declines (&lt;em&gt;eg&lt;/em&gt; expired cards, duplicate payment submissions, fraud risk payments, bot activity, brute-force attempts with card PINs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart routing&lt;/strong&gt; selects the most promising processor most likely to approve a transaction, based on historical approval patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insight generation&lt;/strong&gt; uncovers patterns and root causes for declines, helping teams prioritize improvements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While AI has the ability to transform fraud detection, it's not without its challenges. Building, training, updating, and fine-tuning these models is complex work that demands massive data sets and serious computing power. Get the balance wrong, and you either block good customers (false positives) or let fraudsters slip through (false negatives).&lt;/p&gt;

&lt;p&gt;Then there's the regulatory maze. Data protection laws like the &lt;a href="https://gdpr-info.eu/" rel="noopener noreferrer"&gt;General Data Protection Regulation (GDPR)&lt;/a&gt; put strict limits on how you store non-anonymized customer data. Models must be designed to comply with these regulations by anonymizing and encrypting personal data.&lt;/p&gt;

&lt;p&gt;However, here's the thing: despite these challenges, AI makes payment systems more resilient and efficient—it's worth the effort. Even simple rule-based models can help small teams get started. You don't need a data science team or deep machine learning (ML) infrastructure to benefit from intelligent logic. Small teams can still improve success rates by implementing smart rule-based decision engines that handle MACs, flag common fraud indicators, or set retry thresholds. Over time, these systems can evolve into more sophisticated ML pipelines as resources and data maturity grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Partnering with a Unified Payments Platform
&lt;/h2&gt;

&lt;p&gt;A unified payments platform offers end-to-end payment services, like acquisition, issuance, payouts, and digital wallets under a single provider. Instead of relying on multiple services for each step of the payment funnel, businesses can streamline operations, reduce costs, and ship faster by working with a unified solution.&lt;/p&gt;

&lt;p&gt;One major advantage of unified payment platforms is full-stack orchestration. Since these platforms manage both the acquiring and issuing sides of the payment flow, they have more access to granular data, such as issuer response data and fraud signals. This gives them better intelligence about what issuer response codes actually mean and how to act on them.&lt;/p&gt;

&lt;p&gt;For instance, platforms that issue their own cards or wallets can facilitate internal transactions with less friction, leading to faster approvals, lower fees, and fewer declines. While merchants can't control which card the customers use, partnering with a unified platform significantly improves the likelihood of successful payment outcomes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt; supports payments, payouts, wallets, and card issuing under one umbrella. Even without ML support, the detailed issuer responses and metadata returned by Rapyd can serve as input for custom retry logic or AI decision models. This allows teams to improve retry outcomes without manually aggregating insights from multiple payment service providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Project: Payment Retry Orchestrator with MAC Logic
&lt;/h2&gt;

&lt;p&gt;This section walks you through a simple Node.js project that simulates multiple payment attempts and failure scenarios using MACs to guide retry behavior. The logic randomly fails some transactions and returns a corresponding MAC, which the orchestrator uses to decide what to do next: retry, prompt for a new method, or stop.&lt;/p&gt;

&lt;p&gt;If you prefer local development, you can clone the sample project on &lt;a href="https://github.com/Rapyd-Samples/rapyd-payment-retry-orchestrator" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; by running the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Rapyd-Samples/rapyd-payment-retry-orchestrator

&lt;span class="nb"&gt;cd &lt;/span&gt;payment-retry-orchestrator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also run this project instantly in your browser via &lt;a href="https://stackblitz.com/~/github.com/AdeyinkaAdegbenro/payment-retry-orchestrator" rel="noopener noreferrer"&gt;StackBlitz&lt;/a&gt;, with no setup required.&lt;/p&gt;

&lt;p&gt;The main components include the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/strong&gt; is the entry point of the project. It runs a batch of transactions using &lt;code&gt;runBatch&lt;/code&gt; and handles each one using  &lt;code&gt;processTransaction&lt;/code&gt;, which simulates the payment, receives a MAC, and applies the appropriate retry logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;simulator.js&lt;/code&gt;&lt;/strong&gt; contains the &lt;code&gt;simulateTransaction&lt;/code&gt; function, which randomly decides whether a transaction succeeds or fails. On failure, it returns a randomly selected MAC.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;macLogic.js&lt;/code&gt;&lt;/strong&gt; defines the function &lt;code&gt;interpretMAC&lt;/code&gt; to translate a MAC to an action. The &lt;code&gt;MAC_RULES&lt;/code&gt; object provides a sample set of MACs to action mappings (&lt;em&gt;eg&lt;/em&gt; retry, prompt, or halt).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dashboard.js&lt;/code&gt;&lt;/strong&gt; includes a &lt;code&gt;report&lt;/code&gt; function that summarizes the outcome of all transactions that have run. It tracks metrics like total attempts, retries triggered, user prompts, and halted transactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/strong&gt; provides setup instructions and ideas for extending the project with ML-powered predictions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run the simulator, in either your terminal or the StackBlitz terminal, execute the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the logs of each declined transaction and their corresponding meaning. After all the transactions have run, you'll see a summary report of all transactions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbtsv576myo060l5kfky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbtsv576myo060l5kfky.png" alt="Screenshot of the terminal output" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal isn't to replicate a full production-grade payment system. But as a foundation, you can extend with more advanced logic with payment orchestrator platforms like Rapyd, or even with predictive AI models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Declined payments are more than just lost revenue; they are pointers. By interpreting them and understanding the authorization funnel, developers can turn failed transactions into opportunities for recovery.&lt;/p&gt;

&lt;p&gt;With the right tools, you can go further than reactive retries. Rule-based retry strategies, AI-driven optimizations, and unified payment orchestration platforms like &lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt; can help you make smarter decisions at scale. Developers who take decline codes seriously as data points, rather than as dead ends, build smarter, anti-fragile systems that improve success rates and customer satisfaction.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>performance</category>
      <category>systemdesign</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Blockchain Interoperability: Connecting Multiple Blockchain Networks for Payments</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Tue, 09 Sep 2025 17:46:17 +0000</pubDate>
      <link>https://dev.to/rapyd/blockchain-interoperability-connecting-multiple-blockchain-networks-for-payments-35hn</link>
      <guid>https://dev.to/rapyd/blockchain-interoperability-connecting-multiple-blockchain-networks-for-payments-35hn</guid>
      <description>&lt;p&gt;Writer Name: &lt;strong&gt;Vivek Kumar Maskara&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Blockchain is a decentralized and immutable digital database or ledger that's distributed across a network of computers in a transparent and tamperproof manner.&lt;/p&gt;

&lt;p&gt;Blockchain interoperability refers to the ability of blockchains to communicate and share data with other blockchains. This enables developers to build cross-chain solutions that combine the strengths of each blockchain. For example, financial applications need blockchain interoperability to enable smooth cross-chain transactions and to improve liquidity, accessibility, and expand financial inclusion.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn how to implement blockchain interoperability using &lt;a href="https://soliditylang.org/" rel="noopener noreferrer"&gt;Solidity&lt;/a&gt; smart contracts for payment verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Fintech Applications Need Blockchain Interoperability
&lt;/h2&gt;

&lt;p&gt;If you're building a &lt;a href="https://www.coinbase.com/en-ca/learn/crypto-basics/what-are-decentralized-applications-dapps" rel="noopener noreferrer"&gt;decentralized application&lt;/a&gt; (dApps), you need blockchain interoperability. This allows your app to interact with different blockchain networks, expanding the app's access to assets, usability, and scalability.&lt;/p&gt;

&lt;p&gt;Here are a few benefits of blockchain interoperability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seamless cross-chain transactions:&lt;/strong&gt; Blockchain interoperability enables users to transfer assets across different blockchain networks without relying on centralized exchanges or manually converting them to &lt;a href="https://www.trmlabs.com/glossary/fiat-currency" rel="noopener noreferrer"&gt;fiat currency&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower transaction costs and faster settlement:&lt;/strong&gt; It reduces the need for intermediaries to carry out a transaction, optimizes payment processing costs, and enables &lt;a href="https://www.rapidinnovation.io/post/blockchain-for-cross-border-payments-ultimate-guide-to-fast-cheap-transfers#42-faster-settlement-times" rel="noopener noreferrer"&gt;faster settlement across blockchain networks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved liquidity and accessibility:&lt;/strong&gt; It connects fragmented payment ecosystems, allowing users to access a wider liquidity pool to exchange their tokens. For example, a user can transfer USDT from Ethereum (&lt;a href="https://ethereum.org/en/developers/docs/standards/tokens/erc-20/" rel="noopener noreferrer"&gt;ERC-20&lt;/a&gt;) to the &lt;a href="https://tron.network/" rel="noopener noreferrer"&gt;Tron network&lt;/a&gt; to take advantage of lower fees and faster transaction speeds. This enhances financial accessibility for global users as they can transfer their assets to a different chain based on their needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expanded financial inclusion:&lt;/strong&gt; Supporting multichain compatibility enables fintech applications to reach more users and businesses, even in regions where traditional financial services are limited.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Simplifying Payment Verification with Rapyd
&lt;/h2&gt;

&lt;p&gt;Blockchain interoperability sounds great in theory: move assets and data across networks seamlessly. But building a complete payment verification system requires significant developer effort. Smart contracts struggle to handle real-world requirements, like fiat conversions, regulatory compliance, fraud prevention, and off-chain settlement on their own, especially when these systems must remain reliable and responsive at scale.&lt;/p&gt;

&lt;p&gt;Thankfully, &lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt; offers a robust financial infrastructure with easy-to-integrate &lt;a href="https://docs.rapyd.net/en/get-started.html" rel="noopener noreferrer"&gt;REST APIs&lt;/a&gt; that offload the hard parts for you. It acts as an off-chain settlement layer and cross-chain data exchange, enabling use cases like automated compliance checks, &lt;a href="https://docs.rapyd.net/en/managing-escrow.html" rel="noopener noreferrer"&gt;escrow&lt;/a&gt;, and transaction verification, without requiring developers to build and maintain that infrastructure themselves.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://www.rapyd.net/blog/ai-fraud-prevention/" rel="noopener noreferrer"&gt;real-time fraud prevention&lt;/a&gt; and automated &lt;a href="https://www.rapyd.net/blog/how-rapyd-verify-can-help-global-businesses-with-robust-kyc/" rel="noopener noreferrer"&gt;global KYC/AML&lt;/a&gt; to fiat on/off-ramps in over 100 countries, Rapyd removes the traditional finance complexity from blockchain payments. The &lt;a href="https://docs.rapyd.net/en/api-reference.html" rel="noopener noreferrer"&gt;Rapyd API platform&lt;/a&gt; simplifies the end-to-end financial workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;&lt;a href="https://docs.rapyd.net/en/rapyd-collect-363484.html" rel="noopener noreferrer"&gt;Collect Payments API&lt;/a&gt;&lt;/strong&gt; receives funds from various payment methods and deposits them into &lt;a href="https://docs.rapyd.net/en/rapyd-wallet.html" rel="noopener noreferrer"&gt;Rapyd Wallets&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;&lt;a href="https://docs.rapyd.net/en/rapyd-verify-386565.html" rel="noopener noreferrer"&gt;Rapyd Verify APIs&lt;/a&gt;&lt;/strong&gt; perform hosted Know Your Business (KYB) and Know Your Customer (KYC) verifications to meet compliance requirements.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;&lt;a href="https://docs.rapyd.net/en/rapyd-protect.html" rel="noopener noreferrer"&gt;Rapyd Protect APIs&lt;/a&gt;&lt;/strong&gt; detect fraud and suspicious activity through built-in risk scoring, enhancing compliance and eliminating the need to build custom fraud logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.rapyd.net/en/webhook-format.html" rel="noopener noreferrer"&gt;Webhooks&lt;/a&gt;&lt;/strong&gt; receive real-time notifications for key events, such as payment status changes or verification updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an off-chain infrastructure layer, Rapyd also aligns with one of the core principles of blockchain systems: availability. Even during peak congestion or transaction delays on the blockchain, Rapyd continues to operate reliably, ensuring high availability for compliance, verification, and settlement workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Blockchain Interoperability
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you'll build, deploy, and test smart contracts on Ethereum testnets like &lt;a href="https://sepolia.etherscan.io/" rel="noopener noreferrer"&gt;Sepolia&lt;/a&gt; and &lt;a href="https://holesky.etherscan.io/" rel="noopener noreferrer"&gt;Holesky&lt;/a&gt;. The tutorial uses the &lt;a href="https://hardhat.org/hardhat-runner/docs/getting-started#overview" rel="noopener noreferrer"&gt;Hardhat&lt;/a&gt; developer environment to easily deploy your &lt;a href="https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html" rel="noopener noreferrer"&gt;Solidity smart contracts&lt;/a&gt; and test them using the Hardhat network, which is a local Ethereum network designed for development.&lt;/p&gt;

&lt;p&gt;Here are the primary components of the project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3270xrx1889xlkub4wnk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3270xrx1889xlkub4wnk.png" alt="Project architecture, courtesy of Vivek Kumar Maskara" width="800" height="1738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;CrossChainPayment&lt;/code&gt;&lt;/strong&gt; is a simple smart contract that initiates a cross-chain transaction and emits the &lt;code&gt;PaymentSent&lt;/code&gt; event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;PaymentVerifier&lt;/code&gt;&lt;/strong&gt; is another smart contract that simulates a cross-chain transaction verification and emits the &lt;code&gt;PaymentVerified&lt;/code&gt; event. For simplicity, it doesn't perform any complex checks, but it can be extended based on the use case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;relay.js&lt;/code&gt; script&lt;/strong&gt; watches for events on the source chain (&lt;em&gt;ie&lt;/em&gt; Sepolia) with the destination chain as Holesky and invokes the &lt;code&gt;verifyPayment&lt;/code&gt; method of the destination chain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before you get started, you need to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/learn/getting-started/introduction-to-nodejs" rel="noopener noreferrer"&gt;Install a Node.js development environment&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Sign up for an &lt;a href="https://auth.alchemy.com/signup/" rel="noopener noreferrer"&gt;Alchemy account&lt;/a&gt; and &lt;a href="https://docs.alchemy.com/docs/alchemy-quickstart-guide#1key-create-an-alchemy-api-key" rel="noopener noreferrer"&gt;create an API key&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.metamask.io/start/getting-started-with-metamask/" rel="noopener noreferrer"&gt;Set up Metamask and create a wallet&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/" rel="noopener noreferrer"&gt;Obtain a Metamask account private key&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Fund your Metamask wallet using Google Cloud's Ethereum &lt;a href="https://cloud.google.com/application/web3/faucet/ethereum/holesky" rel="noopener noreferrer"&gt;Holešky&lt;/a&gt; and &lt;a href="https://cloud.google.com/application/web3/faucet/ethereum/sepolia" rel="noopener noreferrer"&gt;Sepolia Faucet&lt;/a&gt;. You can use any faucet of your choice, but some faucets may require a minimum wallet balance to receive funds. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloning the Starter Project
&lt;/h3&gt;

&lt;p&gt;This tutorial uses &lt;a href="https://github.com/Rapyd-Samples/rapyd-starter-blockhain" rel="noopener noreferrer"&gt;this GitHub starter code&lt;/a&gt; that has a barebones Hardhat app set up. To follow along, clone the GitHub repo and switch to the &lt;code&gt;starter&lt;/code&gt; branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Rapyd-Samples/rapyd-starter-blockhain.git
&lt;span class="nb"&gt;cd &lt;/span&gt;rapyd-starter-blockhain
git checkout starter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go over the structure of the codebase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;package.json&lt;/code&gt; file defines the Hardhat project dependencies. It uses the &lt;a href="https://www.npmjs.com/package/hardhat" rel="noopener noreferrer"&gt;Hardhat&lt;/a&gt; dependency to get an Ethereum development environment and uses &lt;a href="https://www.npmjs.com/package/@nomicfoundation/hardhat-toolbox" rel="noopener noreferrer"&gt;@nomicfoundation/hardhat-toolbox&lt;/a&gt; to get all the common Hardhat plugins.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;contracts&lt;/code&gt; directory contains a sample &lt;code&gt;Lock.sol&lt;/code&gt; solidity smart contract. You won't need it in the tutorial, but you can use it to understand the basic structure of a Solidity smart contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Defining Smart Contracts for Cross-Chain Transaction Verification
&lt;/h3&gt;

&lt;p&gt;In this section, you'll define two smart contracts to enable cross-chain transaction verification. &lt;/p&gt;

&lt;h4&gt;
  
  
  CrossChainPayment contract
&lt;/h4&gt;

&lt;p&gt;Initially, you'll define the &lt;code&gt;CrossChainPayment&lt;/code&gt; that initiates a cross-chain payment and emits the &lt;code&gt;PaymentSent&lt;/code&gt; event. Here, you'll define a simple smart contract that checks for amount mismatch issues before emitting the &lt;code&gt;PaymentSent&lt;/code&gt; event. &lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;contracts/CrossChainPayment.sol&lt;/code&gt; file and add the following code snippet to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract CrossChainPayment {
    event PaymentSent(address indexed from, address indexed to, uint256 amount, uint256 chainId);

    function sendPayment(address to, uint256 amount, uint256 destChainId) external payable {
        require(msg.value == amount, "Amount mismatch");
        emit PaymentSent(msg.sender, to, amount, destChainId);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The smart contract defines a &lt;code&gt;sendPayment&lt;/code&gt; function that does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It takes the &lt;code&gt;to&lt;/code&gt; address and &lt;code&gt;amount&lt;/code&gt; for sending the payment, and it asserts that the &lt;code&gt;amount&lt;/code&gt; matches the value set by the sender in the &lt;code&gt;msg&lt;/code&gt; payload.&lt;/li&gt;
&lt;li&gt;It emits a &lt;code&gt;PaymentSent&lt;/code&gt; event with the sender's address (&lt;code&gt;msg.sender&lt;/code&gt;), receiver's address (&lt;code&gt;to&lt;/code&gt;), amount, and destination chain ID (&lt;code&gt;destChainId&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  PaymentVerified contract
&lt;/h4&gt;

&lt;p&gt;Now it's time to define the &lt;code&gt;PaymentVerifier&lt;/code&gt; that will be invoked by the &lt;a href="https://antiersolutions.medium.com/the-role-of-blockchain-relayer-in-transforming-financial-systems-ca2776dd761f" rel="noopener noreferrer"&gt;relayer&lt;/a&gt; (more on this later). The &lt;code&gt;PaymentVerifier&lt;/code&gt; smart contract contains the &lt;code&gt;verifyPayment&lt;/code&gt; method, where on-chain verification can be performed before emitting the &lt;code&gt;PaymentVerified&lt;/code&gt; event. &lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;contracts/PaymentVerifier.sol&lt;/code&gt; file and add the following code snippet to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract PaymentVerifier {
    event PaymentVerified(address indexed to, uint256 amount, uint256 srcChainId, bytes32 txHash);

    function verifyPayment(address to, uint256 amount, uint256 srcChainId, bytes32 txHash) external {
        // perform verification steps
        emit PaymentVerified(to, amount, srcChainId, txHash);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This contract doesn't perform a full cross-chain verification on its own. It acts as a receiver for cross-chain data, and usually, a relayer or a middleware service invokes the &lt;code&gt;verifyPayment&lt;/code&gt; method of the contract. This method expects the transaction receiver's address (&lt;code&gt;to&lt;/code&gt;), amount, source chain ID (&lt;code&gt;srcChainId&lt;/code&gt;), and the transaction hash (&lt;code&gt;txHash&lt;/code&gt;). These fields will be supplied by the relayer while invoking the contract. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;txHash&lt;/code&gt; refers to the on-chain transaction hash and can be used to perform additional transaction checks before emitting the &lt;code&gt;PaymentVerified&lt;/code&gt; event. For this tutorial, the smart contract emits the event without any checks.&lt;/p&gt;

&lt;p&gt;Note that in a real-world system, the &lt;code&gt;PaymentVerifier&lt;/code&gt; contract can be extended to include more extensive verification checks, such as validating signatures and cryptographic proofs. &lt;/p&gt;

&lt;h3&gt;
  
  
  Defining Scripts to Deploy the Smart Contracts
&lt;/h3&gt;

&lt;p&gt;Now that you've defined the smart contracts, you need to deploy them to &lt;a href="https://www.alchemy.com/overviews/what-are-testnets" rel="noopener noreferrer"&gt;test blockchain networks (testnets)&lt;/a&gt; before you can use them. &lt;/p&gt;

&lt;p&gt;To deploy the smart contracts, you can use a &lt;code&gt;node&lt;/code&gt; script that uses the &lt;code&gt;hardhat&lt;/code&gt; SDK to deploy the smart contract and print its address. To deploy the &lt;code&gt;CrossChainPayment&lt;/code&gt; contract, create a &lt;code&gt;scripts/deploy_crosschain.js&lt;/code&gt; script and add the following contents to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CrossChainPayment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForDeployment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contract deployed to:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Hardhat SDK creates an instance of the Ethers &lt;a href="https://docs.ethers.org/v5/api/contract/contract-factory/" rel="noopener noreferrer"&gt;ContractFactory&lt;/a&gt; to convert the &lt;code&gt;CrossChainPayment&lt;/code&gt; solidity contract into &lt;a href="https://blog.chain.link/what-are-abi-and-bytecode-in-solidity/" rel="noopener noreferrer"&gt;bytecode&lt;/a&gt; and deploys it on the blockchain network. &lt;/p&gt;

&lt;p&gt;Before using the script, you need to make sure that the network is configured under &lt;code&gt;hardhat.config.js&lt;/code&gt;. You also need to specify the network name as a CLI parameter while using the script. More on this in a later section. &lt;/p&gt;

&lt;p&gt;Similarly, to deploy the &lt;code&gt;PaymentVerifier&lt;/code&gt; contract, create a &lt;code&gt;scripts/deploy_paymentverifier.js&lt;/code&gt; file and add the following contents to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PaymentVerifier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForDeployment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contract deployed to:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script converts the &lt;code&gt;PaymentVerifier&lt;/code&gt; contract into bytecode and deploys it. Notice that both the contract deployment scripts are quite similar, and you could also parameterize the script and pass the contract name as a CLI argument.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying the Smart Contracts to testnets
&lt;/h3&gt;

&lt;p&gt;This tutorial uses the &lt;a href="https://sepolia.etherscan.io/" rel="noopener noreferrer"&gt;Sepolia&lt;/a&gt; and &lt;a href="https://holesky.etherscan.io/" rel="noopener noreferrer"&gt;Holesky&lt;/a&gt; testnets. Because deploying a smart contract to a &lt;a href="https://www.web3.university/tracks/create-a-smart-contract/what-is-gas-and-how-is-it-used" rel="noopener noreferrer"&gt;network requires gas&lt;/a&gt;, make sure to fund your wallet with tokens using a faucet like Google Cloud's Ethereum &lt;a href="https://cloud.google.com/application/web3/faucet/ethereum/holesky" rel="noopener noreferrer"&gt;Holešky&lt;/a&gt; or &lt;a href="https://cloud.google.com/application/web3/faucet/ethereum/sepolia" rel="noopener noreferrer"&gt;Sepolia Faucet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before deploying the smart contracts, you need to configure the desired testnets in the &lt;code&gt;hardhat.config.js&lt;/code&gt; file. Update the contents of the &lt;code&gt;hardhat.config.js&lt;/code&gt; file with the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nomicfoundation/hardhat-toolbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;solidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.8.20&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sepolia&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SEPOLIA_RPC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;11155111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;holesky&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HOLESKY_RPC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;17000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet updates the &lt;code&gt;network&lt;/code&gt; configuration to add &lt;code&gt;sepolia&lt;/code&gt; and &lt;code&gt;holesky&lt;/code&gt; testnets. Notice that the config file uses &lt;code&gt;SEPOLIA_RPC&lt;/code&gt;, &lt;code&gt;HOLESKY_RPC&lt;/code&gt;, and &lt;code&gt;PRIVATE_KEY&lt;/code&gt; environment variables. To configure environment variables, create a &lt;code&gt;.env&lt;/code&gt; file in the project's root and add the following contents to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY=&amp;lt;YOUR_META_MASK_PRIVATE_KEY&amp;gt;
SEPOLIA_RPC=&amp;lt;YOUR_ALCHEMY_SEPOLOIA_TEST_NET_HTTPS_RPC_URL&amp;gt;
SEPOLIA_WSS=&amp;lt;YOUR_ALCHEMY_SEPOLOIA_TEST_NET_WSS_RPC_URL&amp;gt;
HOLESKY_RPC=&amp;lt;YOUR_ALCHEMY_HOLESKY_TEST_NET_HTTPS_RPC_URL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;YOUR_META_MASK_PRIVATE_KEY&amp;gt;&lt;/code&gt; with the &lt;a href="https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/" rel="noopener noreferrer"&gt;Metamask wallet's private key&lt;/a&gt; obtained earlier. Replace &lt;code&gt;&amp;lt;YOUR_ALCHEMY_SEPOLOIA_TEST_NET_HTTPS_RPC_URL&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;YOUR_ALCHEMY_HOLESKY_TEST_NET_HTTPS_RPC_URL&amp;gt;&lt;/code&gt; with your HTTPS RPC URL from the Alchemy dashboard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jl1zdfouvcwo0snnmwe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jl1zdfouvcwo0snnmwe.png" alt="Obtain RPC URLs from Alchemy" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, make sure you replace &lt;code&gt;&amp;lt;YOUR_ALCHEMY_SEPOLOIA_TEST_NET_WSS_RPC_URL&amp;gt;&lt;/code&gt; with the WebSocket (WSS) RPC URL obtained from the Alchemy dashboard.&lt;/p&gt;

&lt;p&gt;Now that your environment variables and Hardhat configuration are set up, you can deploy the contracts. Either of these chains can be used as a source or destination for a transaction, so you need to deploy &lt;code&gt;PaymentVerifier&lt;/code&gt; and &lt;code&gt;CrossChainPayment&lt;/code&gt; contracts to both Sepolia and Holesky chains.&lt;/p&gt;

&lt;p&gt;Execute the following command to deploy the &lt;code&gt;CrossChainPayment&lt;/code&gt; to the Holesky chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat run scripts/deploy_crosschain.js &lt;span class="nt"&gt;--network&lt;/span&gt; holesky
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might take a few seconds for the contract to deploy, and it outputs the contract address like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Contract deployed to: 0x09292e7C53697DFcdBA3c51425bb7e36d7F6Ef2a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the contract address and deploy the &lt;code&gt;PaymentVerifier&lt;/code&gt; contract to the Holesky chain by executing the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat run scripts/deploy_paymentverifier.js &lt;span class="nt"&gt;--network&lt;/span&gt; holesky
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, deploy the &lt;code&gt;CrossChainPayment&lt;/code&gt; to the Sepolia chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat run scripts/deploy_crosschain.js &lt;span class="nt"&gt;--network&lt;/span&gt; sepolia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, deploy the &lt;code&gt;PaymentVerifier&lt;/code&gt; to the Sepolia chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat run scripts/deploy_paymentverifier.js &lt;span class="nt"&gt;--network&lt;/span&gt; sepolia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to save all the contract addresses as you will need them while defining the relay script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the Relay Script
&lt;/h3&gt;

&lt;p&gt;Now that the smart contracts are defined, you need to define a relay script that will listen for &lt;code&gt;PaymentSent&lt;/code&gt; events on the source chain. When it finds a &lt;code&gt;PaymentSent&lt;/code&gt; event, it matches the destination chain ID and triggers the &lt;code&gt;verifyPayment&lt;/code&gt; smart contract method on the destination chain.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;scripts/relay.js&lt;/code&gt; file and add the following code snippet to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WebSocketProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JsonRpcProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Wallet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Use WebSocket for Sepolia (where we're listening for events)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SEPOLIA_WSS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SEPOLIA_WSS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HOLESKY_RPC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HOLESKY_RPC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SEPOLIA_CONTRACT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;YOUR_CROSS_PAYMENT_SEPOLIA_ADDRESS&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HOLESKY_VERIFIER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;YOUR_PAYMENT_VERIFIER_HOLESKY_ADDRESS&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;eventAbi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;event PaymentSent(address indexed from, address indexed to, uint256 amount, uint256 chainId)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verifierAbi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function verifyPayment(address to, uint256 amount, uint256 srcChainId, bytes32 txHash)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startRelayer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Use WebSocketProvider for event monitoring&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sepoliaProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocketProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SEPOLIA_WSS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;holeskyProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JsonRpcProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HOLESKY_RPC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Wallet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;holeskyProvider&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sourceContract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SEPOLIA_CONTRACT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventAbi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sepoliaProvider&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HOLESKY_VERIFIER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;verifierAbi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Relayer is watching for events on Sepolia via WebSocket...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set up reconnection logic&lt;/span&gt;
    &lt;span class="nx"&gt;sepoliaProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;websocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`WebSocket connection closed with code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Reconnecting...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startRelayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Listen for events using WebSocket&lt;/span&gt;
    &lt;span class="nx"&gt;sourceContract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PaymentSent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PaymentSent Detected:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;chainId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;17000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Skipping non-Holesky destination.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Get transaction hash from event and ensure it's in bytes32 format&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;txHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transactionHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;verifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verifyPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
                &lt;span class="mi"&gt;11155111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nx"&gt;txHash&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Verification TX sent:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error verifying payment:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error details:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Handle process termination&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGINT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Closing WebSocket connection...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sepoliaProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// In case of connection errors, restart the relayer&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;startRelayer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error starting relayer:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startRelayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To interact with the Sepolia and Holesky chains, this code creates an instance of the &lt;a href="https://docs.ethers.org/v5/api/providers/jsonrpc-provider/" rel="noopener noreferrer"&gt;JsonRpcProvider&lt;/a&gt;. The relay script assumes that the transaction will be initiated on the Sepolia chain and starts listening for the &lt;code&gt;PaymentSent&lt;/code&gt; events on this chain. It sets the Holesky chain as the destination chain, creates an instance of the &lt;code&gt;PaymentVerifier&lt;/code&gt; contract deployed on it, and invokes the &lt;code&gt;verifyPayment&lt;/code&gt; method using the payload received in the &lt;code&gt;PaymentSent&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;This setup enables blockchain interoperability by bridging event data between two separate chains. It captures transactions on the source chain (Sepolia) and triggers verification logic on the destination chain (Holesky), without requiring a built-in bridge or shared state between them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Cross-chain Interactions
&lt;/h3&gt;

&lt;p&gt;With smart contracts deployed to both Sepolia and Holesky chains and the relay scripts in place, you can test blockchain interoperability. The goal of testing is to verify the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initiate a cross-chain transaction on the Sepolia chain using the &lt;code&gt;sendPayment&lt;/code&gt; method defined in the &lt;code&gt;CrossChainPayment&lt;/code&gt;. Once the transaction is complete, you will receive a &lt;code&gt;ContractTransactionResponse&lt;/code&gt; confirming the successful completion of the transaction.&lt;/li&gt;
&lt;li&gt;Within a few seconds of completion, the relay script should receive a &lt;code&gt;PaymentSent&lt;/code&gt; event from the &lt;code&gt;CrossChainPayment&lt;/code&gt; contract deployed on the Sepolia chain. The script should invoke the &lt;code&gt;verifyPayment&lt;/code&gt; method defined in the &lt;code&gt;PaymentVerifier&lt;/code&gt; contract deployed on the Holesky chain.&lt;/li&gt;
&lt;li&gt;On invocation, the &lt;code&gt;PaymentVerifier&lt;/code&gt; contract deployed on the Holesky chain should verify the transaction and return a successful response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before you begin testing, start the relay script in a new terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Execute this command in the project's root directory&lt;/span&gt;
node scripts/relay.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code starts the relay script, which listens for events on the Sepolia chain.&lt;/p&gt;

&lt;p&gt;To initiate a transaction on the Sepolia chain, start the &lt;code&gt;hardhat&lt;/code&gt; console for the &lt;code&gt;sepolia&lt;/code&gt; network by executing the following command in the project's root in a separate terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Execute this in the project's root&lt;/span&gt;
npx hardhat console &lt;span class="nt"&gt;--network&lt;/span&gt; sepolia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command starts the &lt;code&gt;hardhat&lt;/code&gt; console, where you can execute smart contracts and perform transactions. To initiate a cross-chain payment, paste the following script in the &lt;code&gt;hardhat&lt;/code&gt; console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get ethers from Hardhat runtime&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Load your deployed contract&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CrossChainPayment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x45d88f6DD0f0eDB69C563233Be73458c9980b519&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Send payment&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0x11ddd4b07B095802B537267358fB8Eb954B29d99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;// Recipient&lt;/span&gt;
  &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;                              &lt;span class="c1"&gt;// Amount&lt;/span&gt;
  &lt;span class="mi"&gt;17000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                                                   &lt;span class="c1"&gt;// Destination Chain ID (Holešky)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;                    &lt;span class="c1"&gt;// Payment value&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that if the terminal prompts you to confirm pasting multiple lines of code, click &lt;strong&gt;Paste&lt;/strong&gt; to confirm the action. Once you paste the code and press &lt;strong&gt;Enter&lt;/strong&gt;, you will receive a &lt;code&gt;ContractTransactionResponse&lt;/code&gt; confirming that the transaction was successful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ContractTransactionResponse {
  provider: HardhatEthersProvider {
    _hardhatProvider: LazyInitializationProviderAdapter {
      _providerFactory: [AsyncFunction (anonymous)],
      _emitter: [EventEmitter],
      _initializingPromise: [Promise],
      provider: [BackwardsCompatibilityProviderAdapter]
    },
    _networkName: 'sepolia',
    _blockListeners: [],
    _transactionHashListeners: Map(0) {},
    _eventListeners: []
  },
  blockNumber: null,
  blockHash: null,
  index: undefined,
  hash: '0xa2bd160eb0bfde7b1eadbde6c3a1c3a19f876ed5e8731e0d32d582628ba5e361',
  type: 2,
  to: '0x45d88f6DD0f0eDB69C563233Be73458c9980b519',
  from: '0xcD0AAcf118B43C0878D90886f0e1D54D043CF726',
  nonce: 7,
  gasLimit: 25215n,
  gasPrice: 55068367n,
  maxPriorityFeePerGas: 50000000n,
  maxFeePerGas: 55068367n,
  maxFeePerBlobGas: null,
  data: '0x8d82e72f00000000000000000000000011ddd4b07b095802b537267358fb8eb954b29d9900000000000000000000000000000000000000000000000000038d7ea4c680000000000000000000000000000000000000000000000000000000000000004268',
  value: 1000000000000000n,
  chainId: 11155111n,
  signature: Signature { r: "0x9c0bc7dd319671a3bf13c09e3d0b7398529fe0805055a86ecb41fc7a0a2c76f8", s: "0x047fcab2b6594f02d3fa8b3d0a00e92364b8c1a41713126cd2974bc15d00dd52", yParity: 0, networkV: null },
  accessList: [],
  blobVersionedHashes: null
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response contains details about the executed transaction, including the transaction hash (&lt;code&gt;hash&lt;/code&gt;), the sender's address (&lt;code&gt;from&lt;/code&gt;), the receiver's address (&lt;code&gt;to&lt;/code&gt;), and the hashed transaction payload (&lt;code&gt;data&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Head back to the relay script's terminal window, and within a few seconds, you should see a &lt;code&gt;PaymentSent&lt;/code&gt; event log printed in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PaymentSent Detected:
{
  from: '0xcD0AAcf118B43C0878D90886f0e1D54D043CF726',
  to: '0x11ddd4b07B095802B537267358fB8Eb954B29d99',
  amount: '1000000000000000',
  chainId: 17000n
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the &lt;code&gt;from&lt;/code&gt; and &lt;code&gt;to&lt;/code&gt; addresses in the event match the addresses received in the &lt;code&gt;ContractTransactionResponse&lt;/code&gt;. The relay script will invoke the &lt;code&gt;verifyPayment&lt;/code&gt; contract on the Holesky chain, and within a few seconds, a transaction verification log will be printed in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Verification TX sent: 0xb034b9bcd67eb3b58615fcdcd3704df70f75608bda16c1f2a454dc0f200a14dd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you learned how to achieve blockchain interoperability by building smart contracts using Solidity and Hardhat. Smart contracts can be used to initiate cross-chain transactions and verify them based on preset rules. This lets developers connect and share data between isolated blockchains, helping them build innovative applications.&lt;/p&gt;

&lt;p&gt;However, developing extensive verification checks to handle different scenarios relating to fraud, settlement, and compliance can be challenging for developers. With &lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt;, developers can focus on their core application logic, whether on-chain or off-chain, while relying on Rapyd to handle the complexity of compliance, identity verification, and secure settlement. More than just a complementary tool, Rapyd serves as your fiat bridge and compliance co-pilot by simplifying off-chain infrastructure, allowing teams to focus on delivering innovative, seamless, and scalable payment experiences faster. &lt;/p&gt;

&lt;p&gt;Experiment with the &lt;a href="https://docs.rapyd.net/en/api-reference.html" rel="noopener noreferrer"&gt;Rapyd API&lt;/a&gt; and the &lt;a href="https://github.com/Rapyd-Samples/rapyd-starter-blockhain" rel="noopener noreferrer"&gt;code used in this tutorial&lt;/a&gt; to discover how Rapyd can offer you the best in building an interoperable payment system.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Creator Economy: How to Manage Royalties, Payouts, and Subscriptions with Rapyd</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Tue, 08 Jul 2025 09:00:00 +0000</pubDate>
      <link>https://dev.to/rapyd/creator-economy-how-to-manage-royalties-payouts-and-subscriptions-with-rapyd-test-3i81</link>
      <guid>https://dev.to/rapyd/creator-economy-how-to-manage-royalties-payouts-and-subscriptions-with-rapyd-test-3i81</guid>
      <description>&lt;p&gt;By: &lt;strong&gt;Gourav Bais&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The creator economy is all about the creation, collection, distribution, and monetization of content, skills, or products. Today's creators—whether YouTubers, streamers, educators, or musicians—are entrepreneurs. And behind every piece of digital content, there's usually an overlooked task: managing payments.&lt;/p&gt;

&lt;p&gt;Creators have to juggle multiple income streams, including ad revenue, brand deals, subscriptions, affiliate commissions, digital product sales, brand partnerships, and direct fan contributions. Managing this mix means dealing with royalties, fluctuating transaction fees, and cross-border payouts. Creators need a payment system that simplifies operations, supports global subscriptions, and makes it easy to pay collaborators and affiliates.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn how &lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt; can help creators manage payments, receive international transactions, and simplify financial operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Payment Requirements in the Creator Economy
&lt;/h2&gt;

&lt;p&gt;Managing payments isn't just about moving money from point A to B; it's also about how the transfer happens: the speed, cost, currency, compliance, and overall user experience. Let's take a look at the core payment requirements that define how financial transactions work in the creator economy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Royalty Payments
&lt;/h3&gt;

&lt;p&gt;Royalty payments can be complicated for creators collaborating on podcasts, music, or shared ad revenue. One of the biggest challenges is tracking revenue sources across platforms and ensuring everyone gets their fair share. Delays or errors in royalty distribution can damage trust and often lead to disputes when multiple parties are involved across various locations.&lt;/p&gt;

&lt;p&gt;Clear, reliable royalty payments are key to maintaining long-term partnerships.&lt;/p&gt;

&lt;h3&gt;
  
  
  Affiliate Payouts
&lt;/h3&gt;

&lt;p&gt;Affiliate marketing allows influencers and creators to earn commissions by promoting products or services—but managing multiple affiliates with varying rates, performance metrics, and payout schedules is tricky. Tracking earnings and calculating variable commissions based on clicks, sales, and engagement can also become increasingly difficult at scale.&lt;/p&gt;

&lt;p&gt;To keep up, creators need tools that can not only automate payment calculations but also scale seamlessly as the affiliate networks expand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subscription Management
&lt;/h3&gt;

&lt;p&gt;Subscriptions provide a steady stream of income and build a loyal community. But handling subscription-based businesses is often challenging, especially when it comes to handling recurring payments and renewals across different regions and currencies.&lt;/p&gt;

&lt;p&gt;Subscriptions can also have multiple tiers, and each tier can have its own pricing, benefits, and audience. Managing these tiers requires a flexible system that can accommodate upgrades, downgrades, cancellations, and trial periods without disrupting the user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Using Rapyd APIs for Creator Payment Systems
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.rapyd.net/en/api-reference.html" rel="noopener noreferrer"&gt;Rapyd's suite of APIs&lt;/a&gt; provides the necessary infrastructure to scale payments efficiently, securely, and globally. It simplifies complex creator payment workflows by providing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplified integration for complex payment flows:&lt;/strong&gt; With a few lines of code, developers can integrate &lt;a href="https://www.rapyd.net/company/partners/" rel="noopener noreferrer"&gt;revenue sharing&lt;/a&gt;, &lt;a href="https://docs.rapyd.net/en/create-payout.html" rel="noopener noreferrer"&gt;automate payouts&lt;/a&gt;, and &lt;a href="https://docs.rapyd.net/en/subscriptions.html" rel="noopener noreferrer"&gt;manage subscription billing&lt;/a&gt;, all within a single platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support for global payouts in multiple currencies:&lt;/strong&gt; Rapyd supports payouts to &lt;a href="https://docs.rapyd.net/en/global.html" rel="noopener noreferrer"&gt;over 190 countries in more than 70 currencies&lt;/a&gt;. This helps creators send and receive payments globally without dealing with separate banking integrations or third-party processors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced security with tokenization and PCI compliance:&lt;/strong&gt; Rapyd provides security features like &lt;a href="https://docs.rapyd.net/en/external-network-tokenization.html" rel="noopener noreferrer"&gt;end-to-end tokenization&lt;/a&gt;, and sensitive data like card details is never stored on your servers. It also offers built-in &lt;a href="https://www.pcisecuritystandards.org/" rel="noopener noreferrer"&gt;PCI DSS&lt;/a&gt; compliance, helping platforms meet regulatory requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementing a Creator Payment System with the Rapyd API
&lt;/h2&gt;

&lt;p&gt;In this walkthrough, you'll learn how to build a basic creator payment system using Rapyd's API—covering royalties, affiliate payouts, and subscription management. We'll use Python and &lt;a href="https://fastapi.tiangolo.com/" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt; to bring it all together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before you begin, you'll need the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://dashboard.rapyd.net/sign-up" rel="noopener noreferrer"&gt;free Rapyd sandbox account&lt;/a&gt;. After registering, go to the &lt;strong&gt;Developers&lt;/strong&gt; section to find your access key and secret key—you'll need these to access Rapyd's APIs.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyyw5azjbwg14bpkwfz0.png" alt="Rapyd Developers page" width="800" height="401"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.python.org/downloads/release/python-390/" rel="noopener noreferrer"&gt;Python 3.8+&lt;/a&gt; installed on your system.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href="https://fastapi.tiangolo.com/" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt;, &lt;a href="https://www.uvicorn.org/" rel="noopener noreferrer"&gt;uvicorn&lt;/a&gt;, &lt;a href="https://pypi.org/project/requests/" rel="noopener noreferrer"&gt;Requests&lt;/a&gt;, and &lt;a href="https://pypi.org/project/python-dotenv/" rel="noopener noreferrer"&gt;python-dotenv&lt;/a&gt; libraries. You can install these with the following command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install fastapi uvicorn requests python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll also need to create a folder to store all your scripts and files. You can name it something like &lt;code&gt;creator_economy_rapyd_implementation&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Rapyd Authentication File
&lt;/h3&gt;

&lt;p&gt;Rapyd requires authentication to use its services. It's recommended that you use a &lt;code&gt;.env&lt;/code&gt; file to store all your credentials.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file inside your project folder and write the following lines of code, replacing &lt;code&gt;your_access_key_here&lt;/code&gt; and &lt;code&gt;your_secret_key_here&lt;/code&gt; with your actual credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RAPYD_ACCESS_KEY=your_access_key_here
RAPYD_SECRET_KEY=your_secret_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create another file named &lt;code&gt;rapyd_utils.py&lt;/code&gt; inside the same folder and import the necessary Python libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the libraries are imported, load the environment variables mentioned in the &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, load the Rapyd credentials and define the Rapyd URL you'll use to access their services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;access_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RAPYD_ACCESS_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RAPYD_SECRET_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://sandboxapi.rapyd.net&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've loaded your Rapyd credentials, it's time to implement Rapyd authentication with the following lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http_method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;body_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;separators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
    &lt;span class="n"&gt;to_sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;http_method&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;url_path&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;access_key&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;secret_key&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;body_str&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;to_sign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function generates a signature to validate each request made to Rapyd's API. To ensure the request is coming from a validated source, Rapyd needs each request to be signed using &lt;a href="https://docs.rapyd.net/en/request-signatures.html" rel="noopener noreferrer"&gt;HMAC-SHA256&lt;/a&gt;. This code uses the following variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;url_path&lt;/code&gt;: The endpoint being called, like &lt;code&gt;/v1/account/transfer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;salt&lt;/code&gt;: A randomly generated string to prevent replay attacks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timestamp&lt;/code&gt;: The current UNIX timestamp to ensure freshness.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;body&lt;/code&gt;: An optional request body for POST and PUT methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, define a function named &lt;code&gt;make_rapyd_request&lt;/code&gt; that will help you call various Rapyd services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_rapyd_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;access_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;access_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code can be broken down into the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It first creates a 12-byte random value (&lt;code&gt;salt&lt;/code&gt;) to ensure uniqueness.&lt;/li&gt;
&lt;li&gt;It then generates a &lt;code&gt;timestamp&lt;/code&gt; to prevent replay attacks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generate_signature()&lt;/code&gt; combines the HTTP method, path, salt, timestamp, and body to create a secure signature for authentication.&lt;/li&gt;
&lt;li&gt;The code sets up the request headers, including authentication and content type.&lt;/li&gt;
&lt;li&gt;It executes the HTTP request using the HTTP method and endpoint.&lt;/li&gt;
&lt;li&gt;Finally, the code parses the server's response into JSON.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all you need to do to make a request to Rapyd endpoints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an Rapyd API App
&lt;/h3&gt;

&lt;p&gt;Once the Rapyd utility script is ready, it's time to implement the main functionalities of a creator economy payment system.&lt;/p&gt;

&lt;p&gt;To start, you need to create &lt;code&gt;main.py&lt;/code&gt; inside your project folder. Your folder structure should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;creator_economy_rapyd_implementation/
│
├── main.py
├── rapyd_utils.py
└── .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import the necessary Python libraries as well as the FastAPI library for creating different payment facility endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rapyd_utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;make_rapyd_request&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, write the different data models that define and validate the expected JSON input for the endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ---------- MODELS ----------
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Collaborator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;wallet_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RoyaltyRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;creator_wallet_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;total_revenue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;collaborators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Collaborator&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AffiliateRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;affiliate_wallet_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;commission_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;sender_wallet_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;customer_email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;monthly&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four different data models are defined: &lt;code&gt;Collaborator&lt;/code&gt; defines an individual involved in royalty revenue sharing, and the remaining three data models define and validate the payment facilities in the creator economy app.&lt;/p&gt;

&lt;h4&gt;
  
  
  Royalty Payments
&lt;/h4&gt;

&lt;p&gt;Royalty payments are often recurring and variable, and they need to be distributed across multiple parties. To handle this efficiently, you need to build a system that supports accurate and timely royalty disbursements.&lt;/p&gt;

&lt;p&gt;In this section, you'll learn how to implement the first endpoint of the application for royalty payments. This is the foundation for handling complex, multiparty creator compensation.&lt;/p&gt;

&lt;p&gt;Add the following endpoint to your FastAPI application inside the &lt;code&gt;main.py&lt;/code&gt; file. This endpoint takes a list of collaborators and their revenue share, calculates each payout, and initiates the transfer to each collaborator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/royalty-payments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;distribute_royalties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RoyaltyRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;collab&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;collaborators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;payout_amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_revenue&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;collab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;beneficiary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ewallet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;collab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wallet_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;payout_amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sender&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ewallet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;creator_wallet_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;royalty&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_rapyd_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/v1/account/transfer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;collab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;payout_amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAILED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payouts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code uses the following variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data.collaborators&lt;/code&gt; calculates how much each collaborator should receive.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;round(..., 2)&lt;/code&gt; rounds off the obtained value up to two decimal points.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;beneficiary&lt;/code&gt; represents who gets the money.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sender&lt;/code&gt; is the creator paying the beneficiary.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;metadata&lt;/code&gt; is an optional tag to label this as a royalty payout.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;make_rapyd_request&lt;/code&gt; calls the Rapyd API to perform the transfer and returns a list of each collaborator, their payout, and the API status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This endpoint is designed to split the revenue among multiple collaborators based on predefined share percentages. Once the request is received, including the creator's wallet ID, total revenue amount, and a list of collaborators, it calculates the payout amount by multiplying the total revenue by their share. The revenue is then rounded off to two decimal places for currency precision, and a JSON body is prepared that includes the sender and receiver wallet IDs, amount, currency, and metadata, indicating this is a "royalty" type of transfer. Finally, it makes a POST request to the Rapyd &lt;code&gt;/v1/account/transfer&lt;/code&gt; endpoint for each collaborator using the &lt;code&gt;make_rapyd_request&lt;/code&gt; function.&lt;/p&gt;

&lt;h4&gt;
  
  
  Affiliate Payouts
&lt;/h4&gt;

&lt;p&gt;Now, let's implement an endpoint that pays a single affiliate based on the provided data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/affiliate-payout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_affiliate_payout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AffiliateRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;beneficiary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ewallet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;affiliate_wallet_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commission_amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sender&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ewallet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender_wallet_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;affiliate_commission&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_rapyd_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/v1/account/transfer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;body{...}&lt;/code&gt; variable is almost identical to the one in the &lt;code&gt;/royalty-payments&lt;/code&gt; endpoint, but with different metadata. &lt;code&gt;make_rapyd_request()&lt;/code&gt; performs and returns the result of the payout.&lt;/p&gt;

&lt;p&gt;This endpoint accepts a JSON payload containing the affiliate's wallet ID, commission amount, and sender's wallet ID. It then constructs a body similar to the previous endpoint, defining the beneficiary, sender, currency, and amount, and tags the metadata with &lt;code&gt;affiliate_commission&lt;/code&gt;. Finally, it makes a POST request to Rapyd's &lt;code&gt;/v1/account/transfer&lt;/code&gt; endpoint to transfer the commission from the sender's wallet to the affiliate's.&lt;/p&gt;

&lt;h4&gt;
  
  
  Managing Subscriptions
&lt;/h4&gt;

&lt;p&gt;Finally, let's implement the last endpoint for managing subscriptions. This endpoint implements a hosted payment link via Rapyd's &lt;code&gt;/v1/payment_links&lt;/code&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/create-subscription&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_subscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SubscriptionRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USD&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_email&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;interval&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subscription_tier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;premium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;make_rapyd_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/v1/payment_links&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redirect_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redirect_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following variables are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;interval&lt;/code&gt;, which defines recurring subscriptions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;metadata&lt;/code&gt;, which can be used to track tiers (basic, premium, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;make_rapyd_request&lt;/code&gt;, which returns a redirect URL that the frontend or customer can use to pay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This endpoint accepts the customer's email, the subscription amount, and the payment interval. Then, it builds a request body that includes the amount, currency, customer details, subscription interval, and optional metadata like the tier name ("premium"). Finally, the body is sent to Rapyd's &lt;code&gt;/v1/payment_links&lt;/code&gt; endpoint, which generates a hosted link that customers can visit to complete the subscription setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the Application
&lt;/h3&gt;

&lt;p&gt;Once you've written the code, all you have to do is run the FastAPI app using &lt;code&gt;uvicorn&lt;/code&gt; to access different endpoints. To do so, open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uvicorn main:app --reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts your FastAPI application, which can be accessed on &lt;a href="http://localhost:8000/docs" rel="noopener noreferrer"&gt;http://localhost:8000/docs&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05atyu8uf7qg6awafz4w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05atyu8uf7qg6awafz4w.png" alt="Creator payment app" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use curl commands to call the following endpoints: &lt;code&gt;/royalty-payments&lt;/code&gt;, &lt;code&gt;/affiliate-payout&lt;/code&gt;, and &lt;code&gt;/create-subscription&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  /royalty-payments
&lt;/h4&gt;

&lt;p&gt;This endpoint splits and distributes revenue among collaborators based on their share. To do this, you need to obtain a wallet ID (such as &lt;code&gt;ewallet_creator_123&lt;/code&gt;) from Rapyd. Every payment in the application—whether a royalty payout, affiliate commission, or subscription—depends on &lt;a href="https://docs.rapyd.net/en/rapyd-wallet.html" rel="noopener noreferrer"&gt;Rapyd Wallets&lt;/a&gt;, also known as ewallets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST http://localhost:8000/royalty-payments \
-H "Content-Type: application/json" \
-d '{
  "creator_wallet_id": "ewallet_creator_123",
  "total_revenue": 1000,
  "collaborators": [
    {
      "name": "Alice",
      "wallet_id": "ewallet_alice_001",
      "share": 0.5
    },
    {
      "name": "Bob",
      "wallet_id": "ewallet_bob_002",
      "share": 0.3
    },
    {
      "name": "Charlie",
      "wallet_id": "ewallet_charlie_003",
      "share": 0.2
    }
  ]
}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your output will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "payouts": [
    {
      "name": "Alice",
      "amount": 500.0,
      "status": "SUCCESS"
    },
    {
      "name": "Bob",
      "amount": 300.0,
      "status": "SUCCESS"
    },
    {
      "name": "Charlie",
      "amount": 200.0,
      "status": "SUCCESS"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint splits $1,000 USD in revenue into 50 percent, 30 percent, and 20 percent shares for Alice, Bob, and Charlie, respectively. Then, it initiates Rapyd transfers for each. The response confirms the transfer status for each payout.&lt;/p&gt;

&lt;h4&gt;
  
  
  /affiliate-payout
&lt;/h4&gt;

&lt;p&gt;This endpoint pays a commission to an affiliate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST http://localhost:8000/affiliate-payout \
-H "Content-Type: application/json" \
-d '{
  "affiliate_wallet_id": "ewallet_aff_007",
  "commission_amount": 120,
  "sender_wallet_id": "ewallet_creator_123"
}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your output will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": {
    "status": "SUCCESS",
    "message": "",
    "error_code": "",
    "response_code": "",
    "operation_id": "e4bc3f56-d40b-4cb4-a9e1-e5d18fc77b8e"
  },
  "data": {
    "id": "transfer_abc123xyz",
    "amount": 120,
    "currency": "USD",
    "status": "ACT",
    "beneficiary": {
      "ewallet": "ewallet_aff_007"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This endpoint transfers $120 USD from the creator's wallet to the affiliate's wallet. The &lt;code&gt;operation_id&lt;/code&gt; can be stored for logging or future reconciliation.&lt;/p&gt;

&lt;h4&gt;
  
  
  /create-subscription
&lt;/h4&gt;

&lt;p&gt;This endpoint creates a payment link for a customer to subscribe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST http://localhost:8000/create-subscription \
-H "Content-Type: application/json" \
-d '{
  "customer_email": "subscriber@example.com",
  "amount": 15.99,
  "interval": "monthly"
}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your output will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "redirect_url": "https://sandboxcheckout.rapyd.net?token=pl_8fc456a83e"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a hosted payment link. Once you click the URL, you'll be taken to a Rapyd-hosted checkout page where you can securely complete the subscription process using your preferred payment method.&lt;/p&gt;

&lt;p&gt;The API call allows customers to subscribe to a monthly plan priced at $15.99 USD. You can also use &lt;a href="https://docs.rapyd.net/en/subscription-webhooks.html" rel="noopener noreferrer"&gt;webhooks in Rapyd&lt;/a&gt; to monitor subscription lifecycle events like &lt;code&gt;subscription.created&lt;/code&gt;, &lt;code&gt;payment.completed&lt;/code&gt;, or &lt;code&gt;subscription.cancelled&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At this point, you've created an application that can manage royalties, payouts, and subscriptions with Rapyd. Congratulations! You can find the full code for this tutorial on &lt;a href="https://github.com/Rapyd-Samples/Creator_Economy_How_To_Manage_Royalties_Payouts_and_Subscriptions_with_Rapyd" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The financial side of content creation can be hard to manage, but the right tools can make it easier. &lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt; helps simplify payment operations so creators can spend less time on logistics and more time on creating.&lt;/p&gt;

&lt;p&gt;Rapyd is more than just a payment provider; it's an all-in-one fintech infrastructure that helps you move money with ease. Whether you're managing complex royalty splits, scaling affiliate payouts, or automating recurring subscriptions, Rapyd's APIs will help you build powerful, secure, and flexible payment systems quickly.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://docs.rapyd.net/en/developers.html" rel="noopener noreferrer"&gt;Client Portal&lt;/a&gt; or play around with &lt;a href="https://docs.rapyd.net/en/environments.html" rel="noopener noreferrer"&gt;Rapyd's Sandbox&lt;/a&gt;—you'll quickly see how easy it is to streamline payments and simplify your workflow with Rapyd.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mastering Compliance API Integrations: A Developer's Guide to AI-Powered KYC, AML, &amp; Fraud Prevention</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Thu, 03 Jul 2025 12:42:31 +0000</pubDate>
      <link>https://dev.to/rapyd/mastering-compliance-api-integrations-a-developers-guide-to-ai-powered-kyc-aml-fraud-4e06</link>
      <guid>https://dev.to/rapyd/mastering-compliance-api-integrations-a-developers-guide-to-ai-powered-kyc-aml-fraud-4e06</guid>
      <description>&lt;p&gt;The rapid evolution of AI is fundamentally reshaping regulatory compliance in payments. For us developers on the front lines, this transformation often manifests through the integration of sophisticated &lt;strong&gt;AI-powered APIs&lt;/strong&gt; for critical functions like &lt;strong&gt;Know Your Customer (KYC)&lt;/strong&gt;, &lt;strong&gt;Anti-Money Laundering (AML)&lt;/strong&gt;, and real-time &lt;strong&gt;fraud prevention&lt;/strong&gt;. This isn't just about automation; it's about embedding intelligent decision-making directly into your payment flows, making your systems smarter and more resilient.&lt;/p&gt;

&lt;p&gt;This article, part of our series on AI in payments compliance (and building on our strategic overview), serves as your direct playbook for navigating the world of compliance API integrations.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Golden Nugget: APIs as Your Compliance Backbone
&lt;/h2&gt;

&lt;p&gt;Here's the core insight for us as developers: you don't need to become an AI expert or a compliance lawyer. Instead, your superpower lies in effectively integrating and orchestrating best-in-class, specialized compliance APIs. These services, often powered by advanced machine learning, handle the heavy lifting of data analysis, risk scoring, and pattern recognition, providing you with clear, actionable outputs you can consume directly in your code. This is where the magic happens – leveraging intelligence without building it from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. API Selection Criteria: Choosing Your Compliance Partner Wisely
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of code, let's talk strategy. What makes a compliance API robust and reliable for a production payment system?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Global Coverage &amp;amp; Data Sources:&lt;/strong&gt; Does it cover the jurisdictions where your users operate? Leading providers like &lt;strong&gt;ComplyCube, Uniify, Jumio, and Onfido&lt;/strong&gt; offer extensive global identity verification and screening. Don't get caught out by regional limitations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Processing &amp;amp; Latency:&lt;/strong&gt; For payment transactions, every millisecond counts. Prioritize APIs designed for near-instant responses to minimize friction in user journeys and prevent real-time fraud. Think about your SLAs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Enrichment Capabilities:&lt;/strong&gt; Beyond simple validation, can the API enrich data? For example, can it provide a risk score based on an IP address, email, or device fingerprint, as offered by solutions like &lt;strong&gt;SEON&lt;/strong&gt; or &lt;strong&gt;IPQualityScore&lt;/strong&gt;? This extra context is invaluable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation Quality (Critically Important!):&lt;/strong&gt; This is paramount. Comprehensive, clear, and interactive API documentation (e.g., Swagger UI/OpenAPI spec) with robust code examples in multiple languages drastically reduces integration time and errors. If the docs are poor, run!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox Environments &amp;amp; Support:&lt;/strong&gt; A robust, feature-rich sandbox for development and testing, coupled with responsive developer support channels, are non-negotiable. Test, test, test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing Models:&lt;/strong&gt; Understand if it's per-API call, tiered, or based on usage volume. Model costs against your projected transaction volumes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Integration Patterns: Weaving Compliance into Your Workflow
&lt;/h2&gt;

&lt;p&gt;Compliance checks need to happen at various, often distinct, points in the payment lifecycle. Understanding the right integration pattern for each is key.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;
  
  
  Onboarding (KYC/KYB): The Asynchronous Dance
&lt;/h3&gt;

&lt;p&gt;Integrate identity and business verification APIs during user or merchant signup. This is often an asynchronous process, where initial checks trigger background processes, allowing the user to continue while comprehensive checks complete.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pattern: Request-Response with Asynchronous Callbacks (Webhooks).&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pseudocode for KYC Onboarding Flow
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initiate_kyc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;transaction_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_unique_id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# Send request to compliance API with your webhook endpoint
&lt;/span&gt;    &lt;span class="n"&gt;compliance_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_kyc_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;callback_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[https://your-domain.com/webhooks/kyc-status](https://your-domain.com/webhooks/kyc-status)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transactionId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;save_pending_kyc_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PENDING_REVIEW&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transactionId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Your webhook endpoint: Called by compliance API when status changes
&lt;/span&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/webhooks/kyc-status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_kyc_webhook&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
    &lt;span class="n"&gt;transaction_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transactionId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;details&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# IMPORTANT: Validate webhook signature here!
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;validate_webhook_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;X-Signature&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;YOUR_WEBHOOK_SECRET&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Invalid signature&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;

    &lt;span class="nf"&gt;update_kyc_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;APPROVED&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;activate_user_account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="c1"&gt;# Acknowledge receipt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An initial API call validates basic info, and a webhook might notify your system when comprehensive background checks (e.g., identity verification, sanctions screening) are complete.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h3&gt;
  
  
  Transaction Processing (AML/Fraud): The Real-Time Gatekeeper
&lt;/h3&gt;

&lt;p&gt;Implement real-time calls to fraud prevention and AML APIs &lt;em&gt;before&lt;/em&gt; a transaction is authorized. These systems analyze transactional data (amount, location, payment method, card BIN) and behavioral signals to generate a risk score.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pattern: Synchronous Request-Response.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pseudocode for Real-time Transaction Fraud Check
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment_details&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fraud_check_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;fraud_api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment_details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fraud_check_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;riskScore&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;THRESHOLD_REJECT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REJECTED&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;High fraud risk&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fraud_check_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;riskScore&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;THRESHOLD_REVIEW&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Log for manual review, but allow transaction to proceed conditionally
&lt;/span&gt;            &lt;span class="nf"&gt;log_for_manual_review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment_details&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fraud_check_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Proceed with payment authorization
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;payment_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment_details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Implement graceful fallback or block transaction
&lt;/span&gt;        &lt;span class="nf"&gt;handle_fraud_api_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment_details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ERROR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Fraud check failed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API call should be fast enough not to introduce significant latency into the checkout flow (aim for single-digit milliseconds). &lt;strong&gt;Google's reCAPTCHA Fraud Prevention&lt;/strong&gt; and &lt;strong&gt;SEON&lt;/strong&gt; are excellent examples of solutions for real-time risk assessments.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;h3&gt;
  
  
  Post-Transaction Monitoring: The Background Watcher
&lt;/h3&gt;

&lt;p&gt;For ongoing AML and suspicious activity detection, integrate APIs that monitor transaction streams or user behavior over time. This is less about blocking and more about continuous vigilance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pattern: Event-Driven Architecture with Webhooks.&lt;/strong&gt; Your system sends transaction data (or batches of data) to a monitoring service, and that service uses webhooks to notify your application of any suspicious activity or alerts that require review. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Data Flow &amp;amp; Security: Protecting Sensitive Information is Non-Negotiable
&lt;/h2&gt;

&lt;p&gt;You're dealing with highly sensitive financial and personal data. &lt;strong&gt;Security is not an afterthought; it's fundamental&lt;/strong&gt; to every line of code you write.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure Transmission:&lt;/strong&gt; Always, always, &lt;em&gt;always&lt;/em&gt; use &lt;strong&gt;HTTPS/TLS&lt;/strong&gt; for all API communications. No excuses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication &amp;amp; Authorization:&lt;/strong&gt; Implement robust API key management, OAuth 2.0, or OpenID Connect. Store API keys securely (e.g., in environment variables, secret management services like AWS Secrets Manager or HashiCorp Vault), never hardcode them. Rotate keys regularly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Minimization:&lt;/strong&gt; Only send the &lt;em&gt;necessary&lt;/em&gt; data to the API. Avoid transmitting sensitive information that isn't required for the specific compliance check. The less data you send, the less surface area for compromise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption &amp;amp; Tokenization:&lt;/strong&gt; Where possible, &lt;strong&gt;tokenize or encrypt&lt;/strong&gt; sensitive data (e.g., payment card numbers, personally identifiable information (PII)) before sending it to third-party APIs. This limits exposure even if a breach occurs. Think of the Payment Card Industry Data Security Standard (PCI DSS) implications here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input/Output Schemas:&lt;/strong&gt; Understand the exact data formats (JSON, XML) and required fields for API requests and responses. Implement strong input &lt;strong&gt;validation&lt;/strong&gt; on &lt;em&gt;all&lt;/em&gt; data sent to and received from APIs to prevent injection attacks or unexpected behavior.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Error Handling &amp;amp; Fallbacks: Building Resilient Systems
&lt;/h2&gt;

&lt;p&gt;External APIs can fail, encounter rate limits, or return unexpected errors. Your integration must be resilient, just like any mission-critical system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP Status Codes:&lt;/strong&gt; Know your common API error codes (e.g., &lt;code&gt;400 Bad Request&lt;/code&gt;, &lt;code&gt;401 Unauthorized&lt;/code&gt;, &lt;code&gt;403 Forbidden&lt;/code&gt;, &lt;code&gt;429 Too Many Requests&lt;/code&gt;, &lt;code&gt;500 Internal Server Error&lt;/code&gt;, &lt;code&gt;503 Service Unavailable&lt;/code&gt;). Each has a specific meaning and demands a specific response from your code.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rate Limit Management:&lt;/strong&gt; Implement client-side rate limiting or use strategies like &lt;strong&gt;exponential backoff with jitter&lt;/strong&gt; for retries when encountering &lt;code&gt;429 Too Many Requests&lt;/code&gt;. The &lt;code&gt;Retry-After&lt;/code&gt; HTTP header is your friend here, indicating when you can safely retry.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt; &lt;span class="c1"&gt;# Assuming 'requests' library for HTTP calls
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_api_call_with_retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_client_method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;api_client_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# Raises HTTPError for bad responses (4xx or 5xx)
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Too Many Requests
&lt;/span&gt;                &lt;span class="n"&gt;wait_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Exponential backoff + jitter
&lt;/span&gt;                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rate limit hit. Retrying in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;wait_time&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; seconds...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wait_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="c1"&gt;# Re-raise other HTTP errors
&lt;/span&gt;        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;ConnectionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Handle network issues more gracefully
&lt;/span&gt;            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Connection error. Retrying in 1 second...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Max retries exceeded for API call.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Circuit Breakers &amp;amp; Timeouts:&lt;/strong&gt; Implement &lt;strong&gt;circuit breakers&lt;/strong&gt; to prevent cascading failures if an API becomes unresponsive. Set appropriate, aggressive timeouts for API calls to avoid hanging requests. Libraries like Hystrix (Java) or Polly (.NET) provide patterns for this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fallback Mechanisms:&lt;/strong&gt; For non-critical checks, consider &lt;strong&gt;graceful degradation&lt;/strong&gt;. What happens if a fraud API is down? Can you temporarily switch to a more conservative internal rule set, or queue checks for later processing when the service recovers? Always have a plan B.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Webhooks &amp;amp; Event-Driven Architecture: Powering Asynchronous Processing
&lt;/h2&gt;

&lt;p&gt;For ongoing monitoring and long-running processes (like comprehensive AML screening or adverse media checks), webhooks are indispensable for an &lt;strong&gt;event-driven architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Listen for Events:&lt;/strong&gt; Your application exposes a secure endpoint that the compliance API can call when an event occurs (e.g., a screening result is ready, a fraud alert is triggered).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Validate Webhook Signatures:&lt;/strong&gt; &lt;strong&gt;Always, always verify the signature of incoming webhooks.&lt;/strong&gt; This ensures the webhook genuinely originates from the compliance provider and hasn't been tampered with by a malicious actor.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_webhook_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Example for HMAC-SHA256 signature validation
&lt;/span&gt;    &lt;span class="c1"&gt;# The specific header name and signature generation method vary by API provider.
&lt;/span&gt;    &lt;span class="n"&gt;expected_signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;request_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;# Use a constant-time comparison to prevent timing attacks
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected_signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature_header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Idempotency:&lt;/strong&gt; Design your webhook handlers to be &lt;strong&gt;idempotent&lt;/strong&gt;. This means processing the same event multiple times won't cause adverse effects, as webhooks can sometimes be delivered more than once due to network issues or retries. Store a unique event ID and check if it's already processed before taking action.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Testing Methodologies: Ensuring Compliance and Performance Under Pressure
&lt;/h2&gt;

&lt;p&gt;Thorough testing is paramount for compliance APIs, given the financial and regulatory stakes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox Environments:&lt;/strong&gt; Conduct initial development and integration testing exclusively in the API provider's sandbox. This is your safe playpen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit &amp;amp; Integration Tests:&lt;/strong&gt; Write comprehensive unit tests for your API integration logic, verifying request formatting, response parsing, and error handling. Then, integration tests against the sandbox to confirm end-to-end flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance &amp;amp; Load Testing:&lt;/strong&gt; Simulate realistic high transaction volumes. Can your integration handle the anticipated load without bottlenecks? Does the compliance API meet your latency requirements under stress?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge Case Testing:&lt;/strong&gt; This is where you find the tricky bugs. Test scenarios like malformed data, very high/low transaction amounts, unusual geo-locations, and identity mismatches to ensure the API responds as expected and your code handles them gracefully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Audits:&lt;/strong&gt; Regularly conduct security audits and penetration tests on your integration points. This includes checking for API key exposure, data leakage, and potential for abuse.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Integrating AI-powered compliance APIs is rapidly becoming a fundamental skill set for modern payment developers. By meticulously selecting the right APIs, designing robust integration patterns, prioritizing data security, implementing resilient error handling, leveraging event-driven architectures, and rigorously testing your solutions, you can significantly enhance your payment gateway's security posture and regulatory adherence.&lt;/p&gt;

&lt;p&gt;This practical, API-first approach to AI implementation empowers you to build highly intelligent, adaptive, and compliant payment systems. It allows you to future-proof your solutions, moving beyond basic automation to truly intelligent, adaptive compliance that supports innovation rather than hindering it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What compliance APIs have &lt;em&gt;you&lt;/em&gt; found most effective in your projects? What integration challenges have you overcome? Share your experiences and insights in the comments below!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article is part of a series stemming from our comprehensive analysis: &lt;a href="https://community.rapyd.net/t/ai-for-regulatory-compliance-in-payments/59638" rel="noopener noreferrer"&gt;https://community.rapyd.net/t/ai-for-regulatory-compliance-in-payments/59638&lt;/a&gt; Explore the other articles in the series to dive deeper into Explainable AI (XAI) and MLOps for compliance!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>payments</category>
      <category>programming</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🗞 Rapyd Developer Newsletter: May 2025 🛠 Build Real-Time Payments with Rapyd’s Latest Tools</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Thu, 12 Jun 2025 15:15:41 +0000</pubDate>
      <link>https://dev.to/rapyd/rapyd-developer-newsletter-may-2025-build-real-time-payments-with-rapyds-latest-tools-4h40</link>
      <guid>https://dev.to/rapyd/rapyd-developer-newsletter-may-2025-build-real-time-payments-with-rapyds-latest-tools-4h40</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;💾 &lt;a href="https://docs.rapyd.net/en/api-changelog.html" rel="noopener noreferrer"&gt;New API &amp;amp; Product Updates&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Updated &lt;a href="https://docs.rapyd.net/en/api-changelog.html" rel="noopener noreferrer"&gt;API Changelog&lt;/a&gt; and &lt;a href="https://docs.rapyd.net/en/product-changelog.html" rel="noopener noreferrer"&gt;Product Changelog&lt;/a&gt; are now available.&lt;/li&gt;
&lt;li&gt;Be sure your integrations are up to date!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;⚡ &lt;a href="https://community.rapyd.net/t/real-time-payment-systems-how-to-build-instant-payment-solutions-with-rapyd/59779" rel="noopener noreferrer"&gt;Real-Time Payment Systems with Rapyd&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Design instant, intelligent payment experiences with Rapyd’s APIs. Our latest guide walks you through building real-time systems that scale with your business. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;🧩 &lt;a href="https://community.rapyd.net/t/fintech-apis-architecting-the-future-with-ai/59762" rel="noopener noreferrer"&gt;Fintech APIs: Architecting the Future with AI&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;From fraud prevention to customer service, discover how AI is reshaping payments. Explore strategies and real-world applications with Rapyd’s platform. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;🖥 &lt;a href="https://community.rapyd.net/t/pos-terminals-fintech-reinvented/59751" rel="noopener noreferrer"&gt;POS Terminals: Fintech Reinvented&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ensure your APIs are compliant with GDPR, PSD2, and global regulations. Get the tools and tips for secure, audit-ready development. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;🧾 &lt;a href="https://docs.rapyd.net/en/hosted-beneficiary-details-page.html" rel="noopener noreferrer"&gt;Simplify Crypto Payouts with Beneficiary Tokenization&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Easily generate a hosted page for beneficiary tokenization and enable USDC payouts. Check out the new docs and start building.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;💼 &lt;a href="https://docs.rapyd.net/en/merchant-settlement-report.html" rel="noopener noreferrer"&gt;Understand Wallet Balances with Merchant Reports&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;New updates to the Client Portal Guide now help you reconcile wallet balances and monitor transaction data.&lt;/p&gt;




&lt;p&gt;See you next month,&lt;br&gt;
The Rapyd Developer Community Team&lt;/p&gt;

&lt;p&gt;💡 We’d love to hear from you! Got an idea, tutorial, or topic you'd like to see covered? Just reply and let us know.&lt;/p&gt;

</description>
      <category>rapydnews</category>
      <category>fintech</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>From Gig to Cash‑Out Build &amp; Monetize Global Payouts</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Thu, 12 Jun 2025 09:00:00 +0000</pubDate>
      <link>https://dev.to/rapyd/from-gig-to-cash-out-build-monetize-global-payouts-1h1b</link>
      <guid>https://dev.to/rapyd/from-gig-to-cash-out-build-monetize-global-payouts-1h1b</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Gig platforms thrive on efficient cash-outs. Discover how to build this crucial revenue engine in an afternoon using Rapyd’s Disburse API and a &lt;a href="https://github.com/Rapyd-Samples/rapyd-basic-payroll-app-with-disburse" rel="noopener noreferrer"&gt;ready-to-fork repository&lt;/a&gt;. Turn payouts into profit, globally!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Micro‑Payment Opportunity is Massive
&lt;/h2&gt;

&lt;p&gt;The gig economy isn't just a trend; it's a powerhouse. With over &lt;strong&gt;435 million online gig workers worldwide&lt;/strong&gt;, the flow of earnings is staggering. Yet, many burgeoning marketplaces and innovative side hustles still wrestle with the friction of manual payouts or the delays of traditional payroll systems.&lt;/p&gt;

&lt;p&gt;Here's the game-changer: &lt;strong&gt;instant payouts + strategic micro-fees = a win for everyone.&lt;/strong&gt; Workers gain immediate access to their hard-earned cash, fostering platform loyalty and stickiness. Simultaneously, the platform unlocks a scalable, automated revenue stream with every single transaction. It's time to tap into the immense potential of this micro-payment gold rush.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. API Monetization 101: Why Pay-Per-Use Wins for Gigs
&lt;/h2&gt;

&lt;p&gt;When integrating payments, monetization models come in various flavors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freemium:&lt;/strong&gt; Basic features free, advanced tiers paid.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription:&lt;/strong&gt; Recurring fees for platform access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay-Per-Use:&lt;/strong&gt; Charges based on transaction volume.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For gig economy payouts, &lt;strong&gt;pay-per-use&lt;/strong&gt;, especially when combined with a small surcharge for expedited ("instant") options, is the clear winner. The direct value exchange – worker receives funds, platform earns a small fee – makes it easily understandable and acceptable. Look at &lt;strong&gt;DoorDash's "Fast Pay," charging a modest $1.99&lt;/strong&gt; for quicker access to earnings. It's a proven model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Rapyd Disburse: Your Unified Gateway to Global Payouts
&lt;/h2&gt;

&lt;p&gt;Forget juggling multiple integrations and navigating complex banking regulations. &lt;strong&gt;Rapyd's Disburse API offers a single, powerful entry point to over 190 countries&lt;/strong&gt;, handling currency conversions (FX) seamlessly under the hood. Get instant access to sandbox API keys and start building without the usual payment infrastructure headaches. Focus on your platform's core value proposition, not the plumbing.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Architecture at a Glance
&lt;/h2&gt;

&lt;p&gt;Our example application boasts a straightforward, developer-friendly architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05i8fmh1r9u37y8zgwva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05i8fmh1r9u37y8zgwva.png" alt="Flow Diagram of the process" width="800" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; A sleek Next.js user interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Robust Next.js API routes for server-side logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; Reliable PostgreSQL for persistent data storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks:&lt;/strong&gt; Real-time event notifications from Rapyd.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fee Logic:&lt;/strong&gt; Simple, configurable fee calculation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Hands‑On: Building Your Monetized Payout System
&lt;/h2&gt;

&lt;p&gt;Let's get practical. Here's how to get this up and running:&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 Clone &amp;amp; Install
&lt;/h3&gt;

&lt;p&gt;Fire up your terminal and clone the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Rapyd-Samples/rapyd-basic-payroll-app-with-disburse.git
&lt;span class="nb"&gt;cd &lt;/span&gt;rapyd-basic-payroll-app-with-disburse
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.2 Configure Environment Variables
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env.local&lt;/code&gt; file and populate it with your Rapyd API credentials and desired fee structure:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```Code snippet&lt;br&gt;
RAPYD_API_KEY=YOUR_RAPYD_API_KEY&lt;br&gt;
RAPYD_SECRET_KEY=YOUR_RAPYD_SECRET_KEY&lt;br&gt;
FEE_FIXED=0.10&lt;br&gt;
FEE_PERCENT=0.01&lt;br&gt;
EXPRESS_PAYOUT_SURCHARGE=0.50 # Optional surcharge for express payouts&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


You can find your API Key and Secret Key in your Rapyd Sandbox dashboard.

### 5.3 Seed Test Data

Populate your database with some sample workers and earnings using the seed script:

`Bashnpm run seed`

Expect output similar to:



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Seeding database...&lt;br&gt;
Worker "Alice" created with ID: 1&lt;br&gt;
Earnings added for Alice: $175.50&lt;br&gt;
Worker "Bob" created with ID: 2&lt;br&gt;
Earnings added for Bob: $230.25&lt;br&gt;
Database seeding complete.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


### 5.4 Trigger Standard vs. Express Payout

&amp;gt; *(Imagine a short GIF embedded here showing a simple UI with a list of workers, a "Payout" button, a modal to enter the amount, and options for "Standard" and "Express" payout before a final confirmation.)*

The application provides a straightforward UI to initiate payouts. Here's an example of a basic API request for a standard payout:



```code
{
  "amount": 75.00,
  "currency": "USD",
  "beneficiary": {
    "type": "bank_account",
    // ... detailed beneficiary information ...
  },
  "payout_method_type": "us_ach"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When an "Express Payout" is selected (and &lt;code&gt;EXPRESS_PAYOUT_SURCHARGE&lt;/code&gt; is configured), the application logic will add this surcharge to the final amount processed by Rapyd.&lt;/p&gt;
&lt;h3&gt;
  
  
  5.5 Webhook Billing Flow
&lt;/h3&gt;

&lt;p&gt;Rapyd Webhooks are essential for accurate fee tracking. When a payout completes successfully (&lt;code&gt;payout.completed&lt;/code&gt; event), your backend receives a notification. Here's a simplified snippet of how you might handle this event and record the fee:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /pages/api/webhooks/rapyd.js (example)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;payout.completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payoutId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isExpress&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FEE_FIXED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FEE_PERCENT&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isExpress&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_PAYOUT_SURCHARGE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_PAYOUT_SURCHARGE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO invoices (worker_id, payout_id, amount, fee, created_at) VALUES ($1, $2, $3, $4, NOW())&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;workerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payoutId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Recorded fee of &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; for payout &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;payoutId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Webhook received and processed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error recording invoice:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error processing webhook&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Webhook received&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Allow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Method &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; Not Allowed`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.6 Admin Dashboard
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;(Imagine a simple screenshot here showing a basic admin interface displaying a table or chart of collected fees, potentially broken down by date or worker.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The included (basic) admin dashboard provides a quick overview of the fees your platform has collected.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Deploy &amp;amp; Go Live
&lt;/h2&gt;

&lt;p&gt;Get your payout engine live quickly using platforms like &lt;strong&gt;Render&lt;/strong&gt; or &lt;strong&gt;Railway&lt;/strong&gt;, which offer seamless deployment from Git repositories. Simply connect your forked repo, configure your environment variables (API keys, fee settings) as secrets in their dashboards, and let them handle the build and deployment process. Remember to run any necessary database migrations on your deployed environment and configure your Rapyd Webhook URL in the Rapyd dashboard to point to your live backend webhook endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Monetization Tweaks &amp;amp; Ideas
&lt;/h2&gt;

&lt;p&gt;The basic fee structure is just the beginning. Consider these enhancements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tiered Fees:&lt;/strong&gt; Adjust fees based on the number of active workers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FX Markup:&lt;/strong&gt; Add a small margin on currency conversions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription Add-ons:&lt;/strong&gt; Offer premium analytics or invoicing for a recurring fee.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Instant Payout" Upsell:&lt;/strong&gt; Clearly market the faster payout option with its surcharge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Security &amp;amp; Compliance Notes
&lt;/h2&gt;

&lt;p&gt;Since this setup primarily handles payouts and doesn't directly process or store sensitive card data, the PCI DSS scope is minimal. However, for platforms with high transaction volumes or specific regulatory requirements, consider integrating Rapyd's KYC (Know Your Customer) solutions. Always consult with legal and compliance experts for your specific jurisdiction.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Key Takeaways: Your Fast Track to Monetized Payouts
&lt;/h2&gt;

&lt;p&gt;In just an afternoon, you can build a global payout system with built-in monetization. Rapyd Disburse handles the complexity, and our ready-to-fork repo gives you a running start. Start earning revenue with every cash-out, quickly and efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Ready to Monetize Your Gig Economy Platform?
&lt;/h2&gt;

&lt;p&gt;Stop leaving money on the table!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Rapyd-Samples/rapyd-basic-payroll-app-with-disburse" rel="noopener noreferrer"&gt;GET THE REPO NOW&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set your fees, deploy your application, and start tracking your platform's profit. Share your feedback and any cool enhancements you build in the comments below!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>postgres</category>
      <category>webdev</category>
      <category>payments</category>
    </item>
    <item>
      <title>Tokenization in Payments: The Future of Secure, Anonymous Transactions</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Tue, 10 Jun 2025 10:00:00 +0000</pubDate>
      <link>https://dev.to/rapyd/tokenization-in-payments-the-future-of-secure-anonymous-transactions-3okn</link>
      <guid>https://dev.to/rapyd/tokenization-in-payments-the-future-of-secure-anonymous-transactions-3okn</guid>
      <description>&lt;p&gt;By: &lt;strong&gt;Adeyinka Adegbenro&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the 2010s, the gatekeepers of the payment industry—think &lt;a href="https://www.pcisecuritystandards.org/" rel="noopener noreferrer"&gt;Payment Card Industry Data Security Standard (PCI DSS)&lt;/a&gt;, &lt;a href="https://mastercard.com/" rel="noopener noreferrer"&gt;Mastercard&lt;/a&gt;, and &lt;a href="https://visa.com/" rel="noopener noreferrer"&gt;Visa&lt;/a&gt;—have promoted tokenization as the industry standard for compliance and card-related fraud prevention.&lt;/p&gt;

&lt;p&gt;Why? Because tokenization is extremely important for protecting the privacy of financial institutions. Instead of sharing a card's actual sixteen-digit number, it swaps in a unique, randomly generated token so that a user's raw card details are never shared.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn more about tokenization and how to implement payment tokenization using the &lt;a href="https://docs.rapyd.net/en/get-started.html" rel="noopener noreferrer"&gt;Rapyd API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Tokenization
&lt;/h2&gt;

&lt;p&gt;At its core, tokenization replaces sensitive payment details with nonsensitive, randomly generated tokens that can't be reversed, unless you have access to the provider's vault. These tokens are securely stored either by the merchant or in the tokenization provider's vault.&lt;/p&gt;

&lt;p&gt;Tokenizing payment data doesn't use just a single algorithm—it uses a layered approach that combines techniques, like masking, cryptographic storage, obfuscation, and randomization, to create secure tokens:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xhduss4s00x2jrrf6w5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xhduss4s00x2jrrf6w5.png" alt="How tokenization works in payments, courtesy of Adeyinka Adegbenro" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In most cases, using a tokenization service is recommended over creating your own service because it's PCI DSS–compliant out of the box, quicker to implement, and built to scale.&lt;/p&gt;

&lt;p&gt;It's important to note that tokenization does not replace due diligence. You still need to validate PCI DSS compliance, but it may simplify the process by reducing the number of components subject to PCI DSS requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Tokenization
&lt;/h2&gt;

&lt;p&gt;The main benefit of tokenization is that it significantly reduces the impact of data breaches and the risk of fraud because the stolen tokens can't be used to access the original card details. Tokenization also provides you with the following benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Requires fewer resources&lt;/strong&gt; than other privacy measures, like encryption, because it doesn't involve complex mathematical operations and can be carried out by third-party providers like Rapyd.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enables secure storage&lt;/strong&gt; of credit card information for modern payment methods, including one-click payments, mobile wallets, and cryptocurrencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhances security and convenience&lt;/strong&gt; while remaining invisible to customers, allowing businesses to offer a seamless payment experience without requiring user actions like signing up, logging in, or managing passwords.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduces fraud risk,&lt;/strong&gt; increasing the likelihood of bank transactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Encryption vs. Tokenization
&lt;/h2&gt;

&lt;p&gt;Tokenization is the process of replacing sensitive data with a token. Meanwhile, encryption is the process of converting data into an unreadable format using a decryption key. Encryption is ideal for securely transmitting and retrieving data, like encrypted emails, readable only by recipients with the cryptographic key. In contrast, tokenization is best for masking data that doesn't need to be stored in its original form. Unlike encryption, tokenization is irreversible if you don't have access to the token vault.&lt;/p&gt;

&lt;p&gt;Encryption also differs from tokenization because encryption can be computationally intensive, especially for large-scale systems. Encryption is widely used for general data security and compliance with privacy laws like the &lt;a href="https://www.hhs.gov/hipaa/index.html" rel="noopener noreferrer"&gt;Health Insurance Portability and Accountability Act (HIPAA)&lt;/a&gt; and the &lt;a href="https://gdpr-info.eu/" rel="noopener noreferrer"&gt;General Data Protection Regulation (GDPR)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In contrast, tokenization is lightweight, making it the primary choice for PCI DSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Implement a Tokenized Payment System with Rapyd
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you'll learn how to use Rapyd for tokenization in a payment system by using a sample project on GitHub called &lt;a href="https://github.com/Rapyd-Samples/rapyd-tokenization-example" rel="noopener noreferrer"&gt;Rapyd_Ecommerce or rapyd-tokenization-example&lt;br&gt;
&lt;/a&gt;. Rapyd_Ecommerce is a simple &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; app that uses Express as a server and &lt;a href="https://ejs.co/" rel="noopener noreferrer"&gt;EJS&lt;/a&gt; as a light template framework to render the UI.&lt;/p&gt;

&lt;p&gt;Before you begin, you need to install the latest version of &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;, Node.js, and &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt; (which comes with Node.js) on your computer.&lt;/p&gt;

&lt;p&gt;Once you have the latest version of Git, clone the sample application from GitHub by running the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Rapyd-Samples/rapyd-tokenization-example.git

&lt;span class="nb"&gt;cd &lt;/span&gt;Rapyd_Ecommerce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a Rapyd Account
&lt;/h3&gt;

&lt;p&gt;If you don't already have one, create a &lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd account&lt;/a&gt;. Once you're signed in, you will, by default, be in sandbox mode.&lt;/p&gt;

&lt;p&gt;From the sidebar, navigate to &lt;strong&gt;Developers &amp;gt; API access control&lt;/strong&gt; and note your sandbox credentials:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxa54fsr4ed8mx7zprm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpxa54fsr4ed8mx7zprm2.png" alt="Rapyd credentials" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, create a &lt;code&gt;.env&lt;/code&gt; file in the root folder. This holds your Rapyd credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;.env&lt;/code&gt; file, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RAPYD_ACCESS_KEY=&amp;lt;YOUR_RAPYD_ACCESS_KEY&amp;gt;
RAPYD_SECRET_KEY=&amp;lt;YOUR_RAPYD_SECRET_KEY&amp;gt;
RAPYD_BASE_URL=https://sandboxapi.rapyd.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in the same file, replace  and  with your access key and secret key. Install the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the Rapyd API doesn't support localhost URLs for webhooks, this tutorial uses &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt; to create a secure, temporary public URL that tunnels requests to your local server. Use the following code to install ngrok:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; ngrok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create an ngrok account and fetch your ngrok token by selecting &lt;a href="https://dashboard.ngrok.com/get-started/your-authtoken" rel="noopener noreferrer"&gt;&lt;strong&gt;Your Authtoken&lt;/strong&gt;&lt;/a&gt; from the sidebar. Copy your authtoken, add it to ngrok in the terminal, and start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok config add-authtoken &lt;span class="nv"&gt;$YOUR_AUTHTOKEN&lt;/span&gt;

ngrok http 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the output, you'll see a public URL that looks like this—&lt;code&gt;https://862e-102-89-82-24.ngrok-free.app&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay99au75hibc731dkp0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay99au75hibc731dkp0x.png" alt="ngrok output" width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up Webhooks
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.rapyd.net/en/payment-webhooks.html" rel="noopener noreferrer"&gt;Webhooks&lt;/a&gt; are sent by Rapyd after a payment request is completed—whether successful, failed, or canceled.&lt;/p&gt;

&lt;p&gt;From your Rapyd Client Portal, navigate to &lt;strong&gt;Developer &amp;gt; Webhooks &amp;gt; Management&lt;/strong&gt;. Go to the section named &lt;strong&gt;Define your callback URL and the events that will trigger it.&lt;/strong&gt; On the blank, add your callback URL. It should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjwdjwjsjpldj0b7nyb7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjwdjwjsjpldj0b7nyb7.png" alt="Screenshot of the Rapyd **Webhooks** page" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, if your public URL is &lt;code&gt;https://cb9d-102-89-83-16.ngrok-free.app&lt;/code&gt;, then the callback URL will be &lt;code&gt;https://cb9d-102-89-83-16.ngrok-free.app/api/webhook&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Collect&lt;/strong&gt; section, click &lt;strong&gt;Select all&lt;/strong&gt; and save your changes. From now on, whenever a payment flow starts and the user completes payment, the server receives a webhook request at &lt;code&gt;/api/webhook&lt;/code&gt; with an update on the original payment request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up the Payment Flow
&lt;/h3&gt;

&lt;p&gt;To start the payment flow, enter your ngrok public URL in a browser and click &lt;strong&gt;Visit Site&lt;/strong&gt;. You'll see a page listing gadgets and their prices:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5khng4bfkq4zc5hu3fvr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5khng4bfkq4zc5hu3fvr.png" alt="Screenshot of the sample application's landing page" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This page is being served by &lt;code&gt;index.ejs&lt;/code&gt; and the product data from &lt;code&gt;products.json&lt;/code&gt;. Clicking the &lt;strong&gt;Buy&lt;/strong&gt; button sends a GET request to the server endpoint (&lt;code&gt;/buy&lt;/code&gt;) along with the &lt;code&gt;productId&lt;/code&gt;, &lt;code&gt;amount&lt;/code&gt;, and &lt;code&gt;currency&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;server.js&lt;/code&gt;, the &lt;code&gt;/buy&lt;/code&gt; endpoint renders the &lt;strong&gt;Checkout&lt;/strong&gt; page using &lt;code&gt;views/checkout.ejs&lt;/code&gt;. This page collects the user's card details and processes the payment. The Rapyd API securely tokenizes the card details and charges the card based on the specified currency, amount, and other transaction details.&lt;/p&gt;

&lt;p&gt;When the &lt;strong&gt;Checkout&lt;/strong&gt; page loads, the app sends a request to the &lt;code&gt;/create-checkout&lt;/code&gt; endpoint to retrieve the Rapyd &lt;strong&gt;Checkout&lt;/strong&gt; page URL. Handling this on the backend is more secure as it keeps sensitive API credentials like &lt;code&gt;RAPYD_ACCESS_KEY&lt;/code&gt; and &lt;code&gt;RAPYD_SECRET_KEY&lt;/code&gt; hidden.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;server.js&lt;/code&gt;, the &lt;code&gt;/create-checkout&lt;/code&gt; route needs to call the Rapyd API &lt;code&gt;/v1/checkout&lt;/code&gt; endpoint with the required headers and body attributes. For a list of possible attributes, see the &lt;a href="https://docs.rapyd.net/en/create-checkout-page.html" rel="noopener noreferrer"&gt;Rapyd &lt;strong&gt;Create Checkout Page&lt;/strong&gt; documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For this tutorial, the &lt;code&gt;body&lt;/code&gt; payload contains the required attributes as well as a few others. On line 75, the body payload contains the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;amount&lt;/code&gt;&lt;/strong&gt; refers to the price of the gadget converted to string format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;currency&lt;/code&gt;&lt;/strong&gt; is the currency of the item being purchased.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;country&lt;/code&gt;&lt;/strong&gt; is the two-letter ISO 3166-1 code for the &lt;a href="https://docs.rapyd.net/en/list-countries.html" rel="noopener noreferrer"&gt;country&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;complete_payment_url&lt;/code&gt;&lt;/strong&gt; is the URL to which you want Rapyd to redirect the user after a successful checkout. It's set to &lt;code&gt;http://localhost:3000/success&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;error_payment_url&lt;/code&gt;&lt;/strong&gt; is the URL to which you want Rapyd to redirect the user after a failed checkout. In this case, it's set to &lt;code&gt;http://localhost:3000/fail&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rapyd uses HMAC-SHA256 signature-based authentication to verify that every API request comes from an authorized source. This means that a request to &lt;code&gt;/v1/checkout&lt;/code&gt; must include a digitally signed SHA-256 signature.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;server.js&lt;/code&gt; (line 88), the header object contains the following attributes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;content-type&lt;/code&gt;&lt;/strong&gt; is set to &lt;code&gt;application/json&lt;/code&gt;, indicating the request body is in JSON format.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;access_key&lt;/code&gt;&lt;/strong&gt; is retrieved from your &lt;code&gt;.env&lt;/code&gt; file. This is the Rapyd access key found in the &lt;strong&gt;Developers&lt;/strong&gt; section of your Rapyd Client Portal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;idempotency&lt;/code&gt;&lt;/strong&gt; is a unique ID generated using the &lt;a href="https://www.npmjs.com/package/uuid" rel="noopener noreferrer"&gt;uuid library&lt;/a&gt; (UUID version 4) to prevent duplicate transactions. When retrying a failed request, reuse the same idempotency key to avoid processing it as a new request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;salt&lt;/code&gt;&lt;/strong&gt; is an eight- to sixteen-digit random string required by Rapyd to generate a unique signature for each request, preventing replay attacks. It's an extra layer of security to protect against malicious reuse of old requests. While the idempotency key can be reused for retries, the salt and signature must be regenerated for every request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;timestamp&lt;/code&gt;&lt;/strong&gt; is the request timestamp in &lt;a href="https://en.wikipedia.org/wiki/Unix_time" rel="noopener noreferrer"&gt;Unix&lt;/a&gt; format (seconds).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;signature&lt;/code&gt;&lt;/strong&gt; is generated in the &lt;code&gt;generateSignature&lt;/code&gt; function by concatenating the request method (POST), URL path (&lt;code&gt;/v1/checkout&lt;/code&gt;), salt, timestamp, access key, secret key, and the stringified JSON body. The string is then hashed using SHA-256 and encoded to Base64. For more details, check out the &lt;a href="https://docs.rapyd.net/en/request-signatures.html" rel="noopener noreferrer"&gt;Rapyd documentation on &lt;strong&gt;Signatures&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the POST request is successfully sent to &lt;code&gt;/v1/checkout&lt;/code&gt;, &lt;code&gt;/create-checkout&lt;/code&gt; returns the &lt;code&gt;checkout_url&lt;/code&gt; to &lt;code&gt;checkout.ejs&lt;/code&gt;, which then redirects the page to the official Rapyd &lt;strong&gt;Checkout&lt;/strong&gt; page. At this point, you should see a &lt;strong&gt;Checkout&lt;/strong&gt; page with multiple payment options:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidpzess3irjuh7m6pa6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidpzess3irjuh7m6pa6f.png" alt="Screenshot of the Rapyd **Checkout** page with card details filled" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since this tutorial focuses on card payment and tokenization, select the &lt;strong&gt;Card&lt;/strong&gt; option.&lt;/p&gt;

&lt;p&gt;Rapyd provides &lt;a href="https://docs.rapyd.net/en/card-numbers-for-testing.html" rel="noopener noreferrer"&gt;test card numbers&lt;/a&gt; for testing card payments. Use &lt;code&gt;4111111111111111&lt;/code&gt; as the card number, any future date as the expiration date, and any three-digit number as the CVV number. Then select &lt;strong&gt;Place Your Order&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once you've placed the order, you should see another authentication page that mimics 3-D Secure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wlnu981zjh04mtjr1js.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wlnu981zjh04mtjr1js.png" alt="Screenshot of the payment **3DS Simulator** page" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;123456&lt;/code&gt; and click &lt;strong&gt;Continue&lt;/strong&gt;. Rapyd then handles payment tokenization and charges the card. All this is done on the Rapyd secure servers, which means you don't need to worry about card number security, tokenization, or the details of charging the card.&lt;/p&gt;

&lt;p&gt;If the payment fails, the &lt;code&gt;error_payment_url&lt;/code&gt; endpoint &lt;code&gt;/fail&lt;/code&gt; is called, and a &lt;code&gt;PAYMENT_FAILED&lt;/code&gt; webhook is sent to the &lt;code&gt;/api/webook&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;p&gt;On the flip side, if the payment is successful, the &lt;code&gt;complete_payment_url&lt;/code&gt; endpoint &lt;code&gt;/success&lt;/code&gt; is called. Then a &lt;code&gt;PAYMENT_SUCCEEDED&lt;/code&gt; webhook is sent to the &lt;code&gt;/api/webook&lt;/code&gt; endpoint:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay7343qnleu34blfglys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fay7343qnleu34blfglys.png" alt=" raw `PAYMENT_SUCCEEDED` endraw  webhook calls" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rapyd lets you save a user's card details by initially creating a customer via the &lt;a href="https://docs.rapyd.net/en/create-customer.html" rel="noopener noreferrer"&gt;&lt;code&gt;Create Customer&lt;/code&gt; endpoint&lt;/a&gt;, which returns a customer ID. This ID can be included in the &lt;code&gt;/v1/checkout&lt;/code&gt; request, giving users the option to save their card for future purchases. For future transactions, simply reuse the customer ID to access saved cards—securely stored by Rapyd—so they never need to be saved on your server.&lt;/p&gt;

&lt;p&gt;The beauty of this payment flow is that the tokenization process is completely abstracted away, leaving you time to focus on other things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Without tokenization, unprotected data is a ticking time bomb. A data breach costs millions in damages and fines. Adding tokenization to your system design helps you build data breach–resilient systems.&lt;/p&gt;

&lt;p&gt;Using the &lt;a href="https://docs.rapyd.net/en/external-network-tokenization.html" rel="noopener noreferrer"&gt;Rapyd API&lt;/a&gt; for tokenization, you can safeguard payment data for all your tokenization needs while ensuring compliance with global security best practices. Rapyd can also be used to receive, send, and manage funds globally. &lt;a href="https://docs.rapyd.net/en/index-en.html" rel="noopener noreferrer"&gt;Learn more about Rapyd today&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Fintech APIs: Architecting the Future with AI</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Fri, 16 May 2025 17:57:44 +0000</pubDate>
      <link>https://dev.to/rapyd/fintech-apis-architecting-the-future-with-ai-2607</link>
      <guid>https://dev.to/rapyd/fintech-apis-architecting-the-future-with-ai-2607</guid>
      <description>&lt;p&gt;APIs have long been the foundation of fintech innovation, enabling everything from payouts to identity verification. Now, Artificial Intelligence is fundamentally changing how developers build and interact with these tools, transforming them from static integrations into intelligent decision-making systems.&lt;/p&gt;

&lt;p&gt;This article explores the evolution of fintech APIs and provides actionable insights for developers looking to build smarter, AI-enhanced payment workflows using GPT-4 and Rapyd.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rise of AI-Powered APIs
&lt;/h2&gt;

&lt;p&gt;APIs are evolving from simple data conduits to context-aware services. Integrating large language models like GPT-4 into financial workflows allows developers to move from fixed rules to intelligent, adaptive logic.&lt;/p&gt;

&lt;p&gt;This leads to advancements in fintech such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smarter real-time payment decisioning&lt;/li&gt;
&lt;li&gt;Adaptive credit workflows based on user behavior&lt;/li&gt;
&lt;li&gt;Evolving fraud detection systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at a practical implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project: GPT-4 Powered Payment Form
&lt;/h2&gt;

&lt;p&gt;We've created an example project to help developers explore this future. It's a working template for integrating AI into real-world fintech flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation: GPT-4 and Rapyd Integration
&lt;/h2&gt;

&lt;p&gt;This open-source repository demonstrates how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate secure payment forms using GPT-4&lt;/li&gt;
&lt;li&gt;Implement custom payment workflows based on user needs&lt;/li&gt;
&lt;li&gt;Trigger payment actions via Rapyd’s API&lt;/li&gt;
&lt;li&gt;Create a modular and customizable framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project provides a starting point for applications like AI-driven form pre-filling, intelligent chatbot checkouts, and AI-assisted KYC processes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repository Contents:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;main.py&lt;/code&gt;: AI and payment interaction orchestration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;form_generator.py&lt;/code&gt;: GPT-4 powered secure form generation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;payment_flows.py&lt;/code&gt;: Rapyd API interaction logic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env.example&lt;/code&gt;: Setup for API keys and tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This demonstrates secure connection of AI-generated input to real API calls within a scalable architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Benefits
&lt;/h2&gt;

&lt;p&gt;This shift towards AI-enhanced APIs offers significant advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduced manual steps and intelligent defaults&lt;/li&gt;
&lt;li&gt;Simplified and secure API interaction&lt;/li&gt;
&lt;li&gt;Improved user and business experiences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach is crucial for developers in areas like embedded finance, wallets, B2B payouts, and global payments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explore the Implementation
&lt;/h2&gt;

&lt;p&gt;Start exploring the possibilities of AI-enhanced fintech development:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/Rapyd-Samples/Using-GPT-4-and-Rapyd-to-Create-a-Payment-Workflow" rel="noopener noreferrer"&gt;&lt;strong&gt;GPT-4 + Rapyd Payment Workflow on GitHub&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This open-source project is designed for quick setup and real-world application.&lt;/p&gt;

&lt;p&gt;Fork it, extend it, and use it as the foundation for your next fintech innovation.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>api</category>
      <category>ai</category>
      <category>rapydpayments</category>
    </item>
    <item>
      <title>Real-Time Payment Systems: How to Build Instant Payment Solutions with Rapyd</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Tue, 13 May 2025 13:08:20 +0000</pubDate>
      <link>https://dev.to/rapyd/real-time-payment-systems-how-to-build-instant-payment-solutions-with-rapyd-22na</link>
      <guid>https://dev.to/rapyd/real-time-payment-systems-how-to-build-instant-payment-solutions-with-rapyd-22na</guid>
      <description>&lt;p&gt;By: &lt;strong&gt;Gift Uhiene&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Real-time payment (RTP) systems enable instant fund transfers between bank accounts, making them essential for modern financial applications. For each transaction, funds and payment information are exchanged and settled within seconds of the transaction initiation. RTP service is continuous 24/7 and available all year round.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd&lt;/a&gt; is a global fintech-as-a-service provider that enables businesses to perform instant fund transfers in local currencies and maintain digital wallets globally. With its extensive API offerings, developers can integrate Rapyd finance capabilities into their applications to effortlessly manage cross-border payments, multicurrency treasury, card issuing, fraud protection, and compliance.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn how to build an RTP-enabled Node.js app using Rapyd and WebSockets, covering setup, API integration, and transaction handling.&lt;/p&gt;

&lt;p&gt;You can explore the complete code and follow along with the implementation via &lt;a href="https://github.com/Rapyd-Samples/rtp-rapyd" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before getting started, you should have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://dashboard.rapyd.net/sign-up" rel="noopener noreferrer"&gt;Rapyd account&lt;/a&gt;; if you're signing up for the first time, you'll need to verify your email and complete the required verification steps&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; installed on your system&lt;/li&gt;
&lt;li&gt;A basic understanding of JavaScript, React.js, and APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Rapyd API Credentials
&lt;/h2&gt;

&lt;p&gt;Log in to the &lt;a href="https://dashboard.rapyd.net/" rel="noopener noreferrer"&gt;Rapyd dashboard&lt;/a&gt; and navigate to the &lt;strong&gt;Developers &amp;gt; API access control&lt;/strong&gt; section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66jdo5li8bdal2uympt7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66jdo5li8bdal2uympt7.png" alt="Get Rapyd credentials" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Store these keys securely as you'll need them to authenticate API requests:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynrqzfgjn83mzulgtvf0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fynrqzfgjn83mzulgtvf0.png" alt="Rapyd credentials" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Real-Time Payment Backend
&lt;/h2&gt;

&lt;p&gt;In this section, you'll build a backend system that integrates the Rapyd API and WebSockets to create a real-time payment flow. The system will allow users to create wallets, initiate transfers, and receive real-time updates on transfer statuses. Here's what we'll cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setting up the Rapyd API client&lt;/strong&gt; to send secure requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creating a WebSocket server&lt;/strong&gt; to broadcast real-time updates to clients&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creating wallet controllers&lt;/strong&gt; to communicate with Rapyd APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building the Express server&lt;/strong&gt; to tie everything together&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Setup
&lt;/h3&gt;

&lt;p&gt;Clone the starter branch of the project with the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--branch&lt;/span&gt; starter &lt;span class="nt"&gt;--single-branch&lt;/span&gt; https://github.com/Rapyd-Samples/rtp-rapyd.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the structure of the &lt;code&gt;backend&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;rtp-rapyd/
    │── backend/
    │   │── node_modules/
    │   │── src/
    │   │   │── config/
    │   │   │   ├── rapydClient.js    # Handles API requests to Rapyd
    │   │   │── controllers/
    │   │   │   ├── walletController.js   # Logic for wallet
    │   │   │── routes/
    │   │   │   ├── walletRoutes.js   # Defines API routes for wallet actions
    │   │   │── server.js             # Main entry point
    │   │   │── websocket.js          # WebSocket logic for real-time updates
    │   │── .env                      # API keys and secrets
    │   │── package.json              # Project dependencies
    │   │── README.md                 # Documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing Dependencies
&lt;/h3&gt;

&lt;p&gt;Navigate to the &lt;code&gt;backend&lt;/code&gt; directory in your terminal and install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;backend
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, run the following command in the &lt;code&gt;backend&lt;/code&gt; directory of your terminal to start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring the Rapyd API Client
&lt;/h2&gt;

&lt;p&gt;To interact with Rapyd's API, you'll need a client that handles authentication, request signing, and HTTP communication.&lt;/p&gt;

&lt;p&gt;Rapyd's API requires specified header parameters for each request to verify that the requester is an authorized user and to protect against data tampering.&lt;/p&gt;

&lt;p&gt;Go to the &lt;code&gt;backend/src/config/rapydClient.js&lt;/code&gt; file and include the code below to set up a Rapyd API client. This will allow you to securely authenticate and make HTTP requests to Rapyd's API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RAPYD_ACCESS_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secretKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RAPYD_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urlPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpBaseURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sandboxapi.rapyd.net&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateRandomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idempotency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;httpMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urlPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;httpBaseURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;urlPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;httpMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;access_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accessKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;idempotency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;idempotency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;httpRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error generating request options&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urlPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bodyString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;toSign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;urlPath&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;accessKey&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;secretKey&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;bodyString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secretKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toSign&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error generating signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateRandomString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;httpRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bodyString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

      &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;makeRequest&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above is from the &lt;a href="https://docs.rapyd.net/en/request-signatures.html" rel="noopener noreferrer"&gt;Node.js example&lt;/a&gt; on the Rapyd documentation. The &lt;code&gt;sign&lt;/code&gt; function generates a signature for each request using your &lt;code&gt;accessKey&lt;/code&gt; and &lt;code&gt;secretKey&lt;/code&gt;, ensuring secure communication with the API. To prevent duplicate transactions, every request includes a unique &lt;code&gt;idempotency&lt;/code&gt; key.&lt;/p&gt;

&lt;p&gt;Before moving forward, create a &lt;code&gt;.env&lt;/code&gt; file in the root of the &lt;code&gt;backend&lt;/code&gt; directory to store your Rapyd credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RAPYD_ACCESS_KEY=your_access_key
RAPYD_SECRET_KEY=your_secret_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting Up WebSockets
&lt;/h2&gt;

&lt;p&gt;WebSockets enable bidirectional communication between the server and clients, allowing real-time updates without the need for constant polling. Implementing WebSockets in this project will keep the connection open so that when a change happens, the server will immediately update users without them having to refresh the page. To implement this, update &lt;code&gt;backend/src/websocket.js&lt;/code&gt; file with the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setupWebSocketServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;wss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;noServer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;upgrade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleUpgrade&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;✅ New WebSocket connection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;📩 Received:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server received: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;❌ Client disconnected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifyUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;setupWebSocketServer(server)&lt;/code&gt; function initializes a WebSocket server that handles upgrades from an HTTP server, listens for client connections, and processes incoming messages. The &lt;code&gt;notifyUsers(transaction)&lt;/code&gt; function will broadcast real-time updates to all connected clients by sending transaction data as a JSON string.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;backend/src/server.js&lt;/code&gt; file with the code below to create a server for the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupWebSocketServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./websocket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;walletRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./routes/walletRoutes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/wallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;walletRoutes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setupWebSocketServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server running on port 4000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rapyd Wallet: Managing Real-Time Transactions and Fund Transfers
&lt;/h2&gt;

&lt;p&gt;When building a real-time payment system, one of the key components you'll need is a reliable and flexible wallet system. &lt;a href="https://docs.rapyd.net/en/rapyd-wallet.html" rel="noopener noreferrer"&gt;Rapyd Wallet&lt;/a&gt; allows businesses and developers to create, manage, and transfer funds between wallets in real time by acting as a financial hub where money can be moved across borders, currencies, and payment methods.&lt;/p&gt;

&lt;p&gt;Some of its key features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multicurrency support:&lt;/strong&gt; Each wallet can hold multiple accounts, each with its own currency and balance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom branding:&lt;/strong&gt; You can brand the wallets with your own logo and design, making it feel like a native part of your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client and user wallets:&lt;/strong&gt; A two-tier structure with client wallets for businesses and user wallets for individuals (such as sellers or employees).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FX capabilities:&lt;/strong&gt; Rapyd Wallet integrates with Rapyd's foreign exchange (FX) features, allowing you to convert currencies at competitive rates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split payments:&lt;/strong&gt; You can split payments between multiple wallets, which is useful for marketplaces or platforms with shared revenue models.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Building the Wallet Controller
&lt;/h3&gt;

&lt;p&gt;To manage all wallet-related operations, let's build a wallet controller. This controller will handle interactions with the Rapyd API and centralize the logic for wallet management.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;backend/src/controllers/walletController.js&lt;/code&gt; and update &lt;code&gt;createWallet&lt;/code&gt; with the code below to implement the function to handle wallet creation and initial funding using Rapyd's API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emailPrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ewalletReferenceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;emailPrefix&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Construct the wallet creation payload&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;walletData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ewallet_reference_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ewalletReferenceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;contact_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;company&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;business&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;personal&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SG&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;line_1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123 Main Street&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SG&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SG&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;date_of_birth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2000-11-22&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;merchant_defined&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;walletResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/v1/ewallets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;walletData&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;walletId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;walletResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fundResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/v1/account/deposit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;ewallet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;walletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SGD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;walletResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;initial_deposit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fundResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code performs the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validates the request using &lt;code&gt;express-validator&lt;/code&gt; to ensure all required fields are present.&lt;/li&gt;
&lt;li&gt;Extracts user details from the request body.&lt;/li&gt;
&lt;li&gt;Generates a unique &lt;code&gt;ewallet_reference_id&lt;/code&gt; by combining the email prefix and a timestamp.&lt;/li&gt;
&lt;li&gt;Constructs a &lt;code&gt;walletData&lt;/code&gt; object containing user details, contact information, address, and metadata. Some fields, like the country (&lt;code&gt;SG&lt;/code&gt;), are hard-coded but can be customized.&lt;/li&gt;
&lt;li&gt;Creates a wallet by sending a POST request to Rapyd's &lt;code&gt;/v1/ewallets&lt;/code&gt; endpoint. The response includes a &lt;code&gt;walletId&lt;/code&gt; that uniquely identifies the wallet.&lt;/li&gt;
&lt;li&gt;Funds the wallet with 20 SGD by making a deposit request to &lt;code&gt;/v1/account/deposit&lt;/code&gt;. This step is specific to sandbox mode, as real deposits require actual funding sources in production.&lt;/li&gt;
&lt;li&gt;Returns a JSON response with the wallet details and deposit transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, in the same file, update the &lt;code&gt;retrieveWallet&lt;/code&gt; function to fetch details about a user wallet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;retrieveWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accountId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Account ID is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/v1/ewallets/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function above extracts &lt;code&gt;accountId&lt;/code&gt; from the request parameters and makes a GET request to Rapyd's API to retrieve a wallet's details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transferring Funds Between Wallets
&lt;/h3&gt;

&lt;p&gt;Rapyd allows &lt;a href="https://docs.rapyd.net/en/transfer-funds-between-wallets.html" rel="noopener noreferrer"&gt;funds transfers&lt;/a&gt; between wallets; if the destination wallet does not have the specified currency, an account for that currency is automatically created. When a transfer is initiated, the status is marked as "PEN" until accepted by the transferee, using the &lt;a href="https://docs.rapyd.net/en/set-transfer-response.html" rel="noopener noreferrer"&gt;Set Transfer Response API&lt;/a&gt;. Unaccepted transfers can, in turn, be canceled by the sender using the same API.&lt;/p&gt;

&lt;p&gt;To initiate a peer-to-peer wallet transfer, update the &lt;code&gt;transferFunds&lt;/code&gt; function in the &lt;code&gt;backend/src/controllers/walletController.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transferFunds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;senderWalletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;receiverWalletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/v1/ewallets/transfer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;source_ewallet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;senderWalletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;destination_ewallet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;receiverWalletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SGD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transactionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Transaction ID not found.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;notifyUsers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;senderWalletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;receiverWalletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SGD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TRANSFER_FUNDS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Transfer initiated. Waiting for confirmation...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function sends a request to Rapyd's &lt;code&gt;/v1/ewallets/transfer&lt;/code&gt; endpoint to transfer funds between wallets, using SGD as the currency. It extracts the transaction ID, notifies all WebSocket clients about the transfer, and responds to the client confirming the request was initiated.&lt;/p&gt;

&lt;p&gt;Finally, update the &lt;code&gt;respondToTransfer&lt;/code&gt; function in the same file to enable both the sender and transferee to respond to a transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondToTransfer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accept&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cancel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid status. Must be 'accept', 'decline', or 'cancel'.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/v1/ewallets/transfer/response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SUCCESS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Failed to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; transfer.`&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;notifyUsers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;source_ewallet_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destination_ewallet_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currency_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accept&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accepted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Declined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cancel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cancelled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RESPONDS_TO_TRANSFER&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Transfer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ed successfully.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function extracts the &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; from the request, validates the &lt;code&gt;status&lt;/code&gt; (&lt;code&gt;accept&lt;/code&gt;, &lt;code&gt;decline&lt;/code&gt;, or &lt;code&gt;cancel&lt;/code&gt;), and sends a request to Rapyd's &lt;code&gt;/v1/ewallets/transfer/response&lt;/code&gt; endpoint to update the transfer. It also notifies the WebSocket clients about the transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting the Frontend
&lt;/h2&gt;

&lt;p&gt;Now that the backend is set up, let's connect the frontend application to interact with the backend and provide real-time updates to users.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Most of the frontend components are already provided in the starter project, so this example doesn't focus on building them from scratch. Instead, you'll concentrate on integrating the frontend with the backend and enabling real-time functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installing Dependencies
&lt;/h3&gt;

&lt;p&gt;In another terminal, navigate to the &lt;code&gt;frontend&lt;/code&gt; directory and install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;frontend
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npm run dev&lt;/code&gt; to run the React.js project.&lt;/p&gt;

&lt;h3&gt;
  
  
  The createWallet Function
&lt;/h3&gt;

&lt;p&gt;Go to the &lt;code&gt;frontend/src/components/create-wallet-form.jsx&lt;/code&gt; file and update &lt;code&gt;createWallet&lt;/code&gt; with the code below. This function sends a POST request to the backend to create a wallet and stores the wallet ID in local storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createWallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:4000/api/wallet/create&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;userData&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ewallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to create wallet:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The transferFunds Function
&lt;/h3&gt;

&lt;p&gt;Let's implement the function to transfer funds between wallets. Update &lt;code&gt;transferFunds&lt;/code&gt; in the &lt;code&gt;frontend/src/components/transfer-form.jsx&lt;/code&gt; file. This function sends a POST request to the backend to initiate a transfer between two wallets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transferFunds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:4000/api/wallet/transfer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;senderWalletId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;walletData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;receiverWalletId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;receiverWallet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to transfer funds:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The respondToTransfer Function
&lt;/h3&gt;

&lt;p&gt;Finally, let's add the function to respond to transfer requests. Update &lt;code&gt;respondToTransfer&lt;/code&gt; in the &lt;code&gt;frontend/src/components/transaction-list.jsx&lt;/code&gt; file. This function sends a POST request to the backend to approve or reject a transfer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;respondToTransfer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:4000/api/wallet/respond-transfer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;transactionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to respond to transfer:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Result
&lt;/h2&gt;

&lt;p&gt;To bring everything together, here's a demonstration of the app in action. The GIF below showcases the real-time payment features, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initiating a fund transfer between wallets&lt;/li&gt;
&lt;li&gt;Receiving real-time updates on transaction statuses&lt;/li&gt;
&lt;li&gt;Accepting, declining, or canceling transfers dynamically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FEQ6KqA3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FEQ6KqA3.gif" alt="Real-time payment demonstration" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that, you've successfully implemented a dynamic, real-time payment system using Rapyd's API and WebSockets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, you learned how to build a real-time payment system using the Rapyd API and WebSockets. From setting up the backend to handling wallet creation, wallet-to-wallet transfers, and real-time updates, you now have the tools to create a seamless payment experience for users. By integrating Rapyd's powerful API and leveraging WebSocket communication, you can ensure that both senders and receivers receive instant feedback on their transactions so your application is dynamic and responsive.&lt;/p&gt;

&lt;p&gt;Rapyd's global payment capabilities make it an excellent choice for developers and businesses looking to implement secure and scalable payment solutions in their applications. Whether you're building a peer-to-peer payment app, an e-commerce platform, or a financial service, Rapyd provides the infrastructure to handle transactions efficiently. To explore more features and capabilities, visit the &lt;a href="https://docs.rapyd.net/en/index-en.html" rel="noopener noreferrer"&gt;Rapyd API documentation&lt;/a&gt; and start building your next fintech solution today.&lt;/p&gt;

&lt;p&gt;For further learning, check out Rapyd's &lt;a href="https://community.rapyd.net/" rel="noopener noreferrer"&gt;developer community resources&lt;/a&gt; and &lt;a href="https://github.com/Rapyd-Samples" rel="noopener noreferrer"&gt;sample projects&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>fintech</category>
      <category>node</category>
    </item>
    <item>
      <title>Navigating Regulatory Compliance in API Development</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Thu, 03 Apr 2025 09:00:00 +0000</pubDate>
      <link>https://dev.to/rapyd/navigating-regulatory-compliance-in-api-development-3nab</link>
      <guid>https://dev.to/rapyd/navigating-regulatory-compliance-in-api-development-3nab</guid>
      <description>&lt;p&gt;Regulatory compliance is not just a checkbox in API development - it's foundational to maintaining trust, security, and operational integrity. Developers working with enterprise merchants and partners must understand critical regulatory frameworks and embed compliance into every stage of API design and implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Regulatory Frameworks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GDPR (General Data Protection Regulation)
&lt;/h3&gt;

&lt;p&gt;GDPR mandates stringent requirements for personal data management within APIs. Developers must ensure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Minimization: Collect only necessary user information.&lt;/li&gt;
&lt;li&gt;Consent Management: APIs must facilitate clear and explicit user consent.&lt;/li&gt;
&lt;li&gt;Right to Erasure: Implement mechanisms to delete user data upon request.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  PSD2 (Payment Services Directive 2)
&lt;/h3&gt;

&lt;p&gt;PSD2 shapes how payment services APIs interact within the European Economic Area:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong Customer Authentication (SCA): APIs must support multi-factor authentication.&lt;/li&gt;
&lt;li&gt;Secure Communication: Ensuring secure data transmission via encryption and authentication methods.&lt;/li&gt;
&lt;li&gt;Open Banking Standards: Adhering to defined API protocols for financial transactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Regional Compliance Challenges
&lt;/h3&gt;

&lt;p&gt;Regional regulations, such as California's CCPA or Brazil's LGPD, introduce additional layers of complexity. APIs need configurable compliance logic that adapts to region-specific data protection and security standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building APIs with Compliance in Mind
&lt;/h2&gt;

&lt;p&gt;Compliance should be integral from the outset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security by Design: Adopt secure coding practices, perform regular penetration testing, and code reviews.&lt;/li&gt;
&lt;li&gt;Data Governance: Implement clear data handling and retention policies.&lt;/li&gt;
&lt;li&gt;Documentation and Transparency: Clearly document API functionalities, including compliance-related considerations, making audits smoother.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Embedding compliance strategically doesn't only fulfill obligations - it can deliver competitive advantages like faster market entry, greater customer trust, and reduced risk exposure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools and Strategies for Real-time Reporting and Audit Readiness
&lt;/h2&gt;

&lt;p&gt;Effective compliance management involves real-time monitoring and immediate audit readiness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logging and Monitoring: Implement comprehensive logging of API requests and responses.&lt;/li&gt;
&lt;li&gt;Real-time Alerts: Develop alert systems for unusual activity to ensure rapid response.&lt;/li&gt;
&lt;li&gt;Audit Trails: Maintain immutable records of transactions and user actions for compliance verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Resource: Secure Request Signatures
&lt;/h2&gt;

&lt;p&gt;To practically implement secure API interactions, developers can utilize the Rapyd PHP SDK for request signatures:&lt;/p&gt;

&lt;p&gt;GitHub Repository: &lt;a href="https://cta-service-cms2.hubspot.com/web-interactives/public/v1/track/click?encryptedPayload=AVxigLL79VZ64BjJ3bJaLjuYRffz3%2Bz8m1gp7lxXXSCVubgGauNMCmgq9czoVNWNnTJDlIhopPuqVQhSJDYBlJliJxtqACKOPbTlpqwS2BLbhHcJy7QFrwZj5GJQN%2FuLNWiDvLR5hKi%2BmGNkYgTX3aGDDWeJ9Rq3bbQwu26W9Mao5YS%2Fi3uLDOVd2xfvKDOiChhYjaO4jbc1RkKgfw8ZcqyLk8c%3D&amp;amp;portalId=5246303" rel="noopener noreferrer"&gt;rapyd-request-signatures-php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This repository provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ready-to-use examples demonstrating how to generate and verify secure API request signatures.&lt;/li&gt;
&lt;li&gt;Clear documentation to quickly implement security measures compliant with GDPR, PSD2, and similar regulations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Compliance is integral to Rapyd’s mission to drive global payment innovation securely and reliably. Have you encountered specific regulatory challenges or discovered effective tools in your API projects? We'd love to hear your insights and experiences in the comments below or connect directly with our compliance experts in the Rapyd community.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>payments</category>
      <category>api</category>
      <category>php</category>
    </item>
    <item>
      <title>🗞 Rapyd Developer Newsletter: March 2025 💥 Boost Your Dev Workflow: Automate APIs, Track Payouts &amp; Master Fintech KPIs</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Thu, 27 Mar 2025 14:01:19 +0000</pubDate>
      <link>https://dev.to/rapyd/rapyd-developer-newsletter-march-2025-boost-your-dev-workflow-automate-apis-track-payouts--3po0</link>
      <guid>https://dev.to/rapyd/rapyd-developer-newsletter-march-2025-boost-your-dev-workflow-automate-apis-track-payouts--3po0</guid>
      <description>&lt;p&gt;Stay ahead with the latest updates, trends, and tools from the Rapyd Developer Community! 🚀&lt;/p&gt;

&lt;p&gt;💾 &lt;strong&gt;Essential Updates&lt;/strong&gt;&lt;br&gt;
Be code-ready – our updated &lt;a href="https://docs.rapyd.net/en/api-changelog.html" rel="noopener noreferrer"&gt;API&lt;/a&gt; and &lt;a href="https://docs.rapyd.net/en/product-changelog.html" rel="noopener noreferrer"&gt;Product&lt;/a&gt; changelogs are your go-to for changes impacting your work.&lt;/p&gt;

&lt;p&gt;🧩 &lt;a href="https://community.rapyd.net/t/using-openapi-to-automate-api-integration-with-rapyds-payment-gateway/59719" rel="noopener noreferrer"&gt;Using OpenAPI to Automate API Integration With Rapyd's Payment Gateway&lt;/a&gt;&lt;br&gt;
Automate setup, reduce errors and speed up payment integrations&lt;/p&gt;

&lt;p&gt;💰 &lt;a href="https://docs.rapyd.net/en/listing-payouts.html" rel="noopener noreferrer"&gt;Payout Status Change&lt;/a&gt;&lt;br&gt;
Get instant visibility into payment progress and track updates effortlessly &lt;/p&gt;

&lt;p&gt;💳 &lt;a href="https://community.rapyd.net/t/partners-how-isos-and-payfacs-are-shaping-fintech/59709" rel="noopener noreferrer"&gt;Partners: How ISOs and PayFacs Are Shaping Fintech&lt;/a&gt;&lt;br&gt;
Explore how industry partners are redefining financial services and unlocking new opportunities &lt;/p&gt;

&lt;p&gt;🎯 &lt;a href="https://community.rapyd.net/t/kpis-fintech-developers-should-know/59720" rel="noopener noreferrer"&gt;KPIs Fintech Developers Should Know&lt;/a&gt;&lt;br&gt;
Track the metrics that matter in fintech development and optimize performance with actionable insights.&lt;/p&gt;

&lt;p&gt;See you next month, &lt;br&gt;
The Rapyd Dev Community Team &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; Do you have ideas to improve this newsletter or want to contribute an article or join a panel? Let us know by replying.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>tutorial</category>
      <category>rapydnews</category>
      <category>api</category>
    </item>
    <item>
      <title>Embedded Financial Services: The Future of Vertical SaaS</title>
      <dc:creator>Drew Harris</dc:creator>
      <pubDate>Mon, 03 Mar 2025 15:47:50 +0000</pubDate>
      <link>https://dev.to/rapyd/embedded-financial-services-the-future-of-vertical-saas-37lb</link>
      <guid>https://dev.to/rapyd/embedded-financial-services-the-future-of-vertical-saas-37lb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Embedded financial services are transforming &lt;strong&gt;Vertical SaaS&lt;/strong&gt;, allowing developers to integrate payments, lending, and banking directly into applications. This shift reduces friction for users, unlocks new revenue streams, and &lt;strong&gt;keeps financial interactions inside the platform&lt;/strong&gt; - a game-changer for SaaS providers.&lt;/p&gt;

&lt;p&gt;In this article, we'll cover:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;What embedded financial services are and why they matter&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Real-world case studies of Vertical SaaS implementations&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;API strategies for embedding payments in niche industries&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;A hands-on GitHub project using Rapyd’s API to integrate payments into a travel agency web app&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Are Embedded Financial Services?
&lt;/h2&gt;

&lt;p&gt;Embedded financial services refer to integrating &lt;strong&gt;payments, lending, banking, and insurance&lt;/strong&gt; directly within a software platform. Instead of users relying on external financial institutions, SaaS platforms &lt;strong&gt;own the financial experience&lt;/strong&gt; - improving user retention and creating new monetization opportunities.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key Examples
&lt;/h3&gt;

&lt;p&gt;📌 &lt;strong&gt;Embedded Payments:&lt;/strong&gt; Accept transactions within the platform.&lt;br&gt;&lt;br&gt;
📌 &lt;strong&gt;Lending &amp;amp; Financing:&lt;/strong&gt; Offer loans to users based on transaction history.&lt;br&gt;&lt;br&gt;
📌 &lt;strong&gt;Insurance:&lt;/strong&gt; Provide in-app coverage for specific user needs.&lt;br&gt;&lt;br&gt;
📌 &lt;strong&gt;Digital Wallets:&lt;/strong&gt; Allow users to store and send money natively.  &lt;/p&gt;

&lt;p&gt;For developers, the challenge is &lt;strong&gt;seamless integration&lt;/strong&gt; - leveraging APIs to connect financial services while ensuring security, compliance, and scalability.&lt;/p&gt;


&lt;h2&gt;
  
  
  Case Studies: How Vertical SaaS Embeds Financial Services
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Payments &amp;amp; Lending in E-Commerce Platforms
&lt;/h3&gt;

&lt;p&gt;A cloud-based e-commerce platform integrated &lt;strong&gt;embedded payments and merchant financing&lt;/strong&gt;, allowing businesses to process transactions without third-party providers. The platform later expanded into &lt;strong&gt;business loans&lt;/strong&gt;, using sales data to assess loan eligibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact for Developers:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built-in payments eliminated reliance on external payment gateways.
&lt;/li&gt;
&lt;li&gt;API-driven underwriting enabled automated financing decisions.
&lt;/li&gt;
&lt;li&gt;Increased developer control over checkout flows and user experience.
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Subscription Billing for Service-Based SaaS
&lt;/h3&gt;

&lt;p&gt;A SaaS company serving &lt;strong&gt;health and wellness businesses&lt;/strong&gt; embedded &lt;strong&gt;recurring billing and payments&lt;/strong&gt;, allowing gyms, studios, and therapists to &lt;strong&gt;automate payments and manage memberships seamlessly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact for Developers:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrated payments reduced churn by keeping transactions inside the platform.
&lt;/li&gt;
&lt;li&gt;API-driven automation replaced manual billing processes.
&lt;/li&gt;
&lt;li&gt;Improved reporting capabilities for tracking revenue and subscriptions.
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3. Payments &amp;amp; Payroll for Industry-Specific SaaS
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;restaurant technology platform&lt;/strong&gt; embedded &lt;strong&gt;payment processing, payroll, and financial reporting&lt;/strong&gt; to &lt;strong&gt;streamline operations&lt;/strong&gt; for businesses in the hospitality industry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact for Developers:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers implemented an &lt;strong&gt;API-first approach&lt;/strong&gt; for real-time financial transactions.
&lt;/li&gt;
&lt;li&gt;Reduced operational complexity by embedding &lt;strong&gt;financial management tools&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Enabled multi-party payments, distributing funds to vendors, employees, and partners.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These examples highlight &lt;strong&gt;why embedded finance is the next frontier&lt;/strong&gt; for SaaS—&lt;strong&gt;it increases platform value and revenue&lt;/strong&gt; by keeping financial transactions inside the ecosystem.&lt;/p&gt;


&lt;h2&gt;
  
  
  API Strategies for Embedding Financial Services
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Choosing the Right API Provider
&lt;/h3&gt;

&lt;p&gt;When embedding financial services, pick an API provider that offers:&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Comprehensive Documentation&lt;/strong&gt; – Clear API references, code samples, and tutorials.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Multi-Currency Support&lt;/strong&gt; – For global transactions.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Compliance &amp;amp; Security&lt;/strong&gt; – PCI DSS, PSD2, and local financial regulations.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Providers:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rapyd&lt;/strong&gt; (Global payments, wallets, and payouts)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe&lt;/strong&gt; (Payments and financial automation)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plaid&lt;/strong&gt; (Banking API for financial data)
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Implementing Embedded Payments with APIs
&lt;/h3&gt;

&lt;p&gt;Let’s say we’re integrating &lt;strong&gt;Rapyd’s API&lt;/strong&gt; into a travel booking platform to accept payments.&lt;/p&gt;
&lt;h4&gt;
  
  
  Step 1: API Authentication
&lt;/h4&gt;

&lt;p&gt;First, securely authenticate API requests using &lt;strong&gt;HMAC signature authentication&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;

&lt;span class="n"&gt;secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_secret_key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data_to_sign&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Creating a Payment Checkout Page
&lt;/h4&gt;

&lt;p&gt;Send a request to the Rapyd API to generate a checkout page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import requests

url = "https://sandboxapi.rapyd.net/v1/checkout"
payload = {
    "amount": 100,
    "currency": "USD",
    "complete_checkout_url": "https://yourwebsite.com/success",
    "cancel_checkout_url": "https://yourwebsite.com/cancel",
    "payment_method_types_include": ["card"]
}

response = requests.post(url, json=payload, headers=headers)
print(response.json())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Handling Webhooks for Payment Confirmation
&lt;/h4&gt;

&lt;p&gt;Use webhooks to listen for successful transactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask import Flask, request

app = Flask(__name__)

@app.route("/webhook", methods=["POST"])
def webhook():
    data = request.json
    if data["event"] == "PAYMENT_COMPLETED":
        print("Payment received:", data["data"])
    return "", 200

if __name__ == "__main__":
    app.run(port=5000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📌 &lt;strong&gt;Best Practices:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoid storing API keys in code&lt;/strong&gt; – Use environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate webhook requests&lt;/strong&gt; to prevent spoofing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensure compliance&lt;/strong&gt; with local financial regulations.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Practical Example: Building a Travel Agency Web App with Rapyd
&lt;/h2&gt;

&lt;p&gt;To showcase how embedded finance works, we’ve built a &lt;strong&gt;travel booking web app&lt;/strong&gt; that integrates &lt;strong&gt;Rapyd’s payment gateway&lt;/strong&gt; using &lt;strong&gt;Python (Flask) and React&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://cta-service-cms2.hubspot.com/web-interactives/public/v1/track/click?encryptedPayload=AVxigLJjSFv%2BQxIXIAszzzBsOXumF%2BbkqssIMTenXxWSwo8ZyXYmvOD2TiJiVgQiVAyejFCbRj%2BcFiHZFVQYwXXF6AUEdhwk0%2BKFEQlSVS%2Be19P%2FLqGKzMg1Pt%2Fm7nQgWGa0Gn1qs4%2FQb5o65IwuNM3JVublFC%2BSIoJREhTefZHo7d%2F5kf8JHG6ndHZyRxuHgr7sKoaLZOq0fY4aaltVrdwJxvLidyYpI9K294MfOoT75usslt%2ByjJ%2FpTyOidBndAZmSTf22DxIGx6xrzAITCwuCQslo4j%2BMP3x8QLyb&amp;amp;portalId=5246303" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Repo&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;🚀 &lt;strong&gt;Backend:&lt;/strong&gt; Python, Flask&lt;br&gt;
💻 &lt;strong&gt;Frontend:&lt;/strong&gt; React&lt;br&gt;
💳 &lt;strong&gt;Payments:&lt;/strong&gt; Rapyd API&lt;/p&gt;
&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Secure Payments&lt;/strong&gt; – Accept cards, bank transfers, and digital wallets.&lt;br&gt;
✅ &lt;strong&gt;Booking System&lt;/strong&gt; – Users can book flights, hotels, and activities.&lt;br&gt;
✅ &lt;strong&gt;API-Driven Architecture&lt;/strong&gt; – The backend communicates with Rapyd’s payment APIs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Quick Setup Guide
&lt;/h3&gt;

&lt;p&gt;Clone the repo and run the app locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/your-repo/travel-agency-rapyd.git
cd travel-agency-rapyd
pip install -r requirements.txt
npm install &amp;amp;&amp;amp; npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🚀 &lt;strong&gt;Run Flask Backend:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💻 &lt;strong&gt;Start React Frontend:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can test payments directly in the app!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Embedded financial services are redefining Vertical SaaS&lt;/strong&gt;—allowing businesses to &lt;strong&gt;own financial transactions&lt;/strong&gt; and &lt;strong&gt;increase platform revenue&lt;/strong&gt;. Developers play a key role in this transformation by leveraging &lt;strong&gt;financial APIs like Rapyd to integrate payments, lending, and banking&lt;/strong&gt; into their SaaS applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next Steps:
&lt;/h3&gt;

&lt;p&gt;🔹 &lt;strong&gt;Explore the GitHub project&lt;/strong&gt; and integrate Rapyd’s API into your own application.&lt;br&gt;
🔹 &lt;strong&gt;Test the API calls and webhooks&lt;/strong&gt; using the sandbox environment.&lt;br&gt;
🔹 &lt;strong&gt;Think about how embedded finance could enhance your own SaaS product.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s your next embedded finance project? Let’s discuss in the comments!&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>saas</category>
      <category>payments</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
