API Documentation

MonCashConnect is a REST API for accepting MonCash payments in your application, WordPress site, or SaaS — without managing OAuth, tokens, or the complexity of the official gateway.

Every request is authenticated with your project's secret key sk_proj_…. HMAC-SHA256-signed webhooks guarantee the integrity of payment notifications.

HMAC-SHA256
Reliable webhooks
REST + JSON
Base URL: https://api.moncashconnect.com/v1
All requests must use HTTPS. The body of POST requests must be application/json.
Using an AI coding assistant? We have an MCP (Model Context Protocol) server: npx -y @moncashconnect/mcp connects Cursor, Claude Code, or Codex to MonCashConnect read-only, with an sk_ro_… key that can't move money. See the MCP guide.

Quickstart

Integrate MonCash in under 5 minutes. Here is the minimal end-to-end flow.

New to MonCashConnect? Start with the Sandbox Quickstart — test your integration end to end without moving real money, then go live by swapping two secrets (no code changes).
1

Create a project in the dashboard

Go to Developer → Projects and create a project. You will receive a secret key sk_proj_… — keep it somewhere safe, it is shown only once.

2

Create a payment server-side

curl -X POST https://api.moncashconnect.com/v1/pay-create \
  -H "Authorization: Bearer sk_proj_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 500,
    "referenceId": "order_001",
    "returnUrl": "https://votresite.com/merci"
  }'

The response contains paymentUrl — redirect your customer to this URL.

3

Redirect the customer to MonCash

const { paymentUrl } = await res.json();
// Server-side (Express, Next.js, etc.)
res.redirect(paymentUrl);
4

Receive confirmation via webhook

Configure a webhook URL in your project. MonCashConnect sends an HMAC-SHA256-signed POST as soon as the payment is confirmed by MonCash.

import { constructEvent, MonCashError } from "@moncashconnect/sdk";

// Express — read the raw body BEFORE JSON.parse
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
  try {
    const event = constructEvent(
      req.body,
      req.headers["x-mcc-signature"],
      req.headers["x-mcc-timestamp"],
      process.env.MCC_WEBHOOK_SECRET,
    );
    if (event.event === "payment.completed") {
      // Credit the order in your database
    }
    res.sendStatus(200);
  } catch (err) {
    if (err instanceof MonCashError) return res.status(err.statusCode).send(err.message);
    res.sendStatus(500);
  }
});

Authentication

Each project has a unique secret key prefixed with sk_proj_. Pass it in the Authorization header of every request.

curl -H "Authorization: Bearer sk_proj_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
     https://api.moncashconnect.com/v1/pay-balance
Never transmit the secret key from the browser (front-end). Always make API calls from your server. If it leaks, revoke the key immediately from Developer → Projects.

Allowed domains (CORS)

If you configure allowed domains on your project, requests from other origins will be rejected with a 403. Leave the list empty to allow all origins (server-side use only).

The list is all-or-nothing: as soon as it contains at least one domain, all other origins are blocked — including localhost, your staging URLs, and previews. Add each environment (prod, staging, dev) explicitly.

Create a payment

POST
https://api.moncashconnect.com/v1/pay-create

Creates a pending transaction and returns a MonCash payment URL. Redirect your customer to this URL. The transaction expires after 15 minutes.

Parameters (JSON body)

Nom / CodeType / LimiteDescription
amount*integerAmount in HTG, integer between 1 and 1,000,000
referenceId*stringUnique identifier [a-zA-Z0-9-_], 100 characters max. Unique per project.
returnUrlstringHTTPS return URL after payment — strongly recommended
customerNamestringCustomer name — displayed on the MonCash page (optional)
customerEmailstringCustomer email — stored in the transaction (optional)
curl -X POST https://api.moncashconnect.com/v1/pay-create \
  -H "Authorization: Bearer sk_proj_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 500,
    "referenceId": "order_12345",
    "returnUrl": "https://votresite.com/merci",
    "customerName": "Jean Dupont",
    "customerEmail": "jean@example.com"
  }'

Response (200)

{
  "paymentUrl": "https://pay.moncashconnect.com/c/abc123...",
  "reference":  "order_12345",
  "expiresAt":  "2026-05-05T15:30:00.000Z"
}
referenceId must be unique per project. Reusing an existing referenceId returns 409 Conflict.

Safe retries with Idempotency-Key

A /pay-create request that fails (network error, timeout, 502 gateway) may have already created the transaction. To make retries safe, add the Idempotency-Key header with a string that is unique per logical attempt (UUID, order hash, etc.): a second call with the same key and the same body returns the original payment URL instead of creating a duplicate.

Nom / CodeType / LimiteDescription
Idempotency-Key (header)printable ASCII, ≤ 200 charsStable merchant-side identifier. Validity: 15 min (TTL window of the payment URL).
Possible responses with Idempotency-Key
Nom / CodeType / LimiteDescription
200same key + same bodyOriginal response returned (header Idempotent-Replay: true). Identical paymentUrl.
422idempotency_key_mismatchSame key, different body — refused to avoid a silently modified transaction.
409idempotent_request_in_progressA previous request with this key is still in progress. Header Retry-After: 2 — retry.
502idempotent_replay_failedThe previous request with this key failed — use a new key to retry.
410idempotent_replay_expiredThe cached URL is > 15 min old; use a new Idempotency-Key (the previous one has expired).
curl -X POST https://api.moncashconnect.com/v1/pay-create \
  -H "Authorization: Bearer sk_proj_xxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_12345-attempt-1" \
  -d '{ "amount": 500, "referenceId": "order_12345", "returnUrl": "https://votresite.com/merci" }'
Without Idempotency-Key (compatible with the earlier behavior): if you receive a 409 or a network failure, call GET /pay-status?referenceId=… to verify that a transaction exists before generating a new referenceId. The fallback code below remains valid for legacy integrations.
Fallback without Idempotency-Key: recovery via /pay-status

General rule: poll /pay-status before generating a new referenceId. Only retry /pay-create with a fresh identifier if /pay-status returns 404 (transaction never created).

Check status

GET
https://api.moncashconnect.com/v1/pay-status?referenceId=order_12345

Query the status of a transaction by its referenceId. Useful after the customer redirect or for fallback polling if the webhook is not configured.

curl -H "Authorization: Bearer sk_proj_xxxx" \
  "https://api.moncashconnect.com/v1/pay-status?referenceId=order_12345"

Response (200)

{
  "reference":            "order_12345",
  "status":               "completed",
  "amount":               500,
  "netAmount":            485,
  "completedAt":          "2026-05-05T14:21:18.000Z",
  "failedAt":             null,
  "failureReason":        null,
  "moncashTransactionId": "MC-123456789",
  "createdAt":            "2026-05-05T14:05:00.000Z"
}
Nom / CodeType / LimiteDescription
statusstringpending · completed · failed
amountinteger (HTG)Gross amount collected
netAmountinteger (HTG)Amount after commission deduction (e.g. 500 × 97% = 485 HTG on the Free plan)
moncashTransactionIdstring | nullMonCash transaction ID — available after confirmation
failureReasonstring | nullFailure reason if status = failed

Balance

GET
https://api.moncashconnect.com/v1/pay-balance

Returns the HTG balance of your MonCashConnect merchant account — that is, the total of accepted payments that have settled, minus withdrawals already made. This endpoint returns no information about any particular customer or payment; it is used to automate withdrawals to MonCash from your dashboard.

curl -H "Authorization: Bearer sk_proj_xxxx" \
  "https://api.moncashconnect.com/v1/pay-balance"
{
  "balanceHtg":      12500,
  "withdrawableHtg":  5000,
  "dailyCapHtg":      5000,
  "usedTodayHtg":        0
}
Nom / CodeType / LimiteDescription
balanceHtgintegerTotal balance available in the account
withdrawableHtgintegerAmount withdrawable now (min(balance, cap - used))
dailyCapHtgintegerDaily withdrawal cap based on your plan
usedTodayHtgintegerAlready withdrawn today

Withdrawals are requested from the Withdrawals page of the dashboard and are approved before being sent to MonCash.

Payouts (outbound)

There are several ways to send money from MonCashConnect. Choose the right one for your needs:

You want to…RouteHow
Pay your own users (marketplace, wallet, app)payout-createSelf-serve API, sk_proj_ key, as soon as KYC is verified. Your users live in your database; MCC only sees one account, yours.
Withdraw your balance to your own number, automaticallyAuto withdrawalsA toggle on the Withdrawals page, no code. Details below.
Pay several numbers at once (CSV import)Bulk payout/payouts/new page. Enabled by the team.
An external app pays from other people's MCC accountsexternal-payout-createPartner / Connect, OAuth token. Typical HaiPay case, restricted and enabled by the team. See the Partners docs.
Manual withdrawal to your own numberWithdrawals pageOne click from /withdrawals.
Don't confuse the two outbound APIs. payout-create moves your money to your users (self-serve, below). Partner/Connect (external-payout-create) lets an external app act on the balance of other MCC account holders, with their OAuth consent (restricted, enabled by the team). If you are paying your own users, you want payout-create, not Connect.

Automate payments to your users (API)

POST
https://api.moncashconnect.com/v1/payout-create

Sends funds from your merchant balance to any MonCash number. Your MonCashConnect account acts as a shared pool: you collect payments from your users, then redistribute to each of them — manage their individual balance in your own database.

Fee model: the recipient receives exactly the amount you specify. Network fees are charged on top of that from your balance (see the fee_htg field in the response).

Parameters (JSON body)

Nom / CodeType / LimiteDescription
amount*integerAmount in HTG to send to the recipient, an integer between 1 and 100,000 per payout. The recipient receives this exact amount; fees are charged on top of that from your balance.
moncashNumberstringRecipient's MonCash number (raw, e.g. 50912345678). Required if recipientCode is absent.
recipientCodestringCode of a recipient saved in your project. Alternative to moncashNumber.
referenceIdstringYour idempotency identifier [a-zA-Z0-9-_], 100 characters max. A duplicate returns 409 duplicate_reference.
curl -X POST https://api.moncashconnect.com/v1/payout-create \
  -H "Authorization: Bearer sk_proj_xxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: payout-user42-2026-06-24" \
  -d '{
    "amount": 5000,
    "moncashNumber": "50912345678",
    "referenceId": "payout-user42-2026-06-24"
  }'

Response (201)

{
  "status": "success",
  "payout": {
    "reference":                "wd_123",
    "status":                   "queued",
    "amount_htg":               5000,
    "fee_htg":                  250,
    "net_htg":                  5000,
    "recipient_account_masked": "509****1234"
  }
}
Nom / CodeType / LimiteDescription
payout.referencestringInternal payout identifier (wd_ prefix)
payout.statusstringInitial state: queued. Full cycle: queued → processing → completed | failed
payout.amount_htgintegerRequested amount (what the recipient receives)
payout.fee_htgintegerNetwork fees charged on top of that from your balance
payout.net_htgintegerAmount actually received by the recipient (= amount_htg)
payout.recipient_account_maskedstringRecipient's masked MonCash number, for safe display

Idempotency

Pass a unique referenceId or the Idempotency-Key header to make retries safe. A second call with the same identifier returns 409 duplicate_reference instead of creating a duplicate.

Confirmation webhook

MonCashConnect sends an HMAC-SHA256-signed POST to your webhook URL as soon as the payout is settled. The signature is verified exactly as for pay-in webhooks (X-MCC-Signature: sha256=…, X-MCC-Timestamp).

payout.completed
The payout was transmitted and the recipient received the funds on their MonCash number.
{
  "event": "payout.completed",
  "reference": "wd_123",
  "amount": 5000,
  "status": "completed",
  "recipient_account_masked": "509****1234",
  "completedAt": "2026-06-24T16:21:18.000Z",
  "failureReason": null
}
payout.failed
The payout failed (invalid number, MonCash account unreachable, etc.). Check failureReason.
{
  "event": "payout.failed",
  "reference": "wd_124",
  "amount": 5000,
  "status": "failed",
  "recipient_account_masked": "509****5678",
  "completedAt": null,
  "failureReason": "recipient_account_not_found"
}

Payout-specific error codes

Nom / CodeType / LimiteDescription
missing_bearer_token401Authorization header absent
invalid_key_type401The provided key is not a project key sk_proj_…
invalid_api_key401Invalid or revoked key
kyc_required403Identity verification required before enabling payouts
account_suspended403Merchant account suspended
invalid_amount400The amount is not a valid integer
invalid_moncash_number400Incorrect MonCash number format
recipient_required400Neither moncashNumber nor recipientCode provided
invalid_reference400referenceId does not match the format [a-zA-Z0-9-_] / exceeds 100 characters
insufficient_balance402Insufficient balance to cover amount + network fees
below_minimum422Amount below the allowed minimum
above_maximum422Amount above 100,000 HTG per payout
recipient_not_found404recipientCode not found in your project
duplicate_reference409referenceId or Idempotency-Key already used — the payout already exists

Automatic withdrawals (no code)

No coding needed to automate your own withdrawals. On the Withdrawals page, enable automatic payments: choose a saved withdrawal number, set a "Send when balance reaches" threshold (minimum 100 HTG), and an optional cap per payment. As soon as your balance crosses the threshold, MonCashConnect sends automatically to that number, with a minimum delay of 30 minutes between two sends. Same network fees as for a manual withdrawal.

Ideal for "I just want my money to land on my MonCash without thinking about it." To pay other people automatically (your users), use the payout-create API above instead.

Webhooks

Configure a webhook URL in your project to receive payment events in real time. MonCashConnect sends an HMAC-SHA256-signed POST to your URL as soon as a payment is finalized by MonCash.

Connect / partner integration? Outbound payout webhooks (external_payout.*) use a distinct signature scheme (t=…,v1=…) with a deduplication header X-MCC-Event-Id. See the partner documentation →

Headers sent

Nom / CodeType / LimiteDescription
X-MCC-Signaturestringsha256=<hex_hmac> — HMAC-SHA256 of the raw JSON body, signed with your webhook secret
X-MCC-TimestampstringUnix timestamp (seconds) of the send — reject if the gap is > 5 min
Content-Typestringapplication/json

Events

payment.completed
The MonCash payment was confirmed and the net amount credited to your balance.
{
  "event": "payment.completed",
  "reference": "order_12345",
  "amount": 500,
  "status": "completed",
  "completedAt": "2026-05-05T14:21:18.000Z"
}
payment.failed
The payment expired, was cancelled or rejected by MonCash.
{
  "event": "payment.failed",
  "reference": "order_12345",
  "amount": 500,
  "status": "failed",
  "completedAt": null
}

Signature verification

Read the raw body (req.body as a Buffer) before any JSON.parse(). Reject any request whose signature is invalid or whose timestamp is more than 5 minutes old.

# Generate a test signature locally
SECRET="whsec_your_webhook_secret"
BODY='{"event":"payment.completed","reference":"test_001","amount":500,"status":"completed","completedAt":"2026-05-05T14:21:18.000Z"}'
TS=$(date +%s)
SIG="sha256=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/.*= //')"

curl -X POST https://yoursite.com/webhook \
  -H "Content-Type: application/json" \
  -H "X-MCC-Signature: $SIG" \
  -H "X-MCC-Timestamp: $TS" \
  -d "$BODY"

Retry policy

If your endpoint does not respond with a 2xx within 10 seconds, MonCashConnect records the failure and schedules a new attempt after 60 seconds. Make sure your handler is idempotent — it may receive the same event several times.

Official SDKs

Official SDKs cover the three main languages. Each SDK includes error handling, HMAC verification of webhooks, and TypeScript types / Python annotations.

Node.js / TypeScript

@moncashconnect/sdk
npm install @moncashconnect/sdk
import { MonCashClient } from "@moncashconnect/sdk";

const client = new MonCashClient(
  process.env.MCC_SECRET_KEY
);

const payment = await client.createPayment(
  500, "order_001",
  { returnUrl: "https://site.ht/merci" }
);
res.redirect(payment.paymentUrl);

Python / pip

moncashconnect
pip install moncashconnect
from moncashconnect import MonCashClient
import os

client = MonCashClient(
  os.environ["MCC_SECRET_KEY"]
)

payment = client.create_payment(
  500, "order_001",
  return_url="https://site.ht/merci"
)
# redirect(payment["paymentUrl"])

PHP / Composer

moncashconnect/php-sdk
composer require moncashconnect/php-sdk
use MonCashConnect\Client;

$client = new Client(
  $_ENV['MCC_SECRET_KEY']
);

$payment = $client->createPayment(
  500, 'order_001',
  ['returnUrl' => 'https://site.ht/merci']
);
header('Location: '.$payment['paymentUrl']);

Guides by framework

Fees

MonCashConnect takes 0% on your transactions.

The fees you see on the gateway come from the Digicel MonCash network. We pass them through unchanged — no added markup.

Detailed fees

Nom / CodeType / LimiteDescription
Collection2.9%Charged on every incoming payment via MonCash. On 1,000 HTG collected, you receive 971 HTG.
MonCash withdrawal5%Charged when sending to a MonCash number. To send 1,000 HTG, your balance decreases by 1,050 HTG.
Transfers between MCC accounts0%Free — no network fees, no MCC commission.
MonCashConnect commission0%We take nothing on transactions, regardless of the plan.

So why does a subscription exist?

The subscription (Pro, Early Visionary Pass) unlocks only two things: more than one API project on your account, and higher daily caps on withdrawals. As long as you stay on a single project and the Free cap, you have no reason to pay. See the plans →

Rate limits

Limits apply per project secret key and per IP address. Exceeding them returns a 429 Too Many Requests.

Nom / CodeType / LimiteDescription
POST /pay-create60 / min / key30 / min / IP
GET /pay-status120 / min / key60 / min / IP
GET /pay-balance120 / min / key60 / min / IP

In case of repeated overruns, implement an exponential backoff with jitter between attempts. Avoid intensive polling on pay-status — prefer webhooks for real-time confirmations.

Hosted pages (deposit QR & invoices)

The payment pages hosted by MonCashConnect — the QR-code deposit page and the invoice settlement page — are loaded by your customer's browser, not by your server. They have their own limits, applied per IP address and per public token; exceeding them also returns a 429 Too Many Requests with a Retry-After: 60 header.

Nom / CodeType / LimiteDescription
QR deposit page (creation)20 / min / IP30 / min / token
QR deposit — payer info120 / min / IPPublic read (display)
QR deposit — status120 / min / IPConfirmation page polling
Invoice page (payment)20 / min / IP30 / min / token
Invoice — info120 / min / IPPublic read (display)

These limits protect the hosted pages against abuse; they do not affect your server calls authenticated with an sk_proj_ key.

Error codes

All errors return a JSON object { "error": "message" }.

Nom / CodeType / LimiteDescription
400Bad RequestInvalid or missing parameter — check amount, referenceId, returnUrl
401UnauthorizedAPI key absent, invalid, or revoked
403ForbiddenOrigin not allowed (CORS) or account suspended
404Not FoundTransaction not found for this referenceId and project
409ConflictreferenceId already used for this project — use a unique identifier
429Too Many RequestsRate limit reached — wait before retrying (exponential backoff)
500Internal ErrorInternal error — contact support if the problem persists
502Bad GatewayPayment gateway error — retry in a few seconds

Structured error codes (400 response)

Beyond HTTP codes, some 400 responses include a machine-readable code field. Use it to branch your client-side logic.

Nom / CodeType / LimiteDescription
invalid_request400Missing or malformed parameter (amount, referenceId, returnUrl, etc.)
amount_below_minimum400Amount below the minimum (1 HTG for creation, 1,000 HTG for withdrawal)
invalid_token401Invalid / expired OAuth token or API key (Connect integrations)
insufficient_scope403The token lacks the required scope (balance.read, payout.request, etc.)
connection_revoked403The merchant revoked your application's access (Connect integrations)
connection_not_found404No active connection between your application and this merchant
insufficient_balance402Insufficient merchant balance for the requested withdrawal
partner_daily_cap_exceeded429Your application's daily cap reached (Connect integrations)
plan_daily_cap_exceeded429The merchant plan's daily cap reached
rate_limit_exceeded429Rate limit exceeded — wait and retry with backoff
auth_unavailable503Authentication service temporarily unavailable — retry
server_misconfigured500Configuration error on the MonCashConnect side — contact support
not_found404Resource (transaction, payout, connection) not found

Example error response

{
  "error": "referenceId already exists for this project",
  "code":  "duplicate_reference"
}

The code field is stable; the error field is meant for humans and may be translated or reworded.

Ready to integrate?

Create a project and get your API keys in under a minute.