API Documentation

Overview

The DroppCash API lets your website or app accept payments, 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.

Authentication & Requests

1. Get your API access key. Sign up or log in, then open the API key page in your user dashboard. Use the key only on your server and never put it in a web page or mobile app.

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 user dashboard you can set the API service mode to test or active (live).

  • 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 your wallet is credited.

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.

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 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.

  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)

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.

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. or Transaction 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.
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.
  • 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