v3.1
API Reference

MyRoPay API

A complete payments infrastructure: send money, collect payments, hold funds in escrow, pay bills, link bank accounts, and build full checkout experiences — all through a single unified REST API.

Personal API https://myropay.com/app/api/ Checkout API https://app.myropay.com/checkout/api/
ℹ️
All responses are JSON. Timestamps are UTC ISO 8601. Amounts are in the major currency unit (e.g. dollars, not cents) unless a note says otherwise. HTTPS is always required.
Security

Authentication

MyRoPay uses short-lived JWT access tokens (15 min) paired with long-lived refresh tokens (30 days). Every authenticated request sends the access token as a Bearer header.

# Every authenticated request
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

Your app should proactively refresh 2 minutes before expiry, or immediately on any 401 response. The SDK (app.js) handles this automatically via setupTokenRefresh().

Access tokens expire in 15 minutes. Call POST /auth.php?action=refresh with your refresh token to get a new pair. Tokens rotate on every refresh — store the new refresh token immediately.
🔑
Personal API keys (mrp_...) are an alternative to JWTs for server-to-server automations. They work the same way in the Authorization: Bearer header. Generate yours in the app under More → API & Integration.
Reference

Errors & Rate Limiting

HTTP CodeMeaningCommon cause
200Success
400Bad RequestMissing or malformed fields
401UnauthorizedMissing, expired, or invalid token
403ForbiddenKYC required, wrong account type, PIN wrong
404Not FoundResource not found or doesn't belong to you
409ConflictDuplicate idempotency key within 24h
429Rate LimitedToo many requests — see retry_after
503UnavailableDatabase momentarily unavailable
// All errors follow this shape
{ "success": false, "message": "Insufficient balance.", "retry_after": 42 }

Idempotency. Financial endpoints accept an optional X-Idempotency-Key header. Send a UUID — repeat calls within 24 h return the original response without re-executing the transaction.

X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

Rate limits. Per-IP defaults: login 10/5 min · register 5/5 min · OTP resend 3/5 min · general 300/min. Headers on limited responses: X-RateLimit-Remaining, X-RateLimit-Reset.

Client Library

Checkout SDK

One script tag. Four integration modes. No gateway keys in your frontend — all keys remain on the server. Works on any HTML page or framework.

Install

Add to any HTML page. The global MyRoPay object is available immediately after the script loads.

<script src="https://app.myropay.com/myropay.js"></script>
Option 1 — Modal popup (recommended)
MyRoPay.checkout({
  publicKey:       'pk_live_...',
  amount:          5000,          // major unit — ₦5000, not 500000 kobo
  currency:        'NGN',
  orderRef:        'ORD-001',
  description:     'Premium plan',
  customer:        { email: 'buyer@email.com', name: 'John Doe' },
  escrow:          true,
  escrowCondition: 'Software delivered and tested',
  onSuccess:  (data) => console.log('Paid:', data),
  onClose:    ()     => console.log('Closed'),
  onError:    (msg)  => console.error(msg),
});
Option 2 — Redirect (server-side session)
// Node.js / PHP backend — use your SECRET key
const session = await MyRoPay.createSession({
  publicKey: 'sk_live_...',
  amount: 15000, currency: 'NGN',
  orderRef: 'ORD-002',
  successUrl: 'https://yoursite.com/thanks',
  cancelUrl:  'https://yoursite.com/cart',
});
res.redirect(session.checkout_url);
Option 3 — Inline embed
const { destroy } = await MyRoPay.inline({
  container: '#checkout-box',
  publicKey: 'pk_live_...',
  amount: 2500, currency: 'NGN',
});
Option 4 — Pre-built button
MyRoPay.createButton({
  container: '#pay-here',
  label: 'Pay with MyRoPay',
  publicKey: 'pk_live_...',
  amount: 5000, currency: 'NGN',
});
Verify a payment (always server-side)
const result = await MyRoPay.verify(sessionId, 'sk_live_...');
if (result.status === 'completed' && result.amount === expectedAmount) {
  // fulfil order
}
ParameterTypeNotes
publicKeyreqpk_live_ or pk_test_ merchant key
amountreqMajor unit (₦5000, $50.00)
currencyreqISO 4217: NGN, USD, GHS, KES
orderRefoptYour internal order ID stored on the session
customer.emailoptPre-fills the buyer email on the checkout page
escrowoptBoolean — requires merchant escrow feature enabled
escrowConditionoptPlain-text delivery condition shown to buyer
escrowDeadlineDaysoptDays before auto-dispute; 1–90, default 7
paymentMethodsoptArray — card, bank_transfer, ussd, mobile_money, wallet
successUrl / cancelUrloptRedirect URLs for non-modal flows
brandColor / brandLogooptCustomize the checkout page appearance
expiresInMinutesoptSession TTL (5–10080 min, default 1440)
Core API

Auth Endpoints

Identity & Session
POST/auth.php?action=registerPublic

Create an account. Returns access + refresh token immediately — no separate login step needed.

Request
Response
{
  "first_name":   "Dami",
  "last_name":    "Ehimare",
  "email":        "dami@example.com",
  "phone":        "+2348100000001",
  "password":     "StrongPass1!",
  "account_type": "personal",  // "personal" | "business"
  "country_code": "NG",        // ISO 3166-1 alpha-2
  "referral_code":"DAMI1234"  // optional
}
{
  "success": true,
  "token":         "eyJhbGci...",     // 15-min access token
  "refresh_token": "a3f2b9...",      // 30-day refresh token
  "user": {
    "id": 42, "uuid": "4c758d...",
    "first_name": "Dami", "last_name": "Ehimare",
    "myrotag": "damiehimare",
    "email": "dami@example.com",
    "currency": "NGN", "currency_symbol": "₦",
    "country_code": "NG", "country": "Nigeria",
    "kyc_status": "pending", "kyc_level": 0,
    "pin_set": false, "email_verified": false,
    "account_type": "personal",
    "referral_code": "DAMI7A2C"
  }
}
POST/auth.php?action=loginPublic

Authenticate with email + password. Include totp_code if 2FA is enabled on the account.

{ "email": "dami@example.com", "password": "StrongPass1!", "totp_code": "123456" }
POST/auth.php?action=refreshPublic

Exchange a refresh token for a new access + refresh pair. Tokens rotate on every use — store the new refresh token immediately.

{ "refresh_token": "b7d3e1..." }
GET/auth.php?action=meJWT

Returns the authenticated user's full profile: balance, KYC status, pin_set, referral code, and unread notification count.

POST/auth.php?action=update-myrotagJWT

Change your @myrotag. Maximum 3 changes per year. Body: { "myrotag": "newhandle" }

Password & Email
POST/auth.php?action=verify-email-otpJWT

Verify email address using the 6-digit OTP sent at registration. Body: { "otp": "123456" }

POST/auth.php?action=forgot-passwordPublic

Trigger a password reset email. Always returns 200 to prevent user enumeration. Body: { "email": "..." }

POST/auth.php?action=reset-passwordPublic

Complete the reset. Body: { "token": "...", "password": "NewPass1!" }

Two-Factor Authentication
POST/auth.php?action=setup-2faJWT

Generate a TOTP secret and QR code URI. Returns secret and qr_url. The user scans it in an authenticator app then confirms via confirm-2fa.

POST/auth.php?action=confirm-2faJWT

Activate 2FA by verifying the first TOTP code. Returns 10 single-use recovery codes — store immediately. Body: { "code": "123456" }

POST/auth.php?action=disable-2faJWT

Disable 2FA by confirming with a current TOTP code. Body: { "code": "123456" }

Core API

Wallet & Transfers

Query balances, send money to any @myrotag or email, request funds, and access full transaction history with search and filters.

GET/wallet.php?action=balanceJWT

Primary wallet balance plus locked funds (in active escrows) and monthly flow totals.

{
  "success":     true,
  "balance":     "42910.24",
  "locked":      "1200.00",   // held in active escrows
  "currency":    "NGN",  "symbol": "₦",
  "monthly_in":  "55000.00",
  "monthly_out": "12090.00"
}
POST/wallet.php?action=transferJWT

Send money to any user. The recipient field accepts @myrotag, email, or phone. Requires PIN or active biometric session. KYC Level 0 limit: $200 per transfer.

Sender debited + fee
Recipient credited
Both notified
Receipt returned
Request
Response
{
  "recipient": "@alexvance",  // @tag | email | phone
  "amount":    1500,
  "pin":       "1234",        // or "biometric_session": "..."
  "note":      "Thanks for dinner"
}
{
  "success":        true,
  "message":        "Transfer of ₦1,500 to @alexvance successful!",
  "transaction_id": "4c758d30-60a6-...",
  "new_balance":    "41395.86",
  "receipt": {
    "amount": "1500.00", "fee": "0.10",
    "from": { "name": "Dami E.", "tag": "@damiehimare" },
    "to":   { "name": "Alex V.", "tag": "@alexvance" },
    "status": "completed", "timestamp": "2025-04-23T14:20:00Z"
  }
}
GET/wallet.php?action=lookup-user&q=@alexvanceJWT

Find a user by @myrotag, email, or phone. Returns id, first_name, last_name, myrotag, avatar, currency.

POST/wallet.php?action=requestJWT

Request payment from another user. They receive an in-app notification with a one-tap pay button. Body: { "target_email": "...", "amount": 500, "note": "..." }

POST/wallet.php?action=fulfill-requestJWT

Pay a received payment request. Body: { "request_id": 14, "pin": "1234" }

GET/wallet.php?action=historyJWT

Paginated transaction history with full-text search and type filters.

Query paramDescription
pageoptPage number (default 1)
limitoptPer page: 5–50 (default 20)
typeoptdeposit · withdrawal · transfer_in · transfer_out · bill_payment · escrow_lock · escrow_release
qoptFull-text search across reference, description, sender/receiver name
from / tooptDate range filter — YYYY-MM-DD
Core API

Deposits

Add money to a wallet. The server selects the best gateway automatically based on the user's country — no public keys are ever sent to the browser.

Use action=init for all integrations. Gateway selection is automatic: Nigeria → Paystack inline, Africa → Flutterwave hosted link, Everywhere else → MyRoPay Checkout session.
POST/deposit.php?action=initJWT

Smart gateway init. Returns different payloads depending on the selected gateway. Optionally pass method to force a specific gateway.

Request
Response variants
{
  "amount":   5000,
  "currency": "NGN",
  "method":   "auto"  // "auto"|"paystack"|"flutterwave"|"checkout"
}
// Nigeria → Paystack  (access_code only, no public key exposed)
{ "gateway":"paystack", "access_code":"0peioxfhpn", "reference":"MRP_PS_3F2A1B8C" }

// Africa → Flutterwave  (hosted payment link, no key)
{ "gateway":"flutterwave", "payment_link":"https://checkout.flutterwave.com/...", "tx_ref":"MRP_FLW_7C4E2A" }

// Global → MyRoPay Checkout session
{ "gateway":"checkout", "checkout_url":"https://app.myropay.com/pay?session=cs_live_...", "session_id":"cs_live_4f2b..." }
POST/deposit.php?action=verify-paystackJWT

Call after PaystackPop onSuccess fires. Body: { "reference": "MRP_PS_..." }. Returns new_balance.

POST/deposit.php?action=verify-flutterwaveJWT

Call after Flutterwave redirect. Body: { "tx_ref": "...", "transaction_id": "..." }.

POST/deposit.php?action=paystack-webhookSig-verified

Server-to-server event from Paystack. Validated using X-Paystack-Signature HMAC-SHA512. Register at: myropay.com/app/api/deposit.php?action=paystack-webhook

POST/deposit.php?action=flutterwave-webhookSig-verified

Server-to-server event from Flutterwave. Validated using VERIF-HASH header. Register at: myropay.com/app/api/deposit.php?action=flutterwave-webhook

Core API

Payouts

Withdraw to a local bank account, mobile money wallet, or PayPal. All withdrawals require verified KYC. Funds are debited immediately and processed within 24 hours.

GET/payout.php?action=list-banks&country=NGJWT

Supported banks for a given country code. NG uses Paystack's list; other countries use Flutterwave.

GET/payout.php?action=resolve-accountJWT

Verify an account number before adding it. Params: account_number, bank_code. Returns the account holder name (Nigeria only, powered by Paystack).

POST/payout.php?action=add-bankJWT

Save a bank account for future withdrawals. Account numbers are AES-256-CBC encrypted at rest. Body: { "bank_name", "bank_code", "account_number", "account_name" }

POST/payout.php?action=initiateJWT

Start a withdrawal. KYC must be verified. Fee: max($1.00, 1%). Funds are debited from the wallet immediately.

Request
Response
{
  "method":  "bank",   // "bank" | "paypal" | "mobile_money"
  "amount":  10000,
  "pin":     "1234",
  "details": { "bank_id": 3 }  // from /payout.php?action=my-banks
}
{
  "success":        true,
  "message":        "Withdrawal initiated. Processing within 24h.",
  "transaction_id": "7f3b9d...",
  "new_balance":    "32810.00"
}
Core API

Transactions

GET/transactions.php?action=listJWT

Paginated list. Query params: page, limit, type, q (search), from, to.

GET/transactions.php?action=detail&uuid={uuid}JWT

Single transaction with full sender and receiver names, @tags, avatars, and fee breakdown.

GET/transactions.php?action=exportJWT

Export up to 5,000 transactions as JSON. Date range params: from, to. Returns a file attachment.

Features

Escrow

Lock funds until delivery conditions are met. Either party can raise a dispute — MyRoPay reviews and resolves within 48 hours. Escrow fee: 1.5% of the locked amount.

Initiator creates + funds
Funds locked in wallet
Work delivered
Release or dispute
POST/escrow.php?action=createJWT

Create and fund an escrow in one step. Amount + 1.5% fee debited immediately and locked.

{
  "beneficiary": "@alexvance",  // @tag or email
  "amount":      50000,
  "title":       "Website redesign",
  "description": "5 pages, 2 revisions, delivered in 2 weeks",
  "due_date":    "2025-05-15",
  "pin":         "1234"
}
POST/escrow.php?action=releaseJWT

Release locked funds to the beneficiary. Only the initiator can call this. Body: { "uuid": "...", "pin": "1234" }

POST/escrow.php?action=disputeJWT

Raise a dispute. Either party can call this. Funds are frozen until resolved by MyRoPay admin. Body: { "uuid": "...", "reason": "...", "evidence": "https://..." }

POST/escrow.php?action=dispute-respondJWT

Submit your response to an open dispute. Body: { "dispute_uuid": "...", "response": "...", "evidence": "..." }

GET/escrow.php?action=listJWT

All escrows where you are initiator or beneficiary. Returns status, counterparty details, amounts, and any open dispute IDs.

Features

Bill Payments NG only

Pay airtime, data, electricity, cable TV, and internet bills for Nigerian users via Flutterwave's bill payment infrastructure.

GET/bills.php?action=categoriesJWT

Returns supported categories: AIRTIME, DATA_BUNDLE, POWERBI (electricity), DSTV, GOTV, STARTIMES, WATERBI, NETPLUSINC. Each category includes its valid billers.

POST/bills.php?action=validateJWT

Validate a customer number before payment (e.g. electricity meter, SmartCard number). Body: { "item_code": "...", "biller_code": "...", "customer": "12345678" }

POST/bills.php?action=payJWT
{
  "type":     "AIRTIME",
  "customer": "08012345678",
  "amount":   1000,
  "pin":      "1234"
}
Features

Savings Goals

Create named savings goals with target amounts, target dates, and optional automatic recurring contributions. Cron runs auto-saves daily.

POST/features.php?section=savings&action=createJWT
{
  "name":               "New MacBook",
  "target_amount":       450000,
  "target_date":         "2025-12-01",
  "auto_save":           true,
  "auto_save_amount":    15000,
  "auto_save_frequency": "monthly"  // "daily"|"weekly"|"monthly"
}
POST/features.php?section=savings&action=top-upJWT

Manually top up a goal from your wallet. Body: { "id": 3, "amount": 5000, "pin": "1234" }. Returns new_amount and progress percentage.

POST/features.php?section=savings&action=withdrawJWT

Withdraw funds from a goal back to your wallet. Body: { "id": 3, "amount": 5000, "pin": "1234" }

Features

Virtual Cards

Virtual Visa cards for online payments. KYC Level 1 required to create. Card numbers are AES-256-CBC encrypted at rest — only decrypted on explicit reveal with PIN.

POST/features.php?section=cards&action=createJWT

Create a new virtual card. Returns masked details only. Full number available via reveal. Body: { "pin": "1234" }

POST/features.php?section=cards&action=revealJWT

Decrypt and return full card number, CVV, and expiry. Requires PIN. Body: { "id": 1, "pin": "1234" }

POST/features.php?section=cards&action=freezeJWT

Toggle card freeze/unfreeze. Body: { "id": 1 }. Returns new status.

Compliance

KYC Verification

Three tiers of identity verification with increasing limits. Documents are reviewed by MyRoPay's compliance team within 24 hours.

LevelLabelDaily limitRequirement
0Starter$200 equiv.Email verified
1Standard$5,000Government ID + selfie
2Verified$50,000Address proof + BVN (NG)
GET/kyc.php?action=statusJWT

Returns current tier, document submission status per tier, and per-tier daily limits.

POST/kyc.php?action=uploadJWT

Submit a KYC document. Multipart form-data (not JSON). Max 5 MB per file. Accepted: JPEG, PNG, PDF.

POST /kyc.php?action=upload
Content-Type: multipart/form-data

doc_type: "govt_id"   # govt_id|selfie|proof_of_address|passport|drivers_license
tier:     1
document: <binary>
POST/kyc.php?action=submit-bvnJWT

Nigerian BVN verification. BVN is hashed (SHA-256) immediately on receipt — never stored in plain text. Body: { "bvn": "12345678901" }

Business

Invoices Business accounts

Create, send, and track professional invoices with line items, taxes, and payment links. Paid invoices credit your wallet automatically.

POST/business.php?section=invoices&action=createJWT
{
  "client_name":  "Acme Corp",
  "client_email": "billing@acme.com",
  "currency":     "NGN",
  "due_date":     "2025-05-30",
  "tax_rate":     7.5,
  "items": [
    { "description": "Logo design", "quantity": 1, "unit_price": 80000 },
    { "description": "Brand guide",  "quantity": 1, "unit_price": 45000 }
  ]
}

Returns uuid, invoice_number (e.g. INV-A3F2B901), subtotal, tax total, and grand total.

POST/business.php?section=invoices&action=sendJWT

Email the invoice PDF to the client. Changes status from draftsent. Body: { "uuid": "..." }

GET/business.php?section=invoices&action=listJWT

All invoices with status. Query param status: draft · sent · paid · overdue.

Business

Payroll Business accounts

Send salaries and payments to multiple MyRoPay users in a single request. Recipients receive funds instantly.

POST/business.php?section=payroll&action=createJWT
{
  "name": "April 2025 Payroll",
  "recipients": [
    { "myrotag": "@alice", "amount": 250000, "note": "April salary" },
    { "myrotag": "@bob",   "amount": 180000, "note": "April salary" }
  ]
}

Wallet must cover the total. Returns batch_id, total_amount, and per-recipient status.

GET/business.php?section=payroll&action=listJWT

Payroll batches with totals, recipient count, and completion status.

Business

Webhook Management Business accounts

POST/business.php?section=webhooks&action=createJWT
{
  "name":   "Production endpoint",
  "url":    "https://yoursite.com/hooks/myropay",
  "events": ["payment.success", "escrow.released", "payout.completed"]
}

Returns a secret for HMAC verification — shown once, store it immediately.

POST/business.php?section=webhooks&action=testJWT

Send a test ping to your endpoint. Body: { "id": 5 }. Returns the HTTP status code your server responded with.

Business

Analytics Business accounts

GET/analytics.php?action=summary&days=30JWT

KPI summary for last N days (7 · 30 · 90). Returns revenue, spending, net, transaction counts, payment link stats, invoice totals, and payroll disbursements.

GET/analytics.php?action=volume-chart&days=30JWT

Daily inflow/outflow series. Returns array of { "date": "2025-04-01", "inflow": 55000, "outflow": 12000 }

GET/analytics.php?action=top-sendersJWT

Top 10 users by total amount sent to your account in the last 90 days.

GET/analytics.php?action=transaction-types&days=30JWT

Breakdown of transaction volume by type (deposit, transfer, escrow, bill, withdrawal) for charting.

Platform

Checkout API

Create and manage checkout sessions directly from your backend using your merchant secret key. Supports standard, instalment, donation, and subscription payment types.

Checkout API Base https://app.myropay.com/checkout/api/
Create a session
POST/sessions.phpSecret Key
Request
Response
POST https://app.myropay.com/checkout/api/sessions.php
Authorization: Bearer sk_live_...

{
  "amount":          15000,
  "currency":        "NGN",
  "order_ref":       "ORD-042",
  "description":     "Premium plan — 1 month",
  "session_type":    "standard",  // standard|instalment|donation|subscription
  "payment_methods": ["card", "bank_transfer", "ussd"],
  "customer":        { "email": "buyer@example.com", "name": "Alex Vance" },
  "success_url":     "https://yoursite.com/thanks?order=ORD-042",
  "cancel_url":      "https://yoursite.com/cart",
  "escrow":          false,
  "brand_color":     "#5B8DF5",
  "expires_in":      1440     // minutes — default 1440 (24h)
}
{
  "session_id":   "cs_live_4f2b9a3c8e1d...",
  "checkout_url": "https://app.myropay.com/pay?session=cs_live_4f2b...",
  "amount":       15000,
  "currency":     "NGN",
  "status":       "pending",
  "expires_at":   "2025-04-24T14:00:00Z"
}
GET/sessions.php?session_id={id}Secret Key

Verify a session after payment. Always verify server-side before fulfilling an order. Check status === "completed" and confirm amount matches your expected value.

Merchant App Keys
POST/apps.php?action=createJWT

Create a merchant app and get pk_live_ / sk_live_ keys. Limited to 5 apps per account.

{
  "app_name":      "My Store",
  "app_url":       "https://mystore.com",
  "support_email": "support@mystore.com",
  "mode":          "live"   // "live"|"test"
}
🔒
Never put your secret key (sk_live_) in frontend JavaScript or expose it in a git repository. Use it only on your backend server. The public key (pk_live_) is safe for the browser with myropay.js.
Platform

Bank Account Linking NG only

Link Nigerian bank accounts via Mono to access real-time balance data and bank statements for financial analysis and income verification.

GET/mono.php?action=initJWT

Returns public_key and user_ref. Pass these to the Mono Connect widget on your frontend.

POST/mono.php?action=exchangeJWT

Exchange the Mono auth code returned by the Connect widget. Stores the linked account and returns account details. Body: { "code": "mono_auth_code_..." }

GET/mono.php?action=statement&account_id={id}JWT

Bank statement for a linked account. Returns last 90 days of transactions.

POST/mono.php?action=unlinkJWT

Remove a linked bank account. Body: { "account_id": "..." }

Platform

Notifications

GET/notifications.php?action=listJWT

Paginated notifications with unread count. Query param: page.

GET/notifications.php?action=unread-countJWT

Returns { "count": 4 } — fast endpoint for polling badge counts.

POST/notifications.php?action=mark-all-readJWT

Mark all notifications as read. No body required.

Platform

Account Settings

POST/settings.php?action=update-profileJWT

Update display name and phone. Body: { "first_name", "last_name", "phone" }

POST/settings.php?action=change-passwordJWT

Body: { "current_password", "new_password" }. Triggers a security alert email and invalidates all other sessions.

POST/settings.php?action=set-pinJWT

Set or change the 4-digit transaction PIN. Body: { "pin": "1234", "confirm_pin": "1234" }

POST/settings.php?action=setJWT

Toggle a preference flag. Body: { "key": "push_notifications", "value": 1 }. Valid keys: push_notifications · email_notifications · login_alerts · weekly_digest_enabled · roundup_enabled.

GET/settings.php?action=sessionsJWT

List all active login sessions with device, browser, IP, and last active time.

POST/settings.php?action=revoke-all-sessionsJWT

Log out all other sessions except the current one. No body required. Good for "logout everywhere" on suspicious activity.

Platform

Personal API Keys

Generate an mrp_-prefixed personal key for server-side automations and integrations. Use it anywhere you'd use a JWT Bearer token — it never expires unless explicitly revoked.

GET/api-keys.php?action=getJWT

Check if a key exists. Returns has_key, key_masked (e.g. mrp_4a7b****c6b7), and key_prefix. Full key is never re-exposed.

POST/api-keys.php?action=generateJWT

Generate or regenerate a key. Requires PIN. The full key is returned once only — copy it immediately.

{ "success": true, "api_key": "mrp_4a7b2c9e1f3d0e8a5c6b..." }
POST/api-keys.php?action=revokeJWT

Immediately invalidate the current key. All requests using it will return 401. Body: { "pin": "1234" }

Platform

Support Tickets

POST/support.php?action=createJWT
{
  "subject":   "Deposit not reflecting",
  "message":   "I paid ₦5000 via Paystack at 2:14pm but...",
  "category":  "payment",  // payment|account|kyc|technical|other
  "priority":  "high"       // low|normal|high|urgent
}
GET/support.php?action=listJWT

All your tickets with status (open, in_progress, resolved, closed) and unread reply count.

POST/support.php?action=replyJWT

Add a reply to an open ticket. Body: { "ticket_id": 12, "message": "..." }

Platform

Webhook Events

MyRoPay delivers HMAC-signed POST requests to your registered endpoints in real time. All events share a common envelope and are retried with exponential backoff on failure.

Verify a delivery
// Node.js — always verify before processing
const crypto   = require('crypto');
const rawBody  = req.rawBody;   // raw Buffer, not parsed JSON
const sig      = req.headers['x-myropay-signature'];
const expected = 'sha256=' + crypto.createHmac('sha256', WEBHOOK_SECRET)
                  .update(rawBody).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
  return res.status(401).end();
}
res.status(200).end();  // ack fast, process async
const event = JSON.parse(rawBody);
Event envelope
{
  "event":       "payment.success",
  "timestamp":   "2025-04-23T14:22:00Z",
  "api_version": "3.1",
  "data": { /* event-specific payload */ }
}
Event types
EventTrigger
payment.successCheckout session paid and completed
payment.failedPayment attempt abandoned or declined
deposit.confirmedWallet deposit credited (any gateway)
transfer.receivedP2P transfer credited to your wallet
payout.completedWithdrawal processed and sent
payout.failedWithdrawal failed — funds returned to wallet
escrow.fundedEscrow created and funds locked
escrow.releasedInitiator releases to beneficiary
escrow.disputedEither party raises a dispute
escrow.resolvedAdmin resolves the dispute
kyc.approvedKYC document reviewed and approved
kyc.rejectedKYC document rejected — resubmission needed
invoice.paidInvoice paid via checkout link
invoice.overdueInvoice past due date with no payment
payroll.completedPayroll batch fully processed
♻️
Retry schedule. Failed deliveries (non-2xx or timeout >10s) are retried: 1 min → 5 min → 30 min → 2 hours → 24 hours. Always respond with 200 immediately and process the payload asynchronously.