Core guides
Connect, payments & Pro auth
Complete guide to Connect with OpenPay (OAuth 2.0), PayButton charges, partner payouts, OpenPay → Pro inbound top-up, and every OpenPay Pro wallet sign-in method.
Developer portal
Partner API · openpy.space
Create an app, copy Client ID + API key, set your domain for redirects, then ship Sign in, transfers, or PayButton.
- 1Register appClient ID + opk_ key
- 2Add domainAuto-fill callbacks
- 3Sign in / payAuth · PayButton
- 4Go liveSecrets on server
Portal
OpenPay Partner API portal
Use the official portal to register apps, manage keys, and follow the setup tutorial (Auth, Transfers, PayButton, Copy-paste, Reference).
- Portal: https://openpy.space/partner-api
- Auth tutorial: https://openpy.space/openpay-auth
- Redirect auto-fill registers
/auth/openpay/callbackand/openpay/connect/callback - Never put
opk_in the browser — exchange codes on your server only
AI tools
AI Partner Pack
Merchants
Pro Pay · Merchant checkout
pro_xfer: to credit a Pro @username / 0x.A · Charges
POST /charges → PayButton → poll paid
B · Inbound
Credit merchant Pro @user / 0x after paid
C · Deep-link
/topup then /pay/@merchant
OpenPay QR
QR Pay · method openpay_pro
On OpenPay QR Pay / checkout, add method openpay_pro so merchants show a QR that pays via OpenPay Balance and credits an OpenPay Pro receive wallet.
Method id: openpay_pro
Label: OpenPay Pro
Settle: POST /charges → poll paid → POST inbound
Note: pro_xfer:@shop:r_order_9001
Receive: @username and/or 0x…Top Up
OpenPay Pro payment methods
/topup — do not embed provider API keys in your app.| Method | Label | Description |
|---|---|---|
| pi | Pi Network (π) | Pay with Pi · live π price → OUSD ($1) credited instantly |
| openpay_balance | OpenPay Balance | Pay from your connected OpenPay account · real debit |
| moonpay | MoonPay | Card / Apple Pay / Google Pay · MoonPay → OUSD |
| usdc | USDC Pay | Pay with USDC · MoonPay Commerce → OUSD |
| helio | Crypto Deposit | SOL / crypto · MoonPay Commerce → OUSD |
| solana_pay | Solana Pay | Commerce Kit · wallet connect, PaymentButton, Solana Pay QR → OUSD |
| circle_mint | Circle Deposit | Circle Mint · USDC payin (payment intent + list payments) → OUSD |
| cash_pay | Pay with CASH | Phantom CASH (Solana SPL) · ledger balance or Solana Pay QR → OUSD 1:1 |
| wallet_ousd | Wallet OUSD | Pay with your OpenPay Pro OUSD balance · buy any token |
| wallet_usdt | Wallet USDT | Pay with your OpenPay Pro USDT balance → OUSD 1:1 |
| wallet_usdc | Wallet USDC | Pay with your OpenPay Pro USDC balance → OUSD 1:1 |
| wallet_sol | Wallet SOL | Pay with your OpenPay Pro SOL balance · live Solana price → OUSD |
| banxa_apple_pay | Apple Pay | Banxa · Apple Pay (Face ID / Touch ID) → crypto settle → OUSD |
| banxa_google_pay | Google Pay | Banxa · Google Pay → crypto settle → OUSD |
| banxa_card | Card | Banxa · debit / credit card → crypto settle → OUSD |
| banxa_bank | Bank Transfer | Banxa · bank transfer (ACH / SEPA / Faster Payments / PayID) → OUSD |
| onramp | Onramp.money | Local bank rails (UPI / IMPS / SEPA / bank transfer) · onramp & offramp widget → OUSD |
| paymongo | QR Ph & e-wallets | PayMongo · GCash, Maya, GrabPay, banks · scan QR Ph → OUSD |
| paypal | PayPal | PayPal, Pay Later, Venmo or card · approve → OUSD |
| scan_pay | Scan to pay | Multi-chain QR · SOL / USDC / USDT / CASH stables → verify TX → OUSD on OpenLedger |
# Buyer funds with full Pro methods, then pays merchant
https://openpaypro.space/topup
https://openpaypro.space/pay/@shop?amount=250&asset=OUSD¬e=order_9001Exchanges
List OUSD on OpenPay Network
Exchanges integrate OUSD as a network asset: network id openpay, Partner Transfer for deposit / withdraw, Pro inbound for Pro wallets, Ledger for audit. OUSD is a ledger dollar (no public ERC-20 mint).
Step 1
Create a partner app
- Open Apps & keys → Register app.
- Copy the
opk_live_…API key immediately (shown once). Save the Client ID (UUID). - Enter only your domain (e.g.
www.yourapp.com) and click Auto-fill & save for redirect URIs. - Or register exact URIs manually, e.g.
https://yourapp.com/openpay/callback
OPENPAY_CLIENT_ID="your-client-uuid"
OPENPAY_PARTNER_API_KEY="opk_live_..."
OPENPAY_PARTNER_API_BASE="https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api"
OPENPAY_REDIRECT_URI="https://yourapp.com/openpay/callback"Never expose the partner API key in the browser — backend only.
Step 2
Connect with OpenPay
profile, balance. User lands on Authorize, signs in, Allow → your callback receives opc_….Authorize URL
https://openpy.space/connect
?client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/openpay/callback
&scope=profile%20balance
&state=RANDOM_CSRF_TOKENDrop-in Connect button
<a href="https://openpy.space/connect?client_id=YOUR_CLIENT_ID&redirect_uri=https://yourapp.com/openpay/callback&scope=profile%20balance&state=xyz"
style="display:inline-flex;align-items:center;gap:8px;background:#1652f0;color:#fff;
padding:12px 20px;border-radius:10px;font-weight:600;text-decoration:none;">
Connect with OpenPay
</a>Callback
# Success
https://yourapp.com/openpay/callback?code=opc_...&state=...
# Cancel
https://yourapp.com/openpay/callback?error=access_denied
# Verify state matches what you storedExchange code (server)
curl -X POST "https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/oauth/token" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "opc_...",
"redirect_uri": "https://yourapp.com/openpay/callback",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "opk_live_YOUR_KEY"
}'User APIs (Bearer opa_live_…)
curl -H "Authorization: Bearer opa_live_..." https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/user/me
curl -H "Authorization: Bearer opa_live_..." https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/user/balance# Typical /user/me response
{
"user_id": "...",
"account_number": "OP...",
"full_name": "...",
"username": "...",
"avatar_url": "...",
"balance": 12.34,
"currency": "OUSD",
"scope": "profile balance"
}Step 3
OpenPay Pro — all sign-in methods
OpenPay
/authpiOAuth 2.0 Connect — profile + balance scopes
- API
- GET/POST /api/public/openpay-auth
- Callback
- /auth/openpay/callback
- Env
- OPENPAY_OAUTH_CLIENT_ID · OPENPAY_PARTNER_API_KEY
Telegram
/authpiTelegram Login OIDC + PKCE (oauth.telegram.org)
- API
- GET/POST /api/public/telegram-auth
- Callback
- /auth/telegram/callback
- Env
- TELEGRAM_CLIENT_ID · TELEGRAM_CLIENT_SECRET
Solana
/authpiSign In With Solana (Phantom / Wallet Standard)
- API
- GET/POST /api/public/solana-auth
- Callback
- —
- Env
- OPENPAY_AUTH_PASSWORD_SECRET (or SOLANA_…)
Pi Network
/authpiPi Browser SDK or Pi OAuth (external browser)
- API
- POST /api/public/pi-auth
- Callback
- /auth/pi/callback
- Env
- VITE_PI_CLIENT_ID
Phantom
/authpiExtension · Google · Apple via Phantom Connect
- API
- Phantom SDK
- Callback
- /auth/callback
- Env
- VITE_PHANTOM_APP_ID (+ Portal allowlists)
WalletConnect
/authpiEVM SIWE (personal_sign) → Supabase session
- API
- GET/POST /api/public/walletconnect-auth
- Callback
- —
- Env
- Auth secret · optional WCP Pay keys
MetaMask
/authpiEmbedded Wallets social OAuth (Web3Auth JWKS)
- API
- POST /api/public/web3auth-auth
- Callback
- Web3Auth modal / social chips
- Env
- VITE_WEB3AUTH_CLIENT_ID · WEB3AUTH_CLIENT_SECRET · JWKS
Shared server secrets
OPENPAY_AUTH_PASSWORD_SECRET="long-random-string"
SUPABASE_URL="https://YOUR_PROJECT.supabase.co"
SUPABASE_PUBLISHABLE_KEY="eyJ..."
SUPABASE_SERVICE_ROLE_KEY="eyJ..." # server only — admin.createUserMetaMask Embedded (Web3Auth)
VITE_WEB3AUTH_CLIENT_ID="your-client-id"
WEB3AUTH_CLIENT_ID="your-client-id"
WEB3AUTH_CLIENT_SECRET="your-secret" # never VITE_
WEB3AUTH_JWKS_URL="https://api-auth.web3auth.io/.well-known/jwks.json"Phantom Portal
VITE_PHANTOM_APP_ID="your-app-id"
# Allowlist each origin + /auth/callback in Phantom PortalClient starters
import { startOpenPaySignIn } from "@/lib/openpay-auth"
import { startSolanaSignIn } from "@/lib/solana-auth"
import { startWalletConnectSignIn } from "@/lib/walletconnect-auth"
import { signInWithPi } from "@/lib/pi-network"
await startOpenPaySignIn({ redirectTo: "/dashboard" })
await startSolanaSignIn({ redirectTo: "/dashboard" })
await startWalletConnectSignIn({ redirectTo: "/dashboard" })- Never expose
opk_,wcp_,WEB3AUTH_CLIENT_SECRET, or service role in the browser - Verify OAuth
stateon every callback - Web3Auth: always check JWT
aud= your Client ID - Verify Solana / SIWE signatures server-side before issuing credentials
Step 4
Accept OpenPay balance payments
Buyer pays from their OpenPay wallet. Funds credit your partner-app owner. Prefer PayButton /charges; use /pay/@username for hosted tag payments.
A · PayButton charge
curl -X POST "https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/charges" \
-H "Authorization: Bearer opk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 19.99,
"currency": "OUSD",
"description": "Order #1234",
"reference": "order_1234",
"success_url": "https://yourapp.com/thanks",
"cancel_url": "https://yourapp.com/cart"
}'
# → { id, checkout_url, status, expires_at } · TTL 2 hours
# → redirect buyer to checkout_url or https://openpy.space/paybutton/CHARGE_IDPoll / cancel
# Status: created | paid | canceled | expired
curl -H "Authorization: Bearer opk_live_YOUR_KEY" \
https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/charges/CHARGE_ID
curl -X POST -H "Authorization: Bearer opk_live_YOUR_KEY" \
https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/charges/CHARGE_ID/cancel
# List
curl -H "Authorization: Bearer opk_live_YOUR_KEY" \
"https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/charges?status=paid"B · Hosted pay tag
https://openpy.space/pay/YOUR_USERNAME
?amount=25.00
¤cy=OUSD
¬e=order_1234
&success_url=https://yourapp.com/thanks
&cancel_url=https://yourapp.com/cart
# Success return: ?openpay_return=1&openpay_ref=order_1234&openpay_tx=...
# Cancel return: ?openpay_cancel=1Pay flow
- Open pay link → amount + note
- Pay → balance check → debit OUSD → thank-you
- Redirect to your
success_url - Backend verifies
paid, then fulfills
Step 5
Payouts — Partner transfers
Idempotency-Key. Prefer OP… account numbers over @username.# Resolve account
curl -H "Authorization: Bearer opk_live_YOUR_KEY" \
https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/accounts/@satoshi
# Send payout
curl -X POST "https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/transfers" \
-H "Authorization: Bearer opk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"to":"OP...","amount":10.00,"note":"Payout"}'
# Partner treasury
curl -H "Authorization: Bearer opk_live_YOUR_KEY" https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/me
curl -H "Authorization: Bearer opk_live_YOUR_KEY" https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/balanceStep 6
OpenPay → OpenPay Pro (inbound / top-up)
Credit a Pro wallet after an OpenPay payment using note routing + inbound API.
Note: pro_xfer:@alice:r_ref or pro_xfer:0x…:r_ref
curl -X POST "https://openpaypro.space/api/public/openpay/inbound" \
-H "Authorization: Bearer opk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "@alice",
"amount": 25,
"openpay_tx_id": "UNIQUE_TX_ID",
"note": "pro_xfer:@alice:r_1",
"from_username": "bob"
}'Idempotent on openpay_tx_id. Pro users can also Receive → Create OpenPay receive link. Product deep-link: /topup.
Step 7
Minimal Node example
const API = process.env.OPENPAY_PARTNER_API_BASE || "https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api";
const KEY = process.env.OPENPAY_PARTNER_API_KEY; // opk_live_…
const CLIENT_ID = process.env.OPENPAY_CLIENT_ID;
const REDIRECT = process.env.OPENPAY_REDIRECT_URI;
export function connectUrl(state) {
const u = new URL("https://openpy.space/connect");
u.searchParams.set("client_id", CLIENT_ID);
u.searchParams.set("redirect_uri", REDIRECT);
u.searchParams.set("scope", "profile balance");
u.searchParams.set("state", state);
return u.toString();
}
export async function exchangeCode(code) {
const res = await fetch(`${API}/oauth/token`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "authorization_code",
code,
redirect_uri: REDIRECT,
client_id: CLIENT_ID,
client_secret: KEY,
}),
});
if (!res.ok) throw new Error(await res.text());
return res.json(); // { access_token: "opa_live_...", ... }
}
export async function createCharge({ amount, reference, success_url, cancel_url }) {
const res = await fetch(`${API}/charges`, {
method: "POST",
headers: {
Authorization: `Bearer ${KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount,
currency: "OUSD",
description: reference,
reference,
success_url,
cancel_url,
}),
});
if (!res.ok) throw new Error(await res.text());
return res.json(); // { id, checkout_url, ... }
}
export async function transfer({ to, amount, note, idempotencyKey }) {
const res = await fetch(`${API}/transfers`, {
method: "POST",
headers: {
Authorization: `Bearer ${KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey,
},
body: JSON.stringify({ to, amount, note }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}Step 8
API cheat sheet
| Method | Path | Auth |
|---|---|---|
| GET | /me | opk_ |
| GET | /balance | opk_ |
| GET | /accounts/:id | opk_ |
| POST | /transfers | opk_ + Idempotency-Key |
| GET | /transfers | opk_ |
| POST | /charges | opk_ |
| GET | /charges/:id | opk_ |
| GET | /charges?status= | opk_ |
| POST | /charges/:id/cancel | opk_ |
| POST | /oauth/token | body client_secret |
| GET | /user/me | opa_ |
| GET | /user/balance | opa_ |
| POST | /api/public/openpay/inbound | opk_ / opdk_ (Pro) |
Base: https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api
Full reference: /docs/api · OpenAPI: /api/public/docs/openapi
Step 9
Public Ledger API
Append-only public ledger of OpenPay Pro transactions. Auth with x-api-key or Authorization: Bearer.
GET https://openpaypro.space/api/public/ledger/entries?limit=50&asset=OUSD&type=buy
x-api-key: YOUR_LEDGER_KEYTypes: send · receive · buy · sell · swap · mint · reward. Docs: /docs/ledger.
Step 10
WalletConnect Pay
Pro can pay WalletConnect Pay merchant links from the in-app scanner (/scan → /wc-pay).
- Merchant creates a WC Pay link via WalletConnect Pay Merchant API
- User scans QR or opens the link in Pro
- Requires server env
WALLETCONNECT_PAY_API_KEY
This is a payer integration inside Pro — not a partner webhook.
Step 11
Charges polling (no partner webhooks)
Confirm payments by polling GET /charges/:id. There is no partner-facing payment webhook today.
GET https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api/charges/CHARGE_ID
Authorization: Bearer opk_live_YOUR_KEY
# Fulfill only when status === "paid"Internal webhooks (MoonPay, KYC, Circle) power Pro itself and are not exposed to third-party apps.
Step 12
OpenNFT mint (high level)
Pro users mint collectibles on OpenPay OpenNFT via a connected OpenPay account (Settings → Connect OpenPay). Marketplace: openpy.space/web3/nft.
- User must link OpenPay OAuth in Pro first
- Mint calls OpenPay partner NFT APIs server-side
- Ledger type
mintis recorded on the Pro Ledger API
Step 13
Errors & launch checklist
401 / invalid_client — bad or quoted opk_live_… / wrong client_id
redirect_uri not registered — must match allowlist exactly
403 — origin not whitelisted
400 — validation, insufficient balance
Scopes — Connect uses profile and balance
- ✓Partner app + secrets on server only (openpy.space/partner-api)
- ✓Redirect URIs registered (exact match)
- ✓Connect → token → store opa_live_ server-side
- ✓Charges or /pay/@tag with success/cancel URLs
- ✓Poll until paid; transfers use Idempotency-Key
- ✓Inbound (if used) unique openpay_tx_id + pro_xfer note
FAQ
OpenPay Pro FAQ
How do I connect OpenPay to Pro?
Settings → Connected → Connect OpenPay (OAuth). You can then send/receive via OpenPay balance and mint OpenNFTs.
Where do trade fees go?
Platform fees credit the admin fee wallet — typically @openpay.
Where do merchants receive Pro earnings?
Use /docs/pro-pay — charges → inbound with pro_xfer: to @username / 0x. QR Pay method: openpay_pro.
Is there a partner webhook?
Not yet — poll GET /charges/:id after payment return.