Merchant API Documentation

Integrate Hanypay to collect payments, send payouts, issue refunds, and manage transactions programmatically.

Base URLhttps://payment-ms.hanypay.co/api/v1/merchant

Getting Started

The Hanypay Merchant API lets you accept AKL payments from customers, send payouts, issue refunds, and query transaction history. All communication is over HTTPS and authenticated via API keys.

Quick start

  1. Create a business in the Hanypay Dashboard
  2. Go to Business → API Keys and create an API key
  3. Copy the key — it is shown only once
  4. Pass the key in the Hanypay-Api-Key header on every request

Authentication

Include your API key in every request using the Hanypay-Api-Key header.

Example request
curl https://payment-ms.hanypay.co/api/v1/merchant/charges/ \
  -H "Content-Type: application/json" \
  -H "Hanypay-Api-Key: YOUR_API_KEY" \
  -d '{"amount": "100.00"}'

All responses follow a consistent shape:

Success response
{
  "success": true,
  "message": "...",
  "data": { ... }
}
Error response
{
  "success": false,
  "error": "error_code",
  "message": "Human-readable error message"
}
Keep your API key secret. Do not expose it in client-side code, public repositories, or browser requests. If compromised, revoke and regenerate it immediately from the Dashboard.

Collections

POST

Initiate Payment

POST /payments/initiate/

Start a payment collection. The customer receives a 6-digit authorization code via email which must be verified to complete the payment.

FieldTypeRequiredDescription
wallet_numberstring(16)RequiredCustomer's wallet number
amountdecimalRequiredAmount in AKL (min 0.000001)
currency_codestring(3)OptionalCurrency code (only "AKL", default "AKL")
txn_referencestring(256)OptionalYour unique reference for idempotency
metadataobjectOptionalArbitrary key-value data returned in webhooks
callback_urlurlOptionalURL to receive webhook notifications
charge_bearerstringOptional"customer" (default) or "merchant". Determines who pays the transaction fee.
Set charge_bearer to "merchant" to absorb the transaction fee yourself. The customer will only be charged the payment amount. Default is "customer", where the fee is added on top of the amount.
curl
curl -X POST https://payment-ms.hanypay.co/api/v1/merchant/payments/initiate/ \
  -H "Content-Type: application/json" \
  -H "Hanypay-Api-Key: YOUR_API_KEY" \
  -d '{
    "wallet_number": "1234567890123456",
    "amount": "100.00",
    "txn_reference": "ORDER-001",
    "charge_bearer": "merchant"
  }'
Response (200)
{
  "success": true,
  "message": "Authorization code has been sent to customer.",
  "data": {
    "transaction_id": "d4f8a2b1-...",
    "txn_reference": "ORDER-001",
    "verification_required": true
  }
}
If you provide a txn_reference that already exists, the existing transaction is returned instead of creating a duplicate. Use this for safe retries.
POST

Verify Payment

POST /payments/verify/

Submit the customer's authorization code to complete the payment. The result is synchronous — you get success or failure immediately.

FieldTypeRequiredDescription
codestringRequired6-character authorization code from customer
txn_referencestringRequiredTransaction reference from initiate response
curl
curl -X POST https://payment-ms.hanypay.co/api/v1/merchant/payments/verify/ \
  -H "Content-Type: application/json" \
  -H "Hanypay-Api-Key: YOUR_API_KEY" \
  -d '{
    "code": "ABC123",
    "txn_reference": "ORDER-001"
  }'
Response (200)
{
  "success": true,
  "message": "Payment completed successfully.",
  "data": {
    "transaction_id": "d4f8a2b1-...",
    "status": "Completed",
    "amount": "100.000000"
  }
}

Error codes: invalid_code, code_expired, invalid_reference, processing_failed

Payout / Disbursement

POST

Payout

POST /payouts/

Send AKL from your business wallet to a recipient wallet.

FieldTypeRequiredDescription
wallet_numberstring(16)RequiredRecipient wallet number
amountdecimalRequiredAmount in AKL
descriptionstring(255)OptionalPayout description
curl
curl -X POST https://payment-ms.hanypay.co/api/v1/merchant/payouts/ \
  -H "Content-Type: application/json" \
  -H "Hanypay-Api-Key: YOUR_API_KEY" \
  -d '{
    "wallet_number": "5555666677778888",
    "amount": "50.00",
    "description": "Salary payout"
  }'
Response (200)
{
  "success": true,
  "message": "Payout completed successfully.",
  "data": {
    "transaction_id": "a1b2c3d4-...",
    "reference": "REF-001",
    "status": "Completed"
  }
}

Error codes: invalid_wallet, limit_exceeded, same_wallet, payout_failed

Transactions

GET

List Transactions

GET /transactions/

Retrieve a paginated list of your business transactions.

FieldTypeRequiredDescription
statusstringOptionalFilter by status (Pending, Completed, Failed, etc.)
transaction_typestringOptionalFilter by type (Purchase, Transfer, Refund)
start_datedateOptionalFilter from date (YYYY-MM-DD)
end_datedateOptionalFilter to date (YYYY-MM-DD)
querystringOptionalSearch by reference or wallet number
pageintegerOptionalPage number (default 1)
page_sizeintegerOptionalResults per page (default 15)
curl
curl "https://payment-ms.hanypay.co/api/v1/merchant/transactions/?status=Completed&page=1" \
  -H "Hanypay-Api-Key: YOUR_API_KEY"
Response (200)
{
  "count": 50,
  "next": "...?page=2",
  "previous": null,
  "total_pages": 4,
  "current_page": 1,
  "results": [
    {
      "reference": "abc123",
      "txn_reference": "ORDER-001",
      "amount": "100.000000",
      "status": "Completed",
      ...
    }
  ]
}
GET

Get Transaction

GET /transactions/{reference}/

Retrieve a single transaction by its internal reference or your txn_reference.

curl
curl https://payment-ms.hanypay.co/api/v1/merchant/transactions/ORDER-001/ \
  -H "Hanypay-Api-Key: YOUR_API_KEY"
Response (200)
{
  "success": true,
  "message": "Transaction retrieved.",
  "data": {
    "id": 123,
    "reference": "abc123",
    "txn_reference": "ORDER-001",
    "amount": "100.000000",
    "charges": "1.500000",
    "currency_code": "AKL",
    "transaction_type": "Purchase",
    "status": "Completed",
    "channel": "Wallet Transfer",
    "description": "",
    "metadata": {},
    "created_at": "2026-01-15T10:30:00Z"
  }
}
POST

Refund

POST /refunds/

Refund a completed purchase transaction. Supports full and partial refunds. Cumulative refunds are tracked — the total cannot exceed the original amount.

FieldTypeRequiredDescription
transaction_referencestringRequiredReference of the original transaction
amountdecimalOptionalPartial refund amount (defaults to full amount)
descriptionstring(255)OptionalReason for refund
curl
curl -X POST https://payment-ms.hanypay.co/api/v1/merchant/refunds/ \
  -H "Content-Type: application/json" \
  -H "Hanypay-Api-Key: YOUR_API_KEY" \
  -d '{
    "transaction_reference": "ORDER-001",
    "amount": "25.00",
    "description": "Customer requested partial refund"
  }'
Response (200)
{
  "success": true,
  "message": "Refund completed successfully.",
  "data": {
    "refund_reference": "REF-REFUND-001",
    "amount": "25.0",
    "status": "Completed"
  }
}

Utilities

POST

Calculate Charges

POST /charges/

Preview the transaction fee for a given amount before initiating a payment.

FieldTypeRequiredDescription
amountdecimalRequiredTransaction amount
curl
curl -X POST https://payment-ms.hanypay.co/api/v1/merchant/charges/ \
  -H "Content-Type: application/json" \
  -H "Hanypay-Api-Key: YOUR_API_KEY" \
  -d '{"amount": "100.00"}'
Response (200)
{
  "success": true,
  "message": "Charges calculated.",
  "data": {
    "amount": "100.000000",
    "charges": "1.500000",
    "total": "101.500000"
  }
}
POST

Exchange Rates

POST /exchange-rates/

Convert between AKL and other currencies. One of the currencies must be AKL.

FieldTypeRequiredDescription
base_currency_codestring(3)RequiredSource currency (e.g. "AKL")
target_currency_codestring(3)RequiredTarget currency (e.g. "USD")
amountdecimalRequiredAmount to convert
curl
curl -X POST https://payment-ms.hanypay.co/api/v1/merchant/exchange-rates/ \
  -H "Content-Type: application/json" \
  -H "Hanypay-Api-Key: YOUR_API_KEY" \
  -d '{
    "base_currency_code": "AKL",
    "target_currency_code": "USD",
    "amount": "100.00"
  }'
Response (200)
{
  "success": true,
  "message": "Exchange rate retrieved.",
  "data": {
    "base_currency": "AKL",
    "target_currency": "USD",
    "rate": 0.052,
    "original_amount": 100.0,
    "converted_amount": 5.2
  }
}

Guides

Payment Flow

The collection flow involves two API calls with a customer action in between:

1
Initiate Payment
Call POST /payments/initiate/ with the customer wallet number and amount.
2
Customer receives code
A 6-digit authorization code is sent to the customer via email.
3
Customer shares code
The customer provides the code to your application (e.g. via a form).
4
Verify Payment
Call POST /payments/verify/ with the code and txn_reference.
5
Payment completes
Success or failure is returned synchronously. A webhook fires to your registered URLs.

Webhooks

Webhook URLs are registered in the Dashboard under Business → API Keys → Webhook URLs. When a payment completes or fails, we send a POST request to each active URL.

Payload format

{
  "event": "payment.completed",
  "data": {
    "reference": "abc123",
    "txn_reference": "ORDER-001",
    "amount": "100.000000",
    "charges": "1.500000",
    "currency_code": "AKL",
    "status": "Completed",
    "transaction_type": "Purchase",
    "created_at": "2026-01-15T10:30:00Z"
  }
}

Events

EventDescription
payment.completedCustomer payment succeeded
payment.failedCustomer payment failed
payment.updatedPayment status changed
payout.completedDisbursement succeeded
payout.failedDisbursement failed

Signature verification

Each webhook includes an X-Hanypay-Signature header containing an HMAC-SHA256 hex digest of the JSON body signed with your webhook secret.

Python verification example
import hmac, hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Error Reference

CodeDescription
invalid_api_keyMissing or invalid API key
invalid_walletWallet number not found
insufficient_balanceNot enough AKL balance
invalid_codeAuthorization code not found
code_expiredAuthorization code has expired
invalid_referenceTransaction reference not found
invalid_amountAmount exceeds allowed limit
processing_failedPayment processing failed
limit_exceededTransaction limit exceeded
same_walletSource and destination wallets are the same
payout_failedPayout processing failed
refund_failedRefund processing failed
conversion_failedCurrency conversion failed

Transaction Statuses

StatusDescription
PendingTransaction created, awaiting verification
InitiatedTransaction initiated with provider
CompletedTransaction completed successfully
FailedTransaction failed
CancelledTransaction cancelled
FundsReservedFunds reserved for transaction
API endpoints are rate-limited to 120 requests per minute per API key. Exceeding this limit returns HTTP 429. Implement exponential backoff in your integration.
Light Logo
Hanypay is a leading provider of online payment processing, and merchant solutions. Our mission is to make electronic payments seemless and accessible for businesses of all sizes.
Follow us
Copyright © 2026. Hanypay - All Rights Reserved.