Get your dream built 10x faster

Replit and Wave Integration: 2026 Guide

We build custom applications 5x faster and cheaper 🚀

Book a Free Consultation
4.9
Clutch rating 🌟
600+
Happy partners
17+
Countries served
190+
Team members
Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Stuck on an error? Book a 30-minute call with an engineer and get a direct fix + next steps. No pressure, no commitment.

Book a free consultation

How to Integrate Replit with Wave

To integrate Replit with Wave (Wave Accounting API), you connect your Replit app to the Wave REST API using standard HTTPS requests, authenticate via OAuth 2.0 (for user-based apps) or personal access tokens (for personal automation), and handle data – like invoices, customers, or payments – inside your running Repl. You’ll store sensitive information such as the Wave API token or client secret securely using Replit Secrets. The Repl will run a small backend (for example, with Express in Node.js or Flask in Python) to communicate with Wave’s endpoints and process webhooks if needed.

 

1. Prepare your Wave Developer Access

 

Wave requires an authenticated API token to interact with financial data. Go to Wave Developer Portal, create an account, and either:

  • Create a personal access token if it’s only for your own data (simpler); or
  • Register an OAuth application if the integration will work for multiple Wave users.

Copy the token or OAuth credentials and add them as Replit Secrets under the “Secrets” tab (the lock icon in the Replit sidebar).

  • If using a personal token: add WAVE_API_TOKEN
  • If using OAuth: add WAVE_CLIENT_ID, WAVE_CLIENT_SECRET, and WAVE_REDIRECT_URI

 

2. Set up your Repl app

 

You can use any language, but let’s show a working example using Node.js with Express, which runs well in Replit’s hosted environment.

// server.js

import express from "express";
import fetch from "node-fetch";

const app = express();
const PORT = process.env.PORT || 3000;

// Ensure your token is added as a Replit Secret named WAVE_API_TOKEN
const WAVE_API_TOKEN = process.env.WAVE_API_TOKEN;

app.get("/businesses", async (req, res) => {
  try {
    // Query Wave’s GraphQL endpoint for available businesses
    const response = await fetch("https://gql.waveapps.com/graphql/public", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${WAVE_API_TOKEN}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        query: `
          query {
            businesses {
              id
              name
            }
          }
        `
      })
    });

    const data = await response.json();
    res.json(data);
  } catch (error) {
    console.error(error);
    res.status(500).send("Error fetching Wave data");
  }
});

app.listen(PORT, "0.0.0.0", () => {
  console.log(`Server running on port ${PORT}`);
});

In the above example:

  • The app binds to 0.0.0.0 so Replit can expose it publicly on a mapped port.
  • It connects to Wave’s GraphQL API endpoint with an Authorization header containing your token.
  • Response data (like list of businesses) appears as JSON when you visit the Replit web URL followed by /businesses.

 

3. Testing and Debugging

 

Run the Repl. Replit automatically builds and runs your server, showing a URL like https://your-repl-name.your-username.repl.co. Visit /businesses in the browser or call it via curl/Postman to verify that the API returns data.

curl https://your-repl-name.your-username.repl.co/businesses

This should return a JSON array of your Wave businesses if your token is correct.

 

4. Handling More Complex Flows

 

  • For OAuth flows: you’d redirect users to Wave’s authorization URL, exchange the authorization code for an access token, and store it temporarily (never hardcode tokens).
  • To handle webhooks: add another app.post("/wave-webhook") route, verify Wave’s webhook payload signature, and process invoice updates or payments live while your Repl runs.
  • Persistence: use Replit’s built-in Database for lightweight state (though any serious accounting records should remain in Wave itself).

 

5. Reliability and Deployment Considerations

 

When ready for production, move long-running or scaling parts (like webhook handlers that need guaranteed uptime) to a dedicated environment. But for demos, testing, or lightweight automation, Replit’s always-on Deployments can work well if set explicitly under “Deployments → Always on app”.

By following these steps, your Replit project will have a solid, explicit, working integration with Wave — secure through Replit Secrets, live via a bound Express server, and testable through standard API calls.

Use Cases for Integrating Wave and Replit

1

Accept Online Payments from a Replit Web App

Integrating Wave’s Invoicing and Payments API with a Replit full‑stack web app allows a small business app or portfolio project to accept real customer payments. A Flask or Express.js server runs inside Replit, exposing endpoints that create invoices or charge clients directly through Wave’s API. All API keys and OAuth tokens are securely stored as Replit Secrets. When the server runs, you map port 3000 or 8080 and bind to 0.0.0.0 so that payment pages and webhook URLs are reachable externally. Wave’s sandbox lets you safely test payments in your Repl before going live.

  • Use Replit Secrets for WAVE_API_KEY.
  • Expose a REST endpoint to create invoices and capture payments.
  • Handle JSON responses with proper status codes for debugging inside Replit.
# Flask example: create an invoice with Wave API
import os, requests
from flask import Flask, jsonify

app = Flask(__name__)
API_KEY = os.getenv("WAVE_API_KEY")

@app.route("/invoice")
def create_invoice():
    url = "https://gql.waveapps.com/graphql/public"
    headers = {"Authorization": f"Bearer {API_KEY}"}
    query = """mutation {
      invoiceCreate(input: {businessId: "your-business-id", title: "Test Invoice"})
      { invoice { id title } }
    }"""
    r = requests.post(url, json={"query": query}, headers=headers)
    return jsonify(r.json())

app.run(host="0.0.0.0", port=3000)

2

Accept Online Payments from a Replit Web App

Using Replit Workflows, you can schedule scripts that sync sales data or expenses into Wave automatically. A deployment runs a Python or Node.js script every few hours to retrieve sales from another API and push them to your Wave account. Since Replit’s filesystem resets and storage is ephemeral, all persistent data or logs should be stored in an external database (for example, Google Sheets or a hosted DB). Secrets securely hold OAuth tokens so your automation remains safe, and when running the Repl manually, you can debug each sync through console output.

  • Trigger Workflows on a timed schedule inside Replit.
  • Use environment variables for authentication.
  • Log results for each batch of synced transactions.
# Replit Workflow step: run Python script to sync transactions
python3 sync_to_wave.py

3

Receive Webhooks for Real‑Time Payment Notifications

You can handle Wave payment webhooks in a live Replit webserver to get instant notification when invoices are paid. This is great for projects that send receipts, update a dashboard, or trigger fulfillment steps. The Flask or Express endpoint runs only while the Repl or Deployment is active. You expose a secure HTTPS URL via Replit, verify each webhook signature for authenticity, and log the events. Because webhooks must respond quickly, design the handler to store minimal data locally and offload heavy logic to an external service or queue.

  • Expose /webhook/wave endpoint listening on 0.0.0.0.
  • Validate the request signature using your Wave secret.
  • Consume JSON payloads and trigger downstream actions (e.g., email notifications).
# Flask webhook listener for Wave payment events
from flask import Flask, request

app = Flask(__name__)

@app.route("/webhook/wave", methods=["POST"])
def wave_webhook():
    data = request.get_json()
    print("Received from Wave:", data)  # Inspect details in Replit console
    return ("ok", 200)

app.run(host="0.0.0.0", port=8080)

Book Your Free 30‑Minute Migration Call

Speak one‑on‑one with a senior engineer about your no‑code app, migration goals, and budget. In just half an hour you’ll leave with clear, actionable next steps—no strings attached.

Book a Free Consultation

Troubleshooting Wave and Replit Integration

1

Why is the Wave API not connecting properly inside a Replit project?

The Wave API usually fails to connect inside Replit when your Repl cannot establish an outbound TLS HTTPS connection due to incorrect environment variables (API keys), using localhost instead of the real endpoint, or network restrictions in the Replit environment. Also, Wave rejects requests without proper Authorization headers or malformed JSON bodies.

 

How to fix it

 

  • Store your Wave API key in Replit Secrets under the same name your code expects (for example WAVE_API_KEY).
  • Use HTTPS endpoints exactly as documented: https://api.waveapps.com/businesses/{business\_id}/….
  • Check that your requests use correct headers: Authorization: Bearer $WAVE_API_KEY and Content-Type: application/json.
  • Run the Repl, open the shell and test connectivity using curl to confirm external requests are allowed.
  • Wave OAuth tokens expire; refresh or regenerate them if you see 401 responses.

 

import os, requests

token = os.getenv("WAVE_API_KEY")  # Set in Replit Secrets
url = "https://gql.waveapps.com/graphql"

query = """{ user { id defaultEmail } }"""  # Simple test query

res = requests.post(url,
    json={"query": query},
    headers={"Authorization": f"Bearer {token}"})

print(res.status_code, res.text)  # Should return 200 and valid JSON

 

2

How to fix “ModuleNotFoundError” when importing Wave in Replit?

The “ModuleNotFoundError: No module named 'wave'” in Replit means Python can’t find the H2O Wave library in your environment. To fix it, explicitly install it from PyPI, confirm the import, and ensure your Repl uses the correct Python environment every time it runs.

 

Fix the Error Step-by-Step

 

  • Install the package inside the Repl shell:
pip install h2o-wave
  • Import and verify the module in your code:
from h2o_wave import main, app, Q, ui  // if import passes, install worked
  • If the module still isn’t found, open the “Packages” tab in Replit UI, search “h2o-wave”, and add it so Replit remembers the dependency for future runs.
  • Replit reinstalls dependencies on every build, so keeping h2o-wave in requirements.txt ensures persistence:
echo "h2o-wave" >> requirements.txt
  • Restart your Repl or workflow after adding packages; this refreshes the Python path used during startup.

3

How to make Replit show Wave dashboard or web app output correctly in the preview?

To make a Wave dashboard or web app show correctly in Replit’s preview, run the app on host 0.0.0.0 and a fixed port (usually 8080), then open the Replit “Webview” or “Open in new tab” option. Replit only displays services bound to this host and mapped port inside its container. Do not use localhost or other ports, because Replit proxies only the designated one.

 

Step-by-step setup

 

  • Inside Replit, install the h2o\_wave package and import required modules.
  • Start the Wave server so it listens on 0.0.0.0 and port 10101, for example.
  • In the Replit “Ports” sidebar, expose that port and open preview.
  • The Wave dashboard UI will appear once the app process is running and bound correctly.

 

# app.py
from h2o_wave import site, ui

page = site['/demo']
page['example'] = ui.markdown_card(box='1 1 2 2', title='Wave on Replit', content='Hello Dashboard!')
page.save()  # render dashboard

# Run server: Replit needs explicit bind
# wave run app --no-reload --address 0.0.0.0 --port 8080

 

If you run with wave run app, include --address 0.0.0.0 and --port 8080. Then click “Open in new tab”. The dashboard renders through Replit’s proxy correctly.

Book a Free Consultation

Schedule a 30‑Minute No‑Code‑to‑Code Consultation

Grab a quick video call to discuss the fastest, most cost‑efficient path from no‑code to production‑ready code. Zero sales fluff—just practical advice tailored to your project.

Contact us

Common Integration Mistakes: Replit + Wave

Not Binding to 0.0.0.0 and Missing Port Exposure

Wave integrations often fail on Replit because developers start their Flask or Express server using localhost instead of 0.0.0.0. On Replit, only 0.0.0.0 allows the Repl to be publicly reachable. If the server listens to localhost, Wave’s webhooks or API callbacks can’t connect. You also need to be sure the port your server uses matches the Replit mapped URL (like port 3000 for Node or 8080 for Python). Always use the port from process.env.PORT so Replit can dynamically assign it.

  • Use 0.0.0.0 as host to allow external access.
  • Use process.env.PORT to bind your app to the correct port.
// Example: Wave webhook listener in Express
import express from "express";
const app = express();

app.post("/wave/webhook", (req, res) => {
  console.log("Webhook received:", req.body);
  res.sendStatus(200);
});

app.listen(process.env.PORT || 3000, "0.0.0.0", () => {
  console.log("Server is live on Replit!");
});

Exposing Wave API Keys in Code

Hardcoding your Wave API key or OAuth token directly inside code is a serious mistake. Replit’s public Repls can be viewed or forked, meaning credentials leak easily. Always store secrets in the Replit Secrets Manager (found under Tools → Secrets) and fetch them using environment variables. This keeps keys encrypted and unavailable to collaborators unless shared deliberately.

  • Never push credentials directly in source files.
  • Use process.env variables from Secrets to store tokens safely.
// Correct usage with secret key
const WAVE_API_KEY = process.env.WAVE_API_KEY;

fetch("https://api.waveapps.com/v1/users/me/", {
  headers: { Authorization: `Bearer ${WAVE_API_KEY}` },
}).then(res => res.json()).then(console.log);

Skipping Webhook Verification

Wave sends webhook calls from its servers to your Replit app — but many forget to verify the source. Without verifying signatures or checking known headers, anyone can spoof fake updates. Always check the X-Wave-Signature or token header against your secret. Store your verification secret in Replit Secrets, and verify on every request before trusting its data. This prevents fraudulent webhook triggers that might alter invoices or transactions.

  • Verify every incoming webhook using a pre-shared secret.
  • Reject unverified requests with proper HTTP status codes (403).
// Basic webhook verification pattern
app.post("/wave/webhook", (req, res) => {
  const received = req.headers["x-wave-signature"];
  if (received !== process.env.WAVE_WEBHOOK_SECRET) {
    return res.sendStatus(403);
  }
  // Process verified event
  res.sendStatus(200);
});

Expecting Replit to Persist or Scale Server State

Wave data or integration state (like tokens or transactions) should never be stored in memory or inside Replit’s temporary filesystem. Replit servers restart or sleep, wiping runtime data. Store lasting data externally — for example, in an external database like Supabase, Firebase, or MongoDB Atlas — which can safely persist beyond Replit restarts. Treat Replit as a lightweight connector, not as your permanent data layer.

  • Use external DBs or cloud storage for state persistence.
  • Never rely on local JSON files or server memory for important Wave data.
// Example: Persisting Wave events externally
import { MongoClient } from "mongodb";
const client = new MongoClient(process.env.MONGO_URL);
await client.connect();

app.post("/wave/webhook", async (req, res) => {
  const event = req.body;
  await client.db("wave").collection("events").insertOne(event);
  res.sendStatus(200);
});

Still stuck?
Copy this prompt into ChatGPT and get a clear, personalized explanation.

This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.

AI AI Prompt


Recognized by the best

Trusted by 600+ businesses globally

From startups to enterprises and everything in between, see for yourself our incredible impact.

RapidDev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with.

They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

Arkady
CPO, Praction
Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost.

He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Donald Muir
Co-Founder, Arc
RapidDev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space.

They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Mat Westergreen-Thorne
Co-CEO, Grantify
RapidDev is an excellent developer for custom-code solutions.

We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Emmanuel Brown
Co-Founder, Church Real Estate Marketplace
Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 

This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Samantha Fekete
Production Manager, Media Production Company
The pSEO strategy executed by RapidDev is clearly driving meaningful results.

Working with RapidDev has delivered measurable, year-over-year growth. Comparing the same period, clicks increased by 129%, impressions grew by 196%, and average position improved by 14.6%. Most importantly, qualified contact form submissions rose 350%, excluding spam.

Appreciation as well to Matt Graham for championing the collaboration!

Michael W. Hammond
Principal Owner, OCD Tech

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â