moneybee
Home / Developers

Build on MoneyBee.
One API for all of it.

A REST API with predictable JSON, signed webhooks and SDKs for TypeScript, Python, Java and PHP.

Overview

The MoneyBee API is organised around resources such as payment intents, payment links, payouts and webhooks. Requests and responses are JSON over HTTPS. Amounts are always integers in minor units with a currency, so AED 100.00 is {"minor": 10000, "currency": "AED"}.

EnvironmentBase URL
Productionhttps://api.moneybee.world
SandboxShared with your sandbox keys during onboarding

Need sandbox access? Write to pt@moneybee.world or message us on WhatsApp and we will send keys the same day.

Authentication

Send your secret API key as a bearer token on every request. Keep secret keys on your server; never put them in an app or a web page.

curl https://api.moneybee.world/v1/balances/available \
  -H "authorization: Bearer $MONEYBEE_KEY"

Quickstart

1. Install an SDK

npm install @moneybee/sdk

2. Take your first payment

import { MoneyBeeClient } from '@moneybee/sdk';

const mb = new MoneyBeeClient({
  baseUrl: 'https://api.moneybee.world',
  apiKey: process.env.MONEYBEE_KEY,
});

const payment = await mb.payments.create({
  amount: { minor: 10000, currency: 'AED' },
});
console.log(payment.id, payment.status);

3. Listen for the result

Register a webhook endpoint (see Webhooks) and fulfil the order when you receive payment_intent.succeeded.

Payments

A payment intent tracks one payment from creation to settlement. MoneyBee routes it to the best connector under your rules and retries on soft declines.

curl -X POST https://api.moneybee.world/v1/payment_intents \
  -H "authorization: Bearer $MONEYBEE_KEY" \
  -H "idempotency-key: order-1042" \
  -H "content-type: application/json" \
  -d '{"amount": {"minor": 10000, "currency": "AED"}, "capture": "manual"}'

With manual capture, capture later, in full or in part. Refunds work the same way.

POST /v1/payment_intents/{id}/capture
POST /v1/payment_intents/{id}/refunds   {"amount": {"minor": 2500, "currency": "AED"}}

Create a link, share the URL or QR, and get a webhook when it is paid. Links can be single-use or reusable and can expire.

curl -X POST https://api.moneybee.world/v1/payment_links \
  -H "authorization: Bearer $MONEYBEE_KEY" \
  -H "content-type: application/json" \
  -d '{"amount": {"minor": 45000, "currency": "AED"}, "description": "Table for 4, Friday"}'

Payouts

Pay out from your available balance. Payouts can require a second approver (maker-checker) before they settle.

GET  /v1/balances/available
POST /v1/payouts
POST /v1/payouts/{id}/approve
GET  /v1/reserves

Onboarding

Create an onboarding case for a new merchant, attach documents, and let MoneyBee agents read them and fill the application. You get a webhook as the case moves through review. Merchants who already have an approved live MID skip this step and are provisioned directly.

POST /v1/onboarding/cases
GET  /v1/onboarding/cases/{id}

Onboarding webhooks carry x-moneybee-timestamp and x-moneybee-signature headers, verified the same way as below.

Webhooks

Register an HTTPS endpoint with POST /v1/webhooks. Each event is a JSON body {"id", "type", "data"} signed in the mb-signature header:

mb-signature: t=1767225600,v1=5f2b...e9

v1 is the hex HMAC-SHA256 of t + "." + rawBody using your endpoint secret. Reject events older than 300 seconds.

import crypto from 'node:crypto';

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const age = Math.abs(Date.now() / 1000 - Number(parts.t));
  if (age > 300) return false;
  const expected = crypto.createHmac('sha256', secret).update(`${parts.t}.${rawBody}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Respond with any 2xx status quickly and do the work afterwards. Events can arrive more than once, so make your handler safe to repeat using the event id.

Idempotency

Send an idempotency-key header on every POST. If a request times out, retry with the same key and you will get the original result instead of a second payment.

Errors

StatusMeaning
400The request is invalid. The body says which field.
401Missing or wrong API key.
402The payment was declined. See decline_code.
404The resource does not exist.
409Idempotency key reused with a different body.
429Too many requests. Back off and retry.
5xxSomething went wrong on our side. Retry with the same idempotency key.

Testing

In the sandbox, the last two digits of the amount in minor units choose the outcome:

Amount ends inResultExample
01Soft decline, insufficient_funds. Cascading retries the next route.10001
02Hard decline, stolen_card. No retry.10002
03requires_action, a 3-D Secure challenge.10003
anything elseSucceeds.10000

Test tokens sbx_hard, sbx_soft_all and sbx_cascade force a hard decline, a soft decline on every route, or a cascade to the second route.

Endpoints

AreaEndpoints
PaymentsPOST/v1/payment_intents, /capture, /refunds
Payment linksPOST/v1/payment_links
Payouts and balances/v1/payouts, /approve, /settle, /v1/balances/available, /v1/reserves
Disputes/v1/disputes
Crypto/v1/crypto/deposits
Cards/v1/cards, /fund, /spend
Billing/v1/invoices, /v1/subscriptions
Treasury/v1/fx/quote, /v1/reconcile
Platform/v1/routing, /v1/connectors, /v1/modules, /v1/webhooks, /v1/onboarding/cases

SDKs and plugins

TypeScript

const mb = new MoneyBeeClient({ baseUrl, apiKey });
const p = await mb.payments.create({ amount: { minor: 10000, currency: 'AED' } });
await mb.payments.capture(p.id);
await mb.payments.refund(p.id, { minor: 2500, currency: 'AED' });

Python

from moneybee import MoneyBeeClient, Amount

mb = MoneyBeeClient("https://api.moneybee.world", key)
payment = mb.create_payment(Amount(10000, "AED"))

Java and PHP

SDKs with the same methods are available for Java and PHP. Ask us for access.

Botim

Botim Pay wallet, cards, Apple Pay, Google Pay, Samsung Pay, holds and subscriptions through one connector. See the Botim via MoneyBee guide.

E-commerce plugins

Ready plugins for WooCommerce, Magento, Medusa and OpenCart. Install, paste your key, and MoneyBee checkout appears at the till.

Stuck? We answer developers directly: pt@moneybee.world or WhatsApp +971 55 861 2001.