If you run affiliate or creator payouts for a Shopify store, you know the drill: export a spreadsheet, log into PayPal or a payout platform, pay per-transaction fees on every single recipient, wait days for settlement, and deal with the countries your payment provider doesn't support.
There's a simpler way: batch USDC payouts on Base. One transaction, N recipients, settlement in seconds, and it works for anyone with a wallet address — anywhere in the world.
In this tutorial, you'll self-host an open-source Shopify app that adds a Payouts section to your Shopify admin. You'll upload a CSV of affiliate wallet addresses and amounts, approve USDC once, and pay everyone in a single on-chain transaction.
Repo: github.com/plagtech/spraay-shopify (MIT license)
🤖 Using an OpenClaw agent? Skip the manual setup entirely:
openclaw skills install @plagtech/spraay-shopify-selfhostwalks you through deployment, and@plagtech/shopify-batch-payoutsruns payouts via the Spraay gateway.
What you're building
The Spraay Shopify app is an embedded admin app (built with Remix + Polaris, so it looks and feels native to Shopify) that lets you:
- Upload or paste a CSV of recipients — wallet address + USDC amount per row
- Review the batch — recipients, totals, and the 0.3% protocol fee, all shown before anything moves
- Connect a wallet — MetaMask or Coinbase Smart Wallet
- Approve USDC once, then execute the entire batch in one transaction on Base
- Track payout history right in your admin
Under the hood, payouts go through the Spraay batch contract on Base (0x1646452F98E36A3c9Cfc3eDD8868221E207B5eEC), using native USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913). Base transaction fees are typically a fraction of a cent, so the cost of paying 50 affiliates is basically the same as paying one.
Why self-hosted?
Two reasons:
- You control everything. Your Shopify credentials, your database, your infrastructure. The app requests zero Shopify scopes — it structurally cannot read your orders, customers, or products — and it never custodies funds: payouts are signed by your wallet, in your browser.
- Custom app distribution is Shopify's intended path for merchant-specific tooling. You create your own app in the Shopify Dev Dashboard, install it on your store, and you're done. No app store, no waiting.
Prerequisites
- A Shopify store (any plan; a development store works for testing)
- A Shopify Partners account (free) to create the custom app
- A Railway account for hosting (or any host that runs Docker/Node 20)
- A Supabase project for the Postgres database (free tier is fine)
- A wallet with USDC on Base (MetaMask or Coinbase Smart Wallet)
Total setup time: about 15 minutes.
Step 1: Fork and deploy
Fork plagtech/spraay-shopify, then deploy it to Railway. The repo ships with a railway.json and Dockerfile (node:20-alpine), so the Deploy to Railway button in the README gets you a running instance quickly.
One important detail: make sure PORT=3000 is set in your Railway service variables — the container expects it.
Once deployed, Railway gives you a public URL (e.g. your-app.up.railway.app). You can point a custom domain at it later via CNAME if you want something cleaner.
Step 2: Create your custom app in Shopify
- Go to dev.shopify.com → Apps → Create app → choose Custom distribution. This is Shopify's intended path for merchant-specific tooling — no App Store review involved.
- Set the App URL to your Railway deployment URL (HTTPS, no trailing slash).
- Add all three OAuth redirect URLs:
https://your-domain/auth/callback
https://your-domain/auth/shopify/callback
https://your-domain/api/auth/callback
- Copy the Client ID and Client Secret — they become
SHOPIFY_API_KEYandSHOPIFY_API_SECRETin the next step. Then install the app on your store from the Dev Dashboard.
Step 3: Configure environment variables
The repo includes a fully documented .env.example. Set these in your Railway service variables (the Deploy button pre-prompts for all of them):
| Variable | Value |
|---|---|
SHOPIFY_API_KEY |
Client ID from Step 2 (public — it ships in the browser bundle) |
SHOPIFY_API_SECRET |
Client Secret from Step 2 (keep secret — it signs webhooks and OAuth) |
SHOPIFY_APP_URL |
Your Railway URL, no trailing slash |
SCOPES |
Leave empty — the app uses no Shopify data |
DATABASE_URL |
Supabase pooled connection string (port 6543), with ?schema=shopify&pgbouncer=true
|
DIRECT_URL |
Supabase direct connection string (port 5432), with ?schema=shopify
|
NODE_ENV |
production |
PORT |
3000 |
Two things worth knowing:
-
PORT=3000is load-bearing. The Dockerfile exposes 3000; if Railway injects its default 8080 instead, every route returns a 502 even though the deploy shows "Online." If you ever see that symptom, this is why. - The
?schema=shopifysuffix keeps the app's tables in their own Postgres schema, so it won't collide with anything else in your Supabase project.
Migrations run automatically on boot. When the deploy logs show a successful migrate and the server's listen URL, and the app opens from your Shopify admin, you're wired up.
Step 4: Run your first payout
- Open the app from your Shopify admin sidebar.
-
Upload a CSV (or paste rows directly) in the format:
wallet_address,amount. Each row is one affiliate. - Review the batch. You'll see every recipient, the total USDC, and the 0.3% protocol fee itemized before you sign anything.
- Connect your wallet — MetaMask or Coinbase Smart Wallet.
- Approve USDC for the batch total (one approval).
- Execute. One transaction on Base pays every recipient. Settlement is near-instant, and the transaction hash links straight to BaseScan.
Your payout history is saved in the app, so month-over-month affiliate payments become a two-minute task: export your affiliate report as CSV, upload, execute.
What this costs
- Base gas: typically under a cent for the whole batch
- Protocol fee: 0.3% of the batch total, collected on-chain by the batch contract
- Hosting: Railway's hobby tier + Supabase free tier cover a single-store deployment
Compare that to per-recipient fees on traditional payout rails, and the math gets very favorable very quickly once you're paying more than a handful of people.
Use cases beyond affiliates
The CSV-in, batch-out model fits anywhere you pay multiple people regularly:
- Creator/UGC payouts for content programs
- Supplier payments to international vendors who accept stablecoins
- Referral and ambassador programs
- Revenue splits between co-founders or collaborators
Wrapping up
You now have a self-hosted, open-source crypto payout system living inside your Shopify admin. No custodial platform, no per-recipient fees, no geography restrictions — just a CSV and one transaction.
- ⭐ Repo: github.com/plagtech/spraay-shopify
- 💧 Spraay Protocol: spraay.app — batch payment infrastructure on Base, Ethereum, Solana, and more
- 🐦 Questions? Reach out @Spraay_app
If you deploy it, open an issue or PR — contributions welcome.
Top comments (0)