API Documentation

Overview

The DroppCash API lets your website or app accept payments and take payments through escrow. With a user API key you can also create escrows and send invoices. Everything below is a plain HTTPS request, so you can use any language.

How a payment works

  1. Your server calls POST /payment/process with the amount, currency and your own order reference. You get back a url.
  2. You send the buyer to that url. The buyer signs in with their DroppCash account and confirms the payment.
  3. DroppCash sends the result to your web_hook and redirects the buyer to your success_url.
  4. Your server calls GET /payment/check-validity to confirm the payment is real, then delivers the goods.

Which API key should I use?

DroppCash has two kinds of accounts, and each one has its own API access key. Both keys work the same way and use the same addresses. They differ in who gets paid and in what you can create.

WhatMerchant API keyUser API key
Where to get itMerchant dashboard, API key pageUser dashboard, API key page
Made forA business or shop that sells to customersA person, marketplace or platform that also sends money, escrows and invoices
Start a payment and confirm itYes. You are paid into your merchant walletYes. You are paid into your user wallet
Escrow Checkout (your customer pays you through escrow)Yes. Paid into your merchant wallet when the buyer releasesYes. Paid into your user wallet when the buyer releases
Create an Escrow (you put your own money in escrow for someone)No (answers with code 403)Yes
Create an InvoiceNo (answers with code 403)Yes
Name the buyer sees at checkoutYour business nameYour account name
  • Want to offer escrow to your customers? Use Escrow Checkout. It works with both kinds of key. Create an Escrow is a different call: it spends your own user-wallet money.
  • A key belongs to the account that made it. Create the key in the account that should receive the money. If you run a business, use the merchant dashboard. Keys made before merchant keys existed belong to user accounts.
  • Business name. Merchant keys show the business name from your merchant profile. If you have not set one, your account name is shown instead.

Authentication & Requests

1. Get your API access key. Log in to the account that should be paid and open its API key page: in the merchant dashboard for a business, or in the user dashboard for an individual (see Which API key should I use?). No account yet? Sign up as a merchant or as a user. Use the key only on your server and never put it in a web page or mobile app. Creating a new key stops the old one working.

2. Send it as a Bearer token in the Authorization header of every request:

Authorization: Bearer YOUR_ACCESS_KEY
Accept: application/json
Content-Type: application/json

3. Send your data as JSON (recommended) or as normal form fields. Both work.

ItemValue
Base URLhttps://droppcash.app
Start a paymentPOST /payment/process
Confirm a paymentGET /payment/check-validity
Create an escrowPOST /payment/make-escrow
Create an invoicePOST /payment/create-invoice

Test Mode & Live Mode

In your dashboard (merchant or user) you can set the API service mode to test or active (live). Each key has its own mode.

  • Test mode: no money moves and no wallet balance is needed. The checkout, webhook and redirect all work exactly as in live mode, so you can test your whole integration.
  • Active (live) mode: the buyer's wallet is charged and the wallet of the account that owns the key is credited: the merchant wallet for a merchant key, the user wallet for a user key.

In both modes the buyer signs in with a DroppCash account during checkout, so create a second test account to play the buyer. In live mode that account also needs a wallet in the payment currency with enough balance.

Start a Payment

POST https://droppcash.app/payment/process

ParamTypeDescription
currency_codestring, max 4Currency to charge, e.g. USD, NGN, BTC. Must be one of the supported currencies. Required
amountnumberAmount to charge, greater than 0, with a decimal point (e.g. 0.02). Crypto currencies allow up to 8 decimal places; other currencies use 2. Required
customstring, max 20Your own order or customer reference. It is returned to you after payment so you can match it to your order. Required
detailsstring, max 255What the buyer is paying for. Required
customer_emailemail, max 30Buyer email address. Required
web_hookURLYour server URL that receives the payment result (server to server). Required
success_urlURLWhere the buyer is sent after paying. Required
cancel_urlURLWhere the buyer is sent if they cancel. Required

The access key is not a body parameter. Send it in the Authorization: Bearer header.

What the buyer sees and pays

  • The checkout shows the name of the account that owns the key: your business name for a merchant key, your account name for a user key.
  • The buyer pays exactly amount. The DroppCash payment fee is taken out of what you receive, and the charge field of the result shows it.
  • The buyer must have a DroppCash user account with a wallet in that currency. Merchant accounts cannot pay. A user also cannot pay a payment that was made with their own user key.
  • If the buyer's balance is too low, the checkout offers a button to add money by card or bank transfer. They then go back to your shop and start the payment again.

cURL

curl -X POST https://droppcash.app/payment/process \
  -H "Authorization: Bearer YOUR_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "custom": "ORDER-1001",
  "currency_code": "USD",
  "amount": 280.00,
  "details": "Digital Product",
  "web_hook": "https://yoursite.com/web_hook.php",
  "success_url": "https://yoursite.com/success",
  "cancel_url": "https://yoursite.com/cancel",
  "customer_email": "customer@mail.com"
}'

PHP

<?php
$parameters = [
    'custom'         => 'ORDER-1001',
    'currency_code'  => 'USD',
    'amount'         => 280.00,
    'details'        => 'Digital Product',
    'web_hook'       => 'https://yoursite.com/web_hook.php',
    'success_url'    => 'https://yoursite.com/success',
    'cancel_url'     => 'https://yoursite.com/cancel',
    'customer_email' => 'customer@mail.com',
];

$ch = curl_init('https://droppcash.app/payment/process');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Accept: application/json',
    'Content-Type: application/json',
    'Authorization: Bearer YOUR_ACCESS_KEY',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if (($response['code'] ?? 0) === 200) {
    header('Location: ' . $response['url']);   // send the buyer to checkout
    exit;
}
echo 'Error: ' . json_encode($response['message'] ?? 'Unknown error');

Node.js

// Node.js 18+ (run this on your server, never in the browser)
const res = await fetch('https://droppcash.app/payment/process', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_ACCESS_KEY',
    'Content-Type': 'application/json',
    'Accept': 'application/json',
  },
  body: JSON.stringify({
    custom: 'ORDER-1001',
    currency_code: 'USD',
    amount: 280.0,
    details: 'Digital Product',
    web_hook: 'https://yoursite.com/web_hook',
    success_url: 'https://yoursite.com/success',
    cancel_url: 'https://yoursite.com/cancel',
    customer_email: 'customer@mail.com',
  }),
});
const data = await res.json();
if (data.code === 200) {
  // redirect the buyer to data.url
} else {
  console.error(data.message);
}

Python

import requests

r = requests.post(
    "https://droppcash.app/payment/process",
    headers={"Authorization": "Bearer YOUR_ACCESS_KEY"},
    json={
        "custom": "ORDER-1001",
        "currency_code": "USD",
        "amount": 280.00,
        "details": "Digital Product",
        "web_hook": "https://yoursite.com/web_hook",
        "success_url": "https://yoursite.com/success",
        "cancel_url": "https://yoursite.com/cancel",
        "customer_email": "customer@mail.com",
    },
    timeout=30,
)
data = r.json()
if data["code"] == 200:
    checkout_url = data["url"]   # redirect the buyer here
else:
    print(data["message"])

Success response

{
  "code": 200,
  "status": "OK",
  "payment_id": "AIYmQIOAz0GlmsjfhgiOeu304",
  "message": "Your payment has been processed. Please follow the URL to complete the payment.",
  "url": "https://droppcash.app/process-checkout?payment_id=AIYmQIOAz0GlmsjfhgiOeu304"
}

Save the payment_id with your order and redirect the buyer to url.

Payment Result (Webhook & Redirect)

When the buyer pays, DroppCash does two things with the same data:

  • Webhook: a form-encoded POST to your web_hook URL. Respond with any 2xx status. The reply is not read and the call is not retried.
  • Redirect: the buyer is sent to your success_url with the same fields added as a query string (?code=200&status=OK&payment_id=...).
FieldDescription
code, status200 and OK for a completed payment
payment_idThe ID returned when you started the payment
transactionThe DroppCash transaction reference
amountAmount paid (up to 3 decimal places)
chargeThe fee applied to this payment
currencyCurrency code
customYour reference from the request
datePayment date, DD-MM-YYYY

PHP webhook example

<?php
// web_hook.php - receives the payment result from DroppCash
$paymentId = $_POST['payment_id'] ?? '';
$custom    = $_POST['custom'] ?? '';

// 1. Never trust this request on its own. Ask DroppCash if the payment is real
//    (see "Confirm a Payment" below).
// 2. Match $custom and the amount with YOUR order record.
// 3. Make sure you only fulfil each order once - the webhook can arrive
//    together with the buyer's redirect.

http_response_code(200);

Node.js webhook example

// Node.js (Express) webhook example
app.use(express.urlencoded({ extended: false }));

app.post('/web_hook', async (req, res) => {
  const { payment_id, custom } = req.body;
  // 1. confirm with check-validity (next section)
  // 2. match custom and amount with your own order
  // 3. fulfil the order once only
  res.sendStatus(200);
});

Confirm a Payment

GET https://droppcash.app/payment/check-validity?payment_id=PAYMENT_ID

Send the payment_id as a query parameter and your access key in the Authorization header. This must be a GET request.

cURL

curl -G https://droppcash.app/payment/check-validity \
  -H "Authorization: Bearer YOUR_ACCESS_KEY" \
  --data-urlencode "payment_id=AIYmQIOAz0GlmsjfhgiOeu304"

PHP

<?php
$paymentId = 'AIYmQIOAz0GlmsjfhgiOeu304';

$ch = curl_init('https://droppcash.app/payment/check-validity?payment_id=' . urlencode($paymentId));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Accept: application/json',
    'Authorization: Bearer YOUR_ACCESS_KEY',
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if (($response['code'] ?? 0) === 200) {
    // payment is completed - safe to deliver the order
}

Node.js

const url = new URL('https://droppcash.app/payment/check-validity');
url.searchParams.set('payment_id', 'AIYmQIOAz0GlmsjfhgiOeu304');

const res = await fetch(url, {
  headers: { 'Authorization': 'Bearer YOUR_ACCESS_KEY', 'Accept': 'application/json' },
});
const data = await res.json();
if (data.code === 200) {
  // payment is completed - safe to deliver the order
}

Python

import requests

r = requests.get(
    "https://droppcash.app/payment/check-validity",
    params={"payment_id": "AIYmQIOAz0GlmsjfhgiOeu304"},
    headers={"Authorization": "Bearer YOUR_ACCESS_KEY"},
    timeout=30,
)
if r.json()["code"] == 200:
    pass  # payment is completed - safe to deliver the order

Responses

// Payment completed
{ "code": 200, "status": "OK", "message": "Transaction is valid" }

// Payment not found or not completed yet
{ "code": 404, "status": "error", "message": "Transaction Not Found." }

// Wrong or missing access key
{ "code": 401, "status": "error", "message": "Invalid API credentials." }

Create an Escrow

Escrow holds money safely until it is released to the receiver. It suits marketplaces. The money comes from the user wallet of the account that owns the access key, in the currency you choose, and is taken immediately.

POST https://droppcash.app/payment/make-escrow

ParamTypeDescription
receiver_emailemailEmail of the person who will receive the escrow. They must already have a DroppCash account. Required
currency_codestringCurrency of the escrow, e.g. NGN. You need a wallet in this currency. Required
amountnumberAmount to hold, greater than 0. Required
descriptionstringWhat the escrow is for. Required
pay_chargebooleantrue: you pay the escrow charge on top of the amount. false: the charge is taken from the amount when it is released. Required

cURL

curl -X POST https://droppcash.app/payment/make-escrow \
  -H "Authorization: Bearer YOUR_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "receiver_email": "seller@mail.com",
    "currency_code": "NGN",
    "amount": 20,
    "description": "Digital Product",
    "pay_charge": true
  }'

PHP

<?php
$parameters = [
    'receiver_email' => 'seller@mail.com',
    'currency_code'  => 'NGN',
    'amount'         => 20,
    'description'    => 'Digital Product',
    'pay_charge'     => true,
];

$ch = curl_init('https://droppcash.app/payment/make-escrow');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Accept: application/json',
    'Content-Type: application/json',
    'Authorization: Bearer YOUR_ACCESS_KEY',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

Responses

// Success
{ "code": 200, "status": "OK", "message": "An Escrow Has Been Made to seller@mail.com" }

// Validation problem (message is a list)
{ "code": 422, "status": "error", "message": ["The selected receiver email is invalid."] }

// Not enough money in your wallet
{ "code": 422, "status": "error", "message": "Insufficent Balance In Your Wallet" }

Create an Invoice

Create an invoice for your customer. DroppCash emails them a payment link and also returns it to you so you can redirect them straight to a clean checkout page.

POST https://droppcash.app/payment/create-invoice

ParamTypeDescription
invoice_tostringName of the person being invoiced. Required
emailemailCustomer email. The customer must already have a DroppCash account. Required
currency_codestringCurrency the invoice is paid in, e.g. NGN. Required
itemarray of stringsNames of the items. Each name must be unique. Required
amountarray of numbersPrice of each item, in the same order as item. Both arrays must be the same length and every amount greater than 0. The invoice total is the sum. Required
addressstringCustomer address. Optional
invoice_statusstringpublish makes the invoice payable, cancel cancels it. If left out the invoice is saved as a draft. Optional
allow_escrowbooleantrue lets the customer pay through escrow. Optional
pay_chargebooleanOnly matters when the customer pays through escrow: true means the escrow charge is paid on top of the invoice total. Optional
success_urlURLWhere to send the customer after paying. Optional
cancel_urlURLWhere to send the customer if they cancel. Optional

cURL

curl -X POST https://droppcash.app/payment/create-invoice \
  -H "Authorization: Bearer YOUR_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_to": "Test User",
    "email": "customer@mail.com",
    "currency_code": "NGN",
    "item": ["Baby doll", "Toy car", "Gift wrap"],
    "amount": [10, 20, 30],
    "address": "Lagos, Nigeria",
    "allow_escrow": true,
    "pay_charge": true,
    "invoice_status": "publish",
    "success_url": "https://yoursite.com/success",
    "cancel_url": "https://yoursite.com/cancel"
  }'

PHP

<?php
$parameters = [
    'invoice_to'     => 'Test User',
    'email'          => 'customer@mail.com',
    'currency_code'  => 'NGN',
    'item'           => ['Baby doll', 'Toy car', 'Gift wrap'],
    'amount'         => [10, 20, 30],
    'address'        => 'Lagos, Nigeria',
    'allow_escrow'   => true,
    'pay_charge'     => true,
    'invoice_status' => 'publish',
    'success_url'    => 'https://yoursite.com/success',
    'cancel_url'     => 'https://yoursite.com/cancel',
];

$ch = curl_init('https://droppcash.app/payment/create-invoice');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Accept: application/json',
    'Content-Type: application/json',
    'Authorization: Bearer YOUR_ACCESS_KEY',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if (($response['code'] ?? 0) === 200) {
    header('Location: ' . $response['url']);   // customer pays on the invoice page
    exit;
}

Responses

// Success
{
  "code": 200,
  "status": "OK",
  "message": "Invoice Has Been Made",
  "url": "https://droppcash.app/view-invoice/eyJpdiI6..."
}

// Customer email has no account (a link to register is returned)
{ "code": 500, "status": "OK", "message": "User Not Registerred On Dropppay", "url": "https://droppcash.app/user/register" }

// item and amount lists do not match
{ "code": 500, "status": "error", "message": "An Error In Your API Parameters Caused This." }

Escrow Checkout (buyer pays into escrow)

With escrow checkout the buyer pays into DroppCash escrow instead of paying you directly. The money is held safely until the buyer releases it to you. You are the seller: the account that owns the API access key is the one that gets paid. This works with both merchant keys and user keys: a merchant key is paid into the merchant wallet, a user key into the user wallet. The buyer sees your business name (merchant key) or your account name (user key) on the checkout.

  1. Your server calls POST /payment/escrow/process and gets a checkout url.
  2. You send the buyer to that URL. The buyer signs in to their DroppCash account and funds the escrow.
  3. DroppCash redirects the buyer to your success_url and calls your web_hook with event escrow.funded. You can now ship the goods or deliver the service.
  4. When the buyer has received the order, they release the payment from their DroppCash account (My Escrows). You get the event escrow.released and the money is in your wallet.
  5. If something goes wrong, you can refund the buyer, or either side can open a dispute that DroppCash support decides.
EndpointWhat it does
POST /payment/escrow/processStart an escrow payment and get the buyer checkout URL
GET /payment/escrow/statusCheck the current state of an escrow payment
POST /payment/escrow/refundReturn the held money to the buyer (while it is still held)
POST /payment/escrow/simulateTest mode only: pretend to be the buyer (release or dispute)

Merchant accounts have no escrow screen in the dashboard yet, so follow an escrow with the status call and the webhooks below.

Start an escrow payment takes the same fields as Start a Payment (currency_code, amount, custom, details, customer_email, web_hook, success_url, cancel_url) plus one optional field:

ParamTypeDescription
pay_chargebooleantrue: the buyer pays the escrow fee on top of the amount. false (default): the fee is taken from the amount when the money is released to you. Optional

cURL

curl -X POST https://droppcash.app/payment/escrow/process \
  -H "Authorization: Bearer YOUR_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "currency_code": "NGN",
    "amount": 7500.50,
    "custom": "ORDER-1001",
    "details": "Laptop bag",
    "customer_email": "buyer@mail.com",
    "web_hook": "https://yoursite.com/webhook.php",
    "success_url": "https://yoursite.com/success.php",
    "cancel_url": "https://yoursite.com/cancel.php",
    "pay_charge": false
  }'
{
  "code": 200,
  "status": "OK",
  "payment_id": "AIYmQIOAz0GlmsjfhgiOeu304",
  "message": "Your escrow payment has been created. Please send the buyer to the URL to fund the escrow.",
  "url": "https://droppcash.app/payment/process-checkout?payment_id=AIYmQIOAz0GlmsjfhgiOeu304"
}

Check the status with GET /payment/escrow/status?payment_id=... (Bearer key). Always use this call, never the address bar, to confirm what happened.

{
  "code": 200,
  "status": "OK",
  "escrow": {
    "payment_id": "AIYmQIOAz0GlmsjfhgiOeu304",
    "custom": "ORDER-1001",
    "amount": "7500.5",
    "currency": "NGN",
    "test": 0,
    "escrow_id": "42",
    "escrow_status": "held",
    "transaction": "K3JD8SL2QW1X",
    "charge": "75",
    "funded_at": "2026-10-16T10:15:00+00:00"
  }
}
escrow_statusMeaning
awaiting_paymentThe buyer has not funded the escrow yet
heldFunded: the money is held. You can ship or deliver.
releasedThe buyer released the money to you
disputedA dispute is open. DroppCash support decides who gets the money.
refundedThe money went back to the buyer
released_by_adminDroppCash support decided in your favour and paid you
closedThe escrow was closed with no payout

Refund the buyer (only while the status is held): POST /payment/escrow/refund with {"payment_id": "..."}. The buyer gets back everything they paid: the held amount, plus the escrow fee if the buyer paid it (pay_charge true). The response shows the refunded total.

{ "code": 200, "status": "OK", "message": "Escrow refunded to the buyer.", "refunded": "7575.5" }

// not refundable (already released, disputed or refunded)
{ "code": 422, "status": "error", "message": "Escrow can only be refunded while it is held." }

Webhook events. DroppCash sends a form-encoded POST to your web_hook URL every time something happens. Events: escrow.funded, escrow.released, escrow.refunded, escrow.disputed, escrow.closed. Answer with any 2xx status. Calls are not retried, so also use the status call as a safety net.

FieldDescription
eventOne of the events above
statusThe escrow_status after the event
payment_id, escrow_idIdentify the payment and the escrow
transactionDroppCash transaction reference
amount, currency, customAmount, currency and your own reference from the request
test1 for a test-mode event, 0 for live
dateTime of the event (ISO 8601)

Every webhook is signed. The header X-DroppCash-Signature holds sha256= followed by the HMAC-SHA256 of the raw request body, using your API access key as the secret. Reject any call whose signature does not match, then also check that amount and currency match your order.

PHP

<?php
$raw       = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_DROPPCASH_SIGNATURE'] ?? '';
$expected  = 'sha256=' . hash_hmac('sha256', $raw, 'YOUR_ACCESS_KEY');

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}
parse_str($raw, $event);   // $event['event'], $event['payment_id'], ...

Node.js

// Node.js (Express): use express.raw({ type: '*/*' }) so you get the raw body
const crypto = require('crypto');
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
  const expected = 'sha256=' + crypto.createHmac('sha256', 'YOUR_ACCESS_KEY').update(req.body).digest('hex');
  const given = req.get('X-DroppCash-Signature') || '';
  const ok = expected.length === given.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given));
  if (!ok) return res.sendStatus(401);
  const event = Object.fromEntries(new URLSearchParams(req.body.toString()));
  res.sendStatus(200);
});

Python

import hmac, hashlib
from urllib.parse import parse_qs

def is_genuine(raw_body: bytes, signature_header: str, access_key: str) -> bool:
    expected = "sha256=" + hmac.new(access_key.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header or "")

# event = {k: v[0] for k, v in parse_qs(raw_body.decode()).items()}

Test mode. With a test-mode key nothing is charged and no real escrow exists, but the whole flow works: checkout, redirect, webhooks, status and refund. Because no real buyer is there to release the money, use POST /payment/escrow/simulate with {"payment_id": "...", "action": "released"} (or "disputed") to act as the buyer. This call is refused for live payments.

See it in action

The screenshot below is from a live integration: an online healthcare booking platform (DocPlus) that takes DroppCash payments for its appointments. Patients pay with DroppCash, and the platform marks each appointment Paid the moment our API confirms the money. Everything on that screen is built from the calls and webhooks documented above — nothing else is installed.

Appointment list of a healthcare platform showing DroppCash payments marked Paid
The platform's appointment list. Every green Paid badge is a DroppCash payment that the platform's server has confirmed. Amounts are in Nigerian naira (NGN).

How the screen maps to the API

On the screenWhere it comes from
Amount (NGN 20,370.00)The amount and currency_code from the Start a Payment or Create an Escrow request
Payment Status PaidA flag on the platform's own order, set only after Confirm a Payment returns code 200 (normal payment) or the signed escrow.funded webhook arrives (escrow) — never from the success redirect alone
DateWhen checkout was completed; the platform stores it together with the payment_id
Status and actions (Approve, Complete, Add Prescription, Video Call)The platform's own business logic. DroppCash only tells it that the money is confirmed or safely held.

End to end for one appointment (escrow checkout, the amounts from the screenshot):

# 1. Patient clicks Pay — the platform starts an escrow payment
curl -X POST https://droppcash.app/payment/escrow/process \
  -H "Authorization: Bearer YOUR_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "currency_code": "NGN",
    "amount": 20370.00,
    "custom": "APT-2043",
    "details": "Consultation with Dr. Adeyemi",
    "customer_email": "patient@mail.com",
    "web_hook": "https://theplatform.com/droppcash/webhook",
    "success_url": "https://theplatform.com/appointment/2043/paid",
    "cancel_url": "https://theplatform.com/appointment/2043"
  }'
// 2. The patient funds the escrow at the checkout URL. This signed webhook arrives:
event=escrow.funded&status=held&payment_id=AIYmQIOAz0GlmsjfhgiOeu304&escrow_id=42
&transaction=K3JD8SL2QW1X&amount=20370¤cy=NGN&custom=APT-2043&test=0
&date=2026-11-03T13:58:02+00:00

// 3. The platform verifies the X-DroppCash-Signature header, matches custom and
//    amount to its order, and only then marks the appointment Paid.
// 4. After the consultation the patient releases the payment (escrow.released)
//    and the money lands in the merchant wallet.

Plugins for every major store platform

DroppCash ships an official plugin for each of the major store platforms. A plugin connects your shop in minutes: you paste your access key, choose the mode, and the plugin does the rest — it starts the payment, receives the webhook, verifies the money, and only then marks the order paid. Every plugin is a thin wrapper around the same API documented on this page, and each package ships with its own step-by-step guide (DOCUMENTATION.md or INSTALLATION.md inside the zip).

Payment gateway WooCommerce WordPress 6.0+ · WooCommerce 7.0+ · PHP 7.4+

“Pay with DroppCash” at checkout — classic and block checkout, HPOS ready, scheduled re-checks.

Download .zip ↓
Payments app Shopify Node 20+ host · Shopify Payments Partner approval

Offsite payments app: buyers are sent from the Shopify checkout to DroppCash and back; the app resolves the session only after verifying.

Download .zip ↓
Payment module Magento 2 Magento 2.4.4–2.4.7 · PHP 7.4–8.3

Native payment method with the key stored encrypted, its own webhook endpoint and a payment log table.

Download .zip ↓
Payment module PrestaShop PrestaShop 1.7.6, 8.x, 9.x · PHP 7.4+

Orders wait in Awaiting DroppCash payment until the payment is confirmed, then become Payment accepted.

Download .zip ↓
Payment extension OpenCart OpenCart 3.0.x & 4.0.2.x · PHP 7.4+

One package with an ocmod build for each major version; configurable order statuses and one reusable payment link per order.

Download .zip ↓
Self-hosted app BigCommerce Any Node 20+ host · no partner approval

Works around BigCommerce's closed checkout: buyers pick a renamed offline method and are redirected to DroppCash from the order confirmation page.

Download .zip ↓
Two routes in one package Wix Premium Wix site, or Wix PSP approval

A Velo plugin for your own store (no approval needed) plus a payment-provider server to offer DroppCash to every Wix merchant.

Download .zip ↓
Direct API Any other platform Any language, any stack

Start a Payment or an Escrow Checkout from your own code — that is all a plugin does internally.

Go to the API →

What every plugin asks you for — the same three things on every platform:

SettingWhat you enter
Access keyCopy it from API Access Key in your DroppCash account and paste it into the plugin settings
ModeStart in Test mode, place a test order, then switch the key to Active when everything works
Everything elseNothing. The plugin creates its own webhook, success and cancel URLs, and sends the platform's order number as custom

How the plugin is linked to each platform:

PlatformHow to link it
WooCommerce (WordPress)WordPress admin → Plugins → Add New Plugin → Upload Plugin with droppcash-for-woocommerce.zip, activate it, then open WooCommerce → Settings → Payments → DroppCash → Manage: tick Enable, paste the access key, choose the payment type (Standard or Escrow), and tick Live mode only when your DroppCash dashboard is Active. For extra safety the key can live in wp-config.php (DROPPCASH_ACCESS_KEY) instead of the database. Orders become Processing after verification; a scheduled check every 10 minutes catches missed webhooks.
ShopifyShopify only lets approved partners add a payment method at checkout, so this package is a payments app: apply in your Shopify Partner account, host the app (Node 20+) and deploy it with the Shopify CLI. Each merchant opens the app's setup link, approves the install and pastes their access key, which is stored encrypted. Activate DroppCash under Settings → Payments in Shopify admin — test mode first. At checkout the buyer is redirected to DroppCash; the app tells Shopify the payment succeeded only after verifying it. Refund requests land in the app's admin queue for approval.
Magento 2Unzip so the module sits at app/code/DroppCash/Payment, then run bin/magento module:enable DroppCash_Payment and bin/magento setup:upgrade (plus the compile and static-content steps in production). Configure under Stores → Configuration → Sales → Payment Methods → DroppCash: enabled, title, API access key (checked when you save, stored encrypted), payment type, test mode, fallback email. The webhook address is sent with every payment — keep /droppcash/payment/webhook out of firewall and full-page-cache rules. Orders become Processing with an invoice after verification.
PrestaShopBack Office → Modules → Module Manager → Upload a module with droppcash.zip, then click Configure: title, access key, payment type, test box, fallback email. Finish in Payment → Preferences by ticking DroppCash for the currencies, countries and customer groups you serve. New orders wait in Awaiting DroppCash payment and move to Payment accepted after verification; the confirmation page offers unpaid buyers a Pay now button.
OpenCartPick the build that matches your shop (4.0.2.x or 3.0.x — both ocmod zips are inside the package; keep the file name droppcash.ocmod.zip). Upload it under Extensions → Installer, then Extensions → Extensions → Payments → DroppCash → Install → Edit: title, access key, payment type, test mode, fallback email and your order statuses. The notice (webhook) address is shown on the settings page and sent to DroppCash with every payment. Hidden for subscription carts and unsupported currencies.
BigCommerceNo partner approval needed. Host the small Node app from the package, create a Store-level API account (Orders, Content and Checkout Content: Modify) and fill the .env with the store hash, the access token and your DroppCash key. Enable any offline payment method, rename it DroppCash, and run npm run setup to install the confirmation-page script that redirects buyers to DroppCash. Orders move from Awaiting Payment to Awaiting Fulfillment after verification; for customers who never paid, the app can issue an emailed payment link.
WixTwo routes in one package. A. Velo plugin — for one store, no Wix approval: add the service-plugin files in the Velo editor, save the access key in Secrets Manager, create the DroppCashTransactions collection, publish, then connect under Settings → Accept Payments → DroppCash. B. Payment-provider server — to offer DroppCash to every Wix merchant from their dashboard: host the server, register its connect/transaction/refund URLs in a Wix payment-gateway app, and complete Wix's payment-provider onboarding first.
Any custom website or appUse the API directly — Start a Payment or Escrow Checkout. That is all a plugin does internally; the cards above show the wrapper each platform needs.

How the link works under the hood — identical on every platform:

  1. At checkout the plugin sends POST /payment/process (or /payment/escrow/process) with the amount, currency, buyer email, the platform's order reference in custom, and its own web_hook, success_url and cancel_url.
  2. The buyer is redirected to the DroppCash checkout and pays from their wallet, or funds the escrow.
  3. DroppCash sends the buyer back to the success URL and calls the plugin's webhook. Escrow webhooks are signed with X-DroppCash-Signature and carry the events escrow.funded, escrow.released, escrow.disputed and escrow.refunded — see Escrow Checkout.
  4. Redirect and webhook are treated as hints only. The plugin asks DroppCash directly — check-validity for normal payments, the escrow status call for escrow — compares amount, currency, reference and (for escrow) the test flag, and only then marks the order paid, exactly once, even if several notifications arrive together.
  5. DroppCash does not retry a failed webhook, so the plugins also re-check unfinished payments on a schedule (every 5–10 minutes depending on the platform) and whenever the buyer reopens the return link.

Refunds through the plugins. Escrow, while the money is still held: the refund is full-amount and goes straight back to the buyer. WooCommerce (Refund button on the order), Magento 2 (online credit memo), BigCommerce and Shopify (admin endpoints) and the Wix Velo plugin (refund from Wix Orders) trigger it for you; with PrestaShop and OpenCart you refund from your DroppCash account. Everything else — standard payments, released escrows, partial amounts: DroppCash has no refund call for these, so refund the buyer from your DroppCash account and record it in the shop's admin.

Errors

Remember: the HTTP status is always 200. Check the code field in the JSON body.

codeMeaningWhat to do
200SuccessContinue.
401Invalid API credentials.The access key is missing or wrong. Check the Authorization: Bearer header.
404Requested currency not found., Transaction Not Found. or Merchant account not found.Check currency_code against the supported list, or the payment_id. A payment that is not completed yet also returns 404 on check-validity. For escrow, You do not have a wallet in this currency. means the account that owns the key needs a wallet in that currency.
403Merchant API keys cannot be used to create invoices or escrows yet.Create an Escrow and Create an Invoice need a user API key. For a shop, use Start a Payment or Escrow Checkout instead.
403 / 409Not allowed for this payment (for example simulate on a live payment, or check-validity on an escrow payment)Use the call that matches the payment type, as the message says.
422Validation failed, or Insufficent Balance In Your Wallet (escrow)For validation, message is a list of what to fix. For balance, top up your wallet.
500Server problem, or invoice parameters/customer account problemCheck the invoice item and amount lists and that the customer is registered. If it keeps happening, contact support.

Example validation error:

{
  "code": 422,
  "status": "error",
  "message": [
    "The amount must be greater than 0.",
    "The success url must be a valid URL."
  ]
}

Security Checklist

  • Keep your access key on your server only. If it leaks, create a new one from your dashboard: the old key stops working at once.
  • Create the key in the account that should receive the money (the merchant dashboard for a business).
  • Always confirm a payment with check-validity before you deliver, and compare custom and the amount with your own order.
  • Fulfil each order once only. Store the payment_id against the order and ignore repeats.
  • Use HTTPS for web_hook, success_url and cancel_url.
  • Do not turn off SSL certificate checks (such as CURLOPT_SSL_VERIFYHOST or verify=False) in your own code.

Supported Currencies

Use the currency code exactly as shown. The list updates automatically when new currencies are added.

Currency NameCurrency SymbolCurrency Code
US Dollar$USD
European Euro€EUR
British Pound£GBP
Bangladeshi Taka৳BDT
BitcoinBTCBTC
Indian Rupee₹INR
Japanese Yen¥JPY
Nigerian nairaNNGN
Chinese YuanCN¥CNY
South African RandRZAR
Kenyan ShillingKshKES
Emirati Dirhamد.إAED
Ghanaian CediGH₵GHS
Canadian DollarCan$CAD
Egyptian PoundE£EGP
Rwandan francR₣RWF
Singapore DollarS$SGD
Ugandan ShillingUShUGX
Turkish Lira₺TRY
Australian DollarA$AUD
Malaysian RinggitRMMYR
Romanian leuleiRON
New Zealand DollarNZDNZD
Hungarian forintFtHUF
Mexican PesoMex$MXN
Hong Kong DollarHK$HKD
Brazilian RealR$BRL
Swiss FrancCHfCHF
Bulgarian LevЛв.BGN
Czech KorunaKčCZK
Danish KroneKr.DKK
Norwegian KronekrNOK
Thai Baht฿THB
Ukrainian hryvnia₴UAH
Polish ZlotyzłPLN
Swedish KronaskrSEK
DogecoinƉDOGE
LitecoinŁLTC
Kucoin TokenKCSKCS
SolanaSOLSOL
Binance CoinBNBBNB
USDT₮USDT
EthereumETHETH
ADA₳ADA
TRXTRXTRX
Israeli Shekel₪ILS
West African CFA francF.CFAXOF
Central African CFA franccéfaXAF
Tanzanian shillingTShTZS
Zambian KwachaZKZMW