APIs

Partner Transfer API

HTTP reference for transfers, PayButton charges, account resolve, and Connect OAuth — the backbone for exchanges, merchants, and apps.

Portal: https://openpy.space/partner-api · Raw markdown: /api/public/docs/partner-transfer

01

Authentication

Authorization: Bearer opk_live_YOUR_KEY

# Never expose opk_live_ in browsers or mobile apps.
# Register redirect URIs in the Partner portal (exact match).

Base URL: https://araojncyittkahvvpdrn.supabase.co/functions/v1/partner-transfer-api

02

Account & balance

GET /me
GET /balance
GET /accounts/:identifier   # @username | OP… | email
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/accounts/@satoshi

03

Transfers (send)

Debits the key owner’s OpenPay balance and credits the recipient. Use Idempotency-Key (header or body) to safely retry.

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":"@username","amount":10.00,"note":"Payout"}'

Body: { "to", "amount", "note?", "idempotency_key?" }. List: GET /transfers

04

PayButton charges (accept payment)

Create a charge → redirect to checkout_url → poll status. Partner webhooks are not available — poll GET /charges/:id. Charges expire in 2 hours.

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 }

GET  /charges/:id          # created | paid | canceled | expired
GET  /charges?status=paid
POST /charges/:id/cancel
<a href="https://openpy.space/paybutton/CHARGE_ID">
  Pay with OpenPay
</a>

05

Connect with OpenPay (OAuth 2.0)

  1. Register exact redirect URIs in the Partner portal.
  2. Send users to https://openpy.space/connect?client_id=…&redirect_uri=…&scope=profile%20balance&state=…
  3. Exchange code for opa_live_… on your backend (codes expire in 10 minutes, single-use).
  4. Call GET /user/me and GET /user/balance with the user token (tokens last ~30 days).
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_APP_ID",
    "client_secret": "opk_live_YOUR_KEY"
  }'
# → { access_token: "opa_live_...", token_type, expires_in, scope, user_id }

Narrative guide: /docs/openpay

06

Error shapes

StatusMeaning
401Missing / invalid / revoked key
403Origin not whitelisted
404Recipient / charge not found
400Validation (amount, insufficient balance, …)

Expanded catalog: /docs/errors

07

Limits & gaps

  • No partner payment webhooks yet — poll charges after return from checkout.
  • No public partner OpenDEX swap HTTP API — deep-link to Pro swap.
  • OUSD is ledger-API based — no public EVM/SPL contract address.