SDK Examples

Payroo has no official SDK yet — use these copy-paste examples to integrate directly via HTTP. All examples use the base URL https://api.payroo.xyz.

Create QR Payment

const res = await fetch('https://api.payroo.xyz/v1/payments', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_YOUR_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'order-001',
  },
  body: JSON.stringify({
    type: 'QRPH',
    amount: 10000,
    currency: 'PHP',
    reference_id: 'ORDER-001',
  }),
})
const payment = await res.json()
console.log(payment.qr_string)

Verify Webhook

import { createHmac } from 'crypto'

function verifyPayrooWebhook(payload, signature, secret) {
  const [tPart, v1Part] = signature.split(',')
  const timestamp = tPart.replace('t=', '')
  const provided = v1Part.replace('v1=', '')
  const expected = createHmac('sha256', secret)
    .update(`${timestamp}.${payload}`)
    .digest('hex')
  return expected === provided
}

Purchase E-Load

const res = await fetch('https://api.payroo.xyz/v1/eload/purchase', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_YOUR_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'eload-001',
  },
  body: JSON.stringify({
    product_id: '101',
    mobile_number: '+639171234567',
    reference_id: 'ELOAD-001',
  }),
})
const result = await res.json()

Create Payout

const res = await fetch('https://api.payroo.xyz/v1/payouts', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_YOUR_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'payout-001',
  },
  body: JSON.stringify({
    amount: 50000,
    currency: 'PHP',
    reference_id: 'PAYOUT-001',
    channel_code: 'GCASH',
    account_number: '+639171234567',
    account_holder_name: 'Juan dela Cruz',
    description: 'Salary disbursement',
  }),
})
const payout = await res.json()
console.log(payout.id, payout.status)

Bill Inquiry + Pay

// Step 1: Inquire
const inquiry = await fetch('https://api.payroo.xyz/v1/bills/inquiry', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_YOUR_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'bill-inq-001',
  },
  body: JSON.stringify({
    biller_id: 'MERALCO',
    account_number: '123456789012',
    reference_id: 'BILL-001',
  }),
}).then(r => r.json())

console.log('Amount due:', inquiry.amount, inquiry.due_date)

// Step 2: Pay using the inquiry transaction ID
const payment = await fetch('https://api.payroo.xyz/v1/bills/pay', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_YOUR_KEY',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'bill-pay-001',
  },
  body: JSON.stringify({
    transaction_id: inquiry.id,
    customer_name: 'Juan dela Cruz',
  }),
}).then(r => r.json())

console.log(payment.status, payment.payment_code)

Register Webhook

// Create endpoint — save the secret, it is shown only once
const res = await fetch('https://api.payroo.xyz/v1/webhooks', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_YOUR_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com/webhooks',
    events: [
      'payment.succeeded', 'payment.failed',
      'payout.succeeded', 'payout.failed',
      'eload.purchase.succeeded', 'eload.purchase.failed',
    ],
  }),
})
const { secret, ...endpoint } = await res.json()
console.log('Endpoint:', endpoint.id)
console.log('Secret (save this!):', secret)

Authentication

All requests require a Bearer API key in the Authorization header. Keys are scoped — use the minimum scope required.

ScopeGrants Access To
payments:writeCreate payments
payouts:writeCreate payouts
eload:writePurchase e-load
eload:readList e-load products and purchases
bills:writeInquire and pay bills
bills:readList billers and bill transactions
transactions:readList and get transactions
webhooks:manageCreate, list, delete webhook endpoints

Idempotency

All money-moving POST endpoints support the Idempotency-Key header. Send the same key with the same body to safely retry without creating duplicate transactions. Keys expire after 24 hours. Sending the same key with a different body returns a 409 IDEMPOTENCY_CONFLICT.