Guides

Merchant integration guides

Authentication, environments, collections, payment IDs, webhooks, and error handling.

Guides for integrating NexuzPayz Merchant Collections. For the full endpoint list with request/response schemas, see the API reference.

Overview

NexuzPayz Merchant API lets you accept GHS collections from your ecommerce checkout or billing system. The platform currently supports:

  • Payment links — hosted checkout URLs you redirect customers to
  • Mobile money USSD — direct MoMo collection via MTN, Telecel, or AirtelTigo
  • Permanent payment IDs — reusable USSD codes (*203*{id}#) for in-person or phone checkout
  • Webhooks — signed HTTP callbacks when collections succeed or fail

Configure API keys, KYC, and settlement in the merchant portal. This documentation covers the integration API your server calls.

All integration routes are prefixed with /api/v1. The base host is configured per environment (production: https://api.nexuzpayz.com).

Authentication

Authenticate integration requests with a secret API key in the Authorization header:

Authorization: Bearer sk_test_xxxxxxxx
PrefixEnvironment
sk_test_Sandbox — test collections without real money movement
sk_live_Live — real GHS collections after KYC approval

Create keys in the merchant portal. The full secret is shown once at creation.

Never expose API keys in client-side JavaScript, mobile apps, or public repositories.

Environments

NexuzPayz uses a single API host per deployment. Sandbox vs live is determined by your API key prefix, not a separate base URL.

SandboxLive
Key prefixsk_test_sk_live_
Money movementTest / simulatedReal GHS
RequirementsMerchant accountKYC approved, status ACTIVE, GHS wallet provisioned

Gating rules:

  • Sandbox keys can be created immediately after onboarding.
  • Live keys require merchant status ACTIVE and a configured GHS collection wallet.
  • Portal payment ID creation always uses the LIVE environment regardless of key type.

Start integration with sandbox keys, then switch to sk_live_ after compliance approval.

Collections

Payment link (recommended for web checkout)

curl -X POST https://api.nexuzpayz.com/api/v1/merchant/collections \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "99.00",
    "method": "payment_link",
    "merchantReference": "ORD-10042",
    "payerEmail": "customer@example.com",
    "expirationMinutes": 60
  }'

Redirect the customer to the paymentUrl in the response. Poll GET /merchant/collections/{id} or listen for webhooks to confirm payment.

USSD mobile money

Omit method: "payment_link" (or set another value) and provide channel + payerPhone:

ChannelProvider
13MTN
6Telecel
7AirtelTigo

Status may be REQUIRES_OTP while the payer confirms on their device.

Collection statuses

StatusMeaning
PENDINGAwaiting payment
REQUIRES_OTPUSSD initiated; payer must confirm
SUCCEEDEDPayment confirmed
FAILEDPayment failed
EXPIREDPayment link expired

Payment IDs

Payment IDs are permanent Moolre identifiers for USSD checkout. Customers dial *203*{paymentId}# to pay.

curl -X POST https://api.nexuzpayz.com/api/v1/merchant/payment-ids \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Order #10042",
    "payerPhone": "+233201234567",
    "merchantReference": "ORD-10042",
    "expectedAmount": "99.00"
  }'

Display the ussdCode to the customer. Poll GET /merchant/payment-ids/{id}?sync=true or use webhooks to detect when status becomes PAID.

Webhooks

Register webhook endpoints in the merchant portal or via POST /merchant/{merchantId}/webhooks.

Events

  • collection.succeeded — payment confirmed
  • collection.failed — payment failed

Verifying signatures

Each delivery includes:

X-NexuzPayz-Event: collection.succeeded
X-NexuzPayz-Signature: t=1719398712,v1=abc123...
  1. Parse t (Unix timestamp) and v1 (hex HMAC) from the signature header.
  2. Build the signed payload: {timestamp}.{raw_request_body}
  3. Compute HMAC-SHA256(signing_key, signed_payload) as lowercase hex.
  4. Compare to v1 using a constant-time comparison.

Reject requests with timestamps too far from your server clock (replay protection).

Requirements

  • Endpoint must be HTTPS
  • Return 2xx within 10 seconds
  • Verify signature before updating your database

Errors

Errors return a JSON body with a consistent shape:

{
  "status": 400,
  "code": "VALIDATION_ERROR",
  "message": "Amount must be positive",
  "traceId": "b4a3d9c5-2c3f-4d0f-8f1b-6d1a1c1f2a3b",
  "timestamp": "2026-06-26T10:00:00Z"
}
HTTP statusTypical cause
400Invalid request body or business rule violation
401Missing or invalid API key / JWT
403Authenticated but not authorised for this merchant
404Resource not found
409Conflict (e.g. constraint violation)
501Feature not configured (e.g. JWT issuer disabled)

Include the traceId when contacting support.

MerchantSummary object

Returned by profile, KYC, and dashboard endpoints:

FieldTypeDescription
iduuidMerchant ID
slugstringURL-safe identifier
tradingNamestringDisplay name
legalNamestringRegistered legal name
registrationNumberstringBusiness registration
industrystringIndustry category
websiteUrlstringBusiness website
supportEmailstringSupport contact email
supportPhonestringSupport contact phone
countrystringISO country code
statusstringPENDING_INVITE, ONBOARDING, KYC_PENDING, ACTIVE, etc.
kycStatusstringPENDING, SUBMITTED, APPROVED, REJECTED
kycRejectionReasonstringPresent when KYC rejected
ghsVirtualAccountIduuidGHS collection wallet (required for collections)
activatedAtISO-8601When merchant was activated