Skip to content
LevaPay

MonCash API and NatCash API documentation

Everything you need to integrate payouts to MonCash and NatCash wallets from your platform: authentication, endpoints, statuses, errors and copy-ready examples.

Quick start

  1. Create a free account and generate an API user and a TEST PRIVATE_KEY in the dashboard.
  2. Use the TEST base URL: https://api.levapay.dev/test/v1
  3. Check your balance, quote, send with a unique idempotency_key and check the status.
  4. Once your business is verified, repeat with your PROD keys and the PROD base URL: https://api.levapay.dev/prod/v1

A TEST key does not work in PROD and vice versa. Transfers are made by your platform through the API.

TEST mode

  • TEST balance is not real money and is assigned by LevaPay. If your TEST balance is 0, transfers return 402: ask your LevaPay contact for TEST balance.
  • NatCash: use the test wallet 50940885084. The transfer is completed instantly.
  • MonCash: in TEST, transfers stay pending and the amount is reserved from your TEST balance. Use it to test how you handle statuses.

Authentication

Send these headers with every request:

Content-Type: application/json
X-Api-User: YOUR_USER
X-Api-Key: YOUR_PRIVATE_KEY

Every response is JSON with ok. If ok is false, the message field explains why.

Balance

GEThttps://api.levapay.dev/test/v1/balance

Returns the available prepaid balance in HTG for the mode in the URL.

{ "ok": true, "data": { "mode": "test", "balance_htg": 2000.00, "currency": "HTG" } }

Quote

POSThttps://api.levapay.dev/test/v1/transfers/quote

{
  "network": "natcash",
  "wallet": "50940885084",
  "amount_htg": 100,
  "note": "Order payment 123"
}

network: natcash or moncash. wallet: 8 digits or 509 + 8. amount_htg: whole number, 1 or more. The quote lasts about 120 seconds and total_htg is what will be debited from your balance if you confirm.

note (optional, up to 64 characters): text the recipient sees on the deposit. If omitted, LEVAPAY is used.

Response:

{
  "ok": true,
  "data": {
    "quote_id": "qt_df63eb09ceba25c5be99",
    "network": "natcash",
    "wallet_masked": "509****5084",
    "amount_htg": 100,
    "fee_htg": 3.5,
    "total_htg": 103.5,
    "expires_at": "2026-10-04T12:00:05-04:00",
    "beneficiary": "Test account"
  }
}

fee_htg is the fee and total_htg = amount_htg + fee_htg. beneficiary (account holder name) is only returned for NatCash.

Send

POSThttps://api.levapay.dev/test/v1/transfers

{ "quote_id": "qt_...", "idempotency_key": "order-123" }

You can also omit quote_id and send network, wallet and amount_htg together with idempotency_key.

Idempotency: repeating the request with the same idempotency_key and the same body returns the same transfer with no second debit; the same key with a different body returns 409. A quote can only be sent once.

Response:

{
  "ok": true,
  "data": {
    "id": "tr_2d3c076092bbff0f59e3",
    "status": "completed",
    "network": "natcash",
    "wallet": "509****5084",
    "amount_htg": 100,
    "fee_htg": 3.5,
    "total_htg": 103.5,
    "created_at": "2026-10-04T11:58:05-04:00",
    "completed_at": "2026-10-04T11:58:06-04:00",
    "message": null
  }
}

Dates use ISO 8601 with a time zone. message contains the reason when a transfer ends up failed.

History and status

GEThttps://api.levapay.dev/test/v1/transfers

Optional parameters: page, per_page (up to 100), status and network. Newest first.

{
  "ok": true,
  "data": {
    "items": [
      {
        "id": "tr_37092e06026a4f7cc967",
        "status": "pending",
        "network": "moncash",
        "wallet": "509****5084",
        "amount_htg": 10,
        "fee_htg": 0.35,
        "total_htg": 10.35,
        "created_at": "2026-10-04T11:58:08-04:00",
        "completed_at": null,
        "message": null
      }
    ],
    "page": 1,
    "per_page": 20,
    "total": 6
  }
}

GEThttps://api.levapay.dev/test/v1/transfers/{id}

Returns the same object as the transfer. If the status is pending (MonCash), check again until completed or failed.

NatCash account holder

GEThttps://api.levapay.dev/test/v1/wallets/50940885084?network=natcash

Returns the account holder name of a NatCash wallet and creates a 100 HTG verification quote: confirm it with POST /transfers only if you want to send it. Not available for MonCash.

{
  "ok": true,
  "data": {
    "network": "natcash",
    "wallet_masked": "509****5084",
    "beneficiary": "Test account",
    "quote_id": "qt_028c3443d910b8ed7db3",
    "note": "Cotización de verificación (100 HTG). Confirme con POST /transfers si desea enviarla."
  }
}

Errors and statuses

HTTPMeaning
401Invalid user or key, or a key from the other mode
402Insufficient prepaid balance
403Account not yet approved for production (PROD only)
404Transfer or endpoint not found
409Quote already used, or idempotency_key reused with a different body
422Invalid data or expired quote
429More than 60 requests per minute with the same key
503Payout service temporarily unavailable
{ "ok": false, "message": "Saldo prepago insuficiente." }

Transfer statuses: pending, completed and failed. Your balance is debited only when the transfer is accepted; if it fails later, the amount goes back to your balance.

API error messages are returned in Spanish.

Examples

cURL: quote a NatCash transfer (TEST)

curl -s -X POST https://api.levapay.dev/test/v1/transfers/quote \
  -H "Content-Type: application/json" \
  -H "X-Api-User: YOUR_USER" \
  -H "X-Api-Key: YOUR_PRIVATE_KEY" \
  -d '{"network":"natcash","wallet":"50940885084","amount_htg":100}'

cURL: confirm the transfer

curl -s -X POST https://api.levapay.dev/test/v1/transfers \
  -H "Content-Type: application/json" \
  -H "X-Api-User: YOUR_USER" \
  -H "X-Api-Key: YOUR_PRIVATE_KEY" \
  -d '{"quote_id":"qt_...","idempotency_key":"send-001"}'

PHP

<?php
$base = 'https://api.levapay.dev/test/v1';
$headers = [
    'Content-Type: application/json',
    'X-Api-User: YOUR_USER',
    'X-Api-Key: YOUR_PRIVATE_KEY',
];

function post(string $url, array $body, array $headers): array {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POSTFIELDS => json_encode($body),
    ]);
    return json_decode((string) curl_exec($ch), true);
}

$quote = post("$base/transfers/quote", [
    'network' => 'natcash', // or moncash
    'wallet' => '50940885084',
    'amount_htg' => 100,
], $headers);

$transfer = post("$base/transfers", [
    'quote_id' => $quote['data']['quote_id'] ?? '',
    'idempotency_key' => 'send-' . uniqid(),
], $headers);
echo $transfer['data']['status'] ?? $transfer['message'];

Node.js

const base = 'https://api.levapay.dev/test/v1';
const headers = {
  'Content-Type': 'application/json',
  'X-Api-User': 'YOUR_USER',
  'X-Api-Key': process.env.LEVAPAY_KEY, // YOUR_PRIVATE_KEY
};
const post = (path, body) =>
  fetch(base + path, { method: 'POST', headers, body: JSON.stringify(body) })
    .then((r) => r.json());

const quote = await post('/transfers/quote', {
  network: 'natcash', // or moncash
  wallet: '50940885084',
  amount_htg: 100,
});

const transfer = await post('/transfers', {
  quote_id: quote.data.quote_id,
  idempotency_key: `send-${Date.now()}`,
});
console.log(transfer.data?.status ?? transfer.message);

Ready to integrate?

Create a free account and get your TEST keys in minutes.