# Welcome to Malum

Welcome to the Malum Card to Crypto Payment Processor API documentation. Malum offers merchants the ability to accept card payments without the risk of chargebacks by converting card payments into cryptocurrency.

### Base API Endpoint

All API requests should be made to the following base endpoint:

```arduino
https://malum.co/api
```

#### Get Your API Key

To obtain your API key, please visit the following endpoint after logging into your Malum account:

```ruby
https://malum.co/merchant/settings/api
```


# Payment Methods Overview

### Overview

This page provides a detailed overview of all available payment methods along with their associated fees, minimum fees, and transaction limits. This information is crucial for integrating and choosing the appropriate payment processor based on your transaction needs.

### Available Payment Methods

The following table lists each payment method along with its fee structure, minimum fee, and transaction limits:

<table><thead><tr><th width="177">Payment Method</th><th>Fee Structure</th><th>Min Fee</th><th>Min Checkout</th><th>Max Checkout</th></tr></thead><tbody><tr><td>iDEAL</td><td>7% + $0.5 USD</td><td>$2.99 USD</td><td>$4.99 USD</td><td>$299.99 USD</td></tr><tr><td>Coinbase Pay (EUR)</td><td>5% + $0.5 USD</td><td>$1.99 USD</td><td>$9.99 USD</td><td>$9999 USD</td></tr><tr><td>Stripe (EU)</td><td>6% + $0.3 USD</td><td>$1.49 USD</td><td>$3.99 USD</td><td>$10500 USD</td></tr><tr><td>PayPal (EU)</td><td>5% + $0.5 USD</td><td>$1.99 USD</td><td>$29.99 USD</td><td>$5000 USD</td></tr><tr><td>Onramp.Money</td><td>5% + $1.0 USD</td><td>$1.99 USD</td><td>$19.99 USD</td><td>$999.99 USD</td></tr><tr><td>Coinbase Pay (USD)</td><td>5% + $0.5 USD</td><td>$1.99 USD</td><td>$4.99 USD</td><td>$2999 USD</td></tr><tr><td>Coinbase Pay (GBP)</td><td>5% + $0.5 USD</td><td>$1.99 USD</td><td>$9.99 USD</td><td>$9999 USD</td></tr><tr><td>Wert.io (NO KYC)</td><td>7% + $0.5 USD</td><td>$0.99 USD</td><td>$2.99 USD</td><td>$5000 USD</td></tr><tr><td>Bank Transfer</td><td>5% + $2.5 USD</td><td>$3.50 USD</td><td>$9.99 USD</td><td>$2500 USD</td></tr><tr><td>Ramp</td><td>5% + $0.3 USD</td><td>$2.99 USD</td><td>$9.99 USD</td><td>$4999 USD</td></tr><tr><td>Revolut</td><td>3% + $0.3 USD</td><td>$1.99 USD</td><td>$9.99 USD</td><td>$4999 USD</td></tr><tr><td>Transak</td><td>5% + $1.0 USD</td><td>$2.99 USD</td><td>$3.49 USD</td><td>$299999 USD</td></tr><tr><td>Unlimit</td><td>5% + $1.0 USD</td><td>$1.99 USD</td><td>$9.99 USD</td><td>$2999 USD</td></tr><tr><td>Bitcoin</td><td>2% + $0.1 USD</td><td>$0.30 USD</td><td>$9.99 USD</td><td>$500 USD</td></tr><tr><td>Litecoin</td><td>2% + $0.1 USD</td><td>$0.30 USD</td><td>$1.99 USD</td><td>$500 USD</td></tr><tr><td>Binance</td><td>5% + $0.5 USD</td><td>$1.99 USD</td><td>$19.99 USD</td><td>$5000 USD</td></tr><tr><td>Bancontact</td><td>7% + $0.5 USD</td><td>$1.99 USD</td><td>$4.00 USD</td><td>$299.99 USD</td></tr><tr><td>Multibanco</td><td>7% + $0.5 USD</td><td>$1.99 USD</td><td>$3.49 USD</td><td>$299.99 USD</td></tr><tr><td>Przelewy24</td><td>7% + $0.5 USD</td><td>$2.99 USD</td><td>$2.99 USD</td><td>$299.99 USD</td></tr><tr><td>EPS</td><td>7% + $0.5 USD</td><td>$2.99 USD</td><td>$4.99 USD</td><td>$299.99 USD</td></tr><tr><td>USDT (ETH)</td><td>2% + $0.1 USD</td><td>$0.20 USD</td><td>$0.90 USD</td><td>$50000 USD</td></tr><tr><td>Stripe (USD)</td><td>6% + $0.3 USD</td><td>$0.99 USD</td><td>$2.99 USD</td><td>$10500 USD</td></tr><tr><td>PayPal (USA)</td><td>3% + $0.5 USD</td><td>$1.99 USD</td><td>$9.99 USD</td><td>$1999 USD</td></tr><tr><td>CashApp</td><td>3% + $1.0 USD</td><td>$1.99 USD</td><td>$29.99 USD</td><td>$3999 USD</td></tr><tr><td>Coinbase Pay (CAD)</td><td>5% + $0.5 USD</td><td>$1.99 USD</td><td>$9.99 USD</td><td>$9999 USD</td></tr><tr><td>Robinhood</td><td>5% + $0.5 USD</td><td>$2.99 USD</td><td>$9.99 USD</td><td>$1499.99 USD</td></tr><tr><td>PIX</td><td>5% + $0.5 USD</td><td>$2.99 USD</td><td>$29.99 USD</td><td>$500 USD</td></tr><tr><td>AstroPay</td><td>5% + $0.5 USD</td><td>$2.99 USD</td><td>$29.99 USD</td><td>$500 USD</td></tr><tr><td>Faster Payment Bank Transfer</td><td>5% + $0.5 USD</td><td>$2.99 USD</td><td>$19.99 USD</td><td>$500 USD</td></tr><tr><td>Open Banking</td><td>5% + $0.5 USD</td><td>$2.99 USD</td><td>$29.99 USD</td><td>$500 USD</td></tr><tr><td>Venmo</td><td>5% + $0.5 USD</td><td>$1.99 USD</td><td>$19.99 USD</td><td>$5000 USD</td></tr><tr><td>Interac</td><td>2% + $5.0 USD</td><td>$5.00 USD</td><td>$70.00 USD</td><td>$5000 USD</td></tr><tr><td>Mercuryo</td><td>4% + $0.3 USD</td><td>$1.99 USD</td><td>$29.99 USD</td><td>$299.99 USD</td></tr><tr><td>Sardine</td><td>4% + $1.5 USD</td><td>$1.99 USD</td><td>$29.99 USD</td><td>$2999 USD</td></tr><tr><td>Guardarian (USD)</td><td>6% + $1.5 USD</td><td>$2.49 USD</td><td>$19.99 USD</td><td>$50000 USD</td></tr><tr><td>Guardarian (EUR)</td><td>6% + $1.5 USD</td><td>$2.49 USD</td><td>$19.99 USD</td><td>$50000 USD</td></tr></tbody></table>

#### Notes

* **Fee Structure:** Fees are calculated as a percentage of the transaction amount plus a fixed fee.
* **Minimum Fee:** This is the lowest fee that will be applied to any transaction.
* **Minimum Checkout Amount:** This is the minimum amount that can be processed through the payment gateway.
* **Maximum Checkout Amount:** This is the maximum amount that can be processed in a single transaction through the payment gateway.

### Additional Notes

This fee is charged automatically on top of your amount. You will only be charged the merchant fee (Default: 5% + 0.5 USD) if you don't set the Parameter "buyer\_pays\_fees" during the transaction creation.


# Create Transaction

### Overview

This endpoint allows you to initiate a payment transaction. Ensure your request includes all required parameters and valid authorization headers to process the payment successfully.

### HTTP Request

<pre class="language-bash"><code class="lang-bash"><a data-footnote-ref href="#user-content-fn-1">POST</a> https://malum.co/api/v2/payment/create
</code></pre>

### Headers

| Header | Value                        |
| ------ | ---------------------------- |
| MALUM  | `{BUSINESS_ID}:{SECRET_KEY}` |

### Request Body

Send data in JSON format. The following table outlines all parameters, noting which are required:

<table><thead><tr><th width="214">Parameter</th><th>Type</th><th width="143">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>amount</code></td><td>float</td><td>Yes</td><td>Amount to be collected.</td></tr><tr><td><code>currency</code></td><td>string</td><td>Yes</td><td>Currency code (e.g., EUR, USD, JPY, AUD, GBP, RUB).</td></tr><tr><td><code>customer_email</code></td><td>string</td><td>Yes</td><td>Email address of the customer.</td></tr><tr><td><code>cancel_url</code></td><td>string</td><td>Yes</td><td>URL to navigate to if the transaction is cancelled.</td></tr><tr><td><code>success_url</code></td><td>string</td><td>Yes</td><td>URL to redirect the customer to after successful payment.</td></tr><tr><td><code>webhook_url</code></td><td>string</td><td>Yes</td><td>URL to send webhook notifications to.</td></tr><tr><td><code>buyer_pays_fees</code></td><td>boolean</td><td>No</td><td>Whether the customer should pay the merchant fee.</td></tr><tr><td><code>metadata</code></td><td>string</td><td>No</td><td>Additional metadata about the transaction (max 255 chars).</td></tr><tr><td><code>product_title</code></td><td>string</td><td>No</td><td>Product title, max length 32 chars</td></tr><tr><td><code>product_description</code></td><td>string</td><td>No</td><td>Product description, max length 800 chars</td></tr><tr><td><code>product_link</code></td><td>string</td><td>No</td><td>"<a href="https://malum.co/">https://malum.co/</a>" link to product, max length 255 chars</td></tr><tr><td><code>product_image</code></td><td>string</td><td>No</td><td>"<a href="https://placehold.co/600x400">https://placehold.co/600x400</a>" link to an image of the product, max length 255 chars</td></tr><tr><td><code>product_markdown</code></td><td>string</td><td>No</td><td>Markdown product description supports bold, italic, links, images and youtube embeds, max length 2500 chars</td></tr><tr><td><code>merchant_pays_gw_fees</code></td><td>boolean or int</td><td>No</td><td>The value can be true or false | 1 or 0<br><br>If set the merchant pays the gateway fee and its own merchant fee instead of the customer</td></tr></tbody></table>

### Success Response

A successful request returns the following JSON structure:

```json
{
  "status": "success",
  "bpf": false,
  "transaction_id": "TRN_XXXXXXXXX",
  "link": "https://malum.co/checkout/TRN_XXXXXXXXX",
  "timestamp": 10000000
}
```

### Error Response

An unsuccessful request returns the following JSON structure, indicating the nature of the error:

```json
{
  "status": "failed",
  "error": "Amount is too high.",
  "timestamp": 10000000
}
```

### Additional Notes

* Ensure that all required parameters are included in your request.
* The `Authorization` header should be properly formatted with your business ID and secret key.

<br>

[^1]: POST Request


# Malum Checkout Form

This guide shows how to integrate a simple checkout form with the Malum Payment API. It now supports optional product presentation fields that render on the Malum checkout page, along with an additional product signature for integrity.

### Prerequisites

* Malum Business ID
* Malum Private Key
* Ability to edit your site's PHP backend

### Core Flow

1. Collect the required parameters.
2. Create a signed message to authenticate the payment request.
3. Optionally include product presentation fields and create a signed product hash.
4. Post a form to Malum to start the checkout.
5. Handle the webhook notification and user redirects.

### Required Parameters

* `amount` numeric string or integer representing the price in major currency units
* `currency` ISO 4217 code such as `USD`, `EUR`
* `webhook_url` URL on your server to receive payment results
* `success_url` where to redirect the buyer after a successful payment
* `cancel_url` where to redirect if the buyer cancels or the payment fails
* `business_id` your Malum business identifier
* `customer_email` buyer email
* `buyer_pays_fees` `0` or `1`
* `metadata` optional opaque string you receive back
* `signed_message` authentication signature described below

### Optional Product Presentation Parameters

These fields allow Malum to display product details on the hosted checkout.

* `product_markdown` free form Markdown that describes the product
* `product_title` short plain title
* `product_image` absolute URL to a product image
* `product_description` short plain summary
* `product_link` absolute URL to view the product on your site
* `signed_product_hash` integrity signature for the five product fields

### Signatures

#### Payment request signature

```
$signed_message = md5(
    $amount
  . $currency
  . $webhook_url
  . $success_url
  . $cancel_url
  . $customer_email
  . $buyer_pays_fees
  . $metadata
  . $business_id
  . $private_key
);
```

#### Product presentation signature

```
$signed_product_hash = md5(
    $product_markdown
  . $product_title
  . $product_image
  . $product_description
  . $product_link
  . $private_key
);
```

### Quick Test Values

Use these while testing. Replace with real values for production.

```php
<?php
// Test values
$amount = 1;
$currency = 'USD';
$webhook_url = 'https://example.com';
$success_url = 'https://example.com';
$cancel_url = 'https://example.com';
$business_id = 'TEST';
$private_key = 'sec_TEST';
$metadata = '';
$customer_email = 'test@example.com';
$buyer_pays_fees = 0;

// Sign the payment request
$signed_message = md5(
    $amount . $currency . $webhook_url . $success_url . $cancel_url .
    $customer_email . $buyer_pays_fees . $metadata . $business_id . $private_key
);

// Optional product presentation
$product_markdown = 'This is a test product.';
$product_title = 'Test Product';
$product_image = 'https://via.placeholder.com/150';
$product_description = 'This is a description for the test product.';
$product_link = 'https://example.com/product';

// Sign the product block
$signed_product_hash = md5(
    $product_markdown . $product_title . $product_image .
    $product_description . $product_link . $private_key
);
?>
```

### Full PHP Example

This example posts the required fields and the optional product fields. Inputs that can contain special characters are HTML escaped.

```php
<?php
// Values from the Quick Test Values section above
// ...
?>
<form method="POST" action="https://malum.co/api/v3/checkout/form">
    <input type="hidden" name="amount" value="<?php echo $amount; ?>">
    <input type="hidden" name="currency" value="<?php echo $currency; ?>">
    <input type="hidden" name="webhook_url" value="<?php echo htmlspecialchars($webhook_url, ENT_QUOTES); ?>">
    <input type="hidden" name="success_url" value="<?php echo htmlspecialchars($success_url, ENT_QUOTES); ?>">
    <input type="hidden" name="cancel_url" value="<?php echo htmlspecialchars($cancel_url, ENT_QUOTES); ?>">
    <input type="hidden" name="customer_email" value="<?php echo htmlspecialchars($customer_email, ENT_QUOTES); ?>">
    <input type="hidden" name="buyer_pays_fees" value="<?php echo (int)$buyer_pays_fees; ?>">
    <input type="hidden" name="metadata" value="<?php echo htmlspecialchars($metadata, ENT_QUOTES); ?>">
    <input type="hidden" name="business_id" value="<?php echo htmlspecialchars($business_id, ENT_QUOTES); ?>">
    <input type="hidden" name="signed_message" value="<?php echo $signed_message; ?>">

    <!-- Optional product presentation fields -->
    <input type="hidden" name="product_markdown" value="<?php echo htmlspecialchars($product_markdown, ENT_QUOTES); ?>">
    <input type="hidden" name="product_title" value="<?php echo htmlspecialchars($product_title, ENT_QUOTES); ?>">
    <input type="hidden" name="product_image" value="<?php echo htmlspecialchars($product_image, ENT_QUOTES); ?>">
    <input type="hidden" name="product_description" value="<?php echo htmlspecialchars($product_description, ENT_QUOTES); ?>">
    <input type="hidden" name="product_link" value="<?php echo htmlspecialchars($product_link, ENT_QUOTES); ?>">
    <input type="hidden" name="signed_product_hash" value="<?php echo $signed_product_hash; ?>">

    <button type="submit">Pay Now</button>
</form>
```

### Webhook Handling

Your `webhook_url` will receive a server to server POST from Malum with the payment status and identifiers. On your endpoint you should:

1. Read the payload and Malum signature header if provided.
2. Verify the payload authenticity according to Malum documentation, for example by reconstructing a signature or by fetching the payment status from Malum using your credentials.
3. Validate that the `amount`, `currency`, `metadata`, and any product details match what you expect for the order.
4. Mark the order as paid only after successful verification and idempotently process repeated notifications.

### Redirect URLs

* `success_url` shown after a successful payment
* `cancel_url` shown if the buyer cancels or payment fails

### Security Notes

* Never expose your `private_key` to the client side. Keep it in server side configuration.
* Always rebuild `signed_message` and, if used, `signed_product_hash` on the server.
* Escape any user supplied values placed in hidden inputs using `htmlspecialchars` as shown above.
* Treat webhook as the source of truth for fulfillment. The browser redirect can be spoofed.

### Troubleshooting

* Signature mismatch. Ensure parameter order in your hashes matches the examples exactly and that you include `buyer_pays_fees` in the payment signature.
* Wrong redirects. Confirm the exact values of `success_url` and `cancel_url` that you hashed are the same ones you post.
* Duplicate field issues. Include `signed_product_hash` only once in the form.

### Production Checklist

* Replace all test values with real ones
* Use HTTPS everywhere
* Log request IDs and verify signatures
* Make webhook processing idempotent
* Store and show your order number in `metadata` for easier reconciliation


# Currency Exchange Rate

### Overview

This endpoint retrieves the current exchange rate between two specified currencies. This service supports all major currencies that conform to the ISO 4217 three-letter code standard.

### HTTP Request

```css
GET https://malum.co/api/v2/exchange/{FROM}-{TO}
OR
GET https://malum.co/api/v2/exchange/{FROM}{TO}
```

#### Path Parameters

| Parameter     | Description                                                                                                          |
| ------------- | -------------------------------------------------------------------------------------------------------------------- |
| `{FROM}-{TO}` | The currency pair to convert from and to. Format as `FROM` to `TO` using ISO 4217 codes (e.g., `EUR-USD OR EURUSD`). |

### Success Response

A successful request returns the current exchange rate between the specified currencies:

```json
{
  "status": "success",
  "from": "EUR",
  "to": "USD",
  "rate": "1.0651",
  "pair": "EURUSD"
}
```

#### Response Fields

| Field    | Description                               |
| -------- | ----------------------------------------- |
| `status` | The status of the request (`success`).    |
| `from`   | The currency code of the source currency. |
| `to`     | The currency code of the target currency. |
| `rate`   | The exchange rate from `from` to `to`.    |
| `pair`   | The concatenated currency pair code.      |

### Error Response

If the request fails, typically due to an invalid currency pair, the following JSON is returned:

```json
{
  "status": "failed",
  "error": "Invalid exchange pair."
}
```

#### Error Response Fields

| Field    | Description                                   |
| -------- | --------------------------------------------- |
| `status` | The status of the request (`failed`).         |
| `error`  | A message describing the nature of the error. |

### Additional Notes

* Ensure that both currency codes are valid ISO 4217 codes.
* This endpoint does not require authentication.
* Rates are updated frequently, reflecting current market conditions.

***

<br>


# Webhook / Callback

### Overview

Webhooks are powerful tools used to communicate events between different systems over the web. One common application of webhooks is in payment gateways, where they provide real-time notifications about transaction statuses. This page explains how you can use webhooks to know when a payment is completed in your application.

### Setting Up a Webhook for Payment Notifications

#### Configuring the Webhook URL

Whenever you create a transaction you can specify a custom webhook url for the transaction. This helpful if you manage multiple shops.

#### Handling the Webhook Data

When a payment transaction completes, the payment gateway will send a POST request to your configured webhook URL. This request will include important details about the transaction, such as:

* **status**: Indicates the outcome of the transaction (COMPLETED, FAILED).
* **txn**: A unique identifier for the transaction.
* **amount**: The amount that was requested in the transaction.
* **currency**: The currency used for the transaction.
* **customer\_id**: A unique identifier for the customer involved in the transaction.
* **checkout**: The amount that was requested by you but converted to USD.
* **timestamp**: The exact time when the transaction was processed.
* **signature**: md5(txn|timestamp|webhook\_key)

**Example Code Signature PHP:**

```php
<?php

$receivedWebhook = json_decode(file_get_contents('php://input'));

$webhook_key = 'Your_personal_webhook_key';
$timestamp = $receivedWebhook['timestamp'];
$txn = $receivedWebhook['txn'];

$signature = md5($txn . '|' . $timestamp . '|' . $webhook_key); 

if($signature == $receivedWebhook['signature']){
    // Execute your code on success
}

?>
```

You can find your webhook key here:\
<https://malum.co/merchant/settings/api>

<br>


# 💸Balance API

The Balance API enables you to programmatically retrieve and monitor the wallet balance of your Malum account. Whether you're developing a financial dashboard, automating transactions, or just keeping

#### Endpoint

**POST**\
`https://malum.co/api/v3/account/balance`

#### Headers

To authenticate your request, use the following header structure:

```css
MALUM: {Business ID}:{Secret Key}
```

* **Business ID**: Your Malum account’s unique identifier.
* **Secret Key**: Your API secret key for secure access.

#### Response Format

**Success Response**

When the request is successful, the API will return the following JSON structure:

```json
{
    "status": "success",
    "message": "Balance retrieved.",
    "data": {
        "balance": "10,000.00",
        "pending": "0.00",
        "currency": "USD"
    },
    "timestamp": 1728676259
}
```

* **status**: Message indicating the successful retrieval of the balance.
* **message**: HTTP status code (200 indicates success).
* **data**:
  * **balance**: The available balance in your account.
  * **pending**: Amount pending from any incomplete transactions.
  * **currency**: The currency of the account balance (e.g., USD).
* **timestamp**: Unix timestamp of when the balance was retrieved.

**Error Response**

If the request fails (e.g., invalid API key), the API will return an error in the following format:

```json
{
    "status": "failed",
    "error": "Invalid API Key.",
    "timestamp": 1728676669
}
```

* **status**: Error status message indicating failure.
* **error**: A descriptive error message explaining the issue.
* **timestamp**: Unix timestamp when the error occurred.

#### Example Request

```bash
curl --location --request POST 'https://malum.co/api/v3/account/balance' \
--header 'MALUM: BusinessID:SecretKey'
```

#### Example Success Response

```json
{
    "status": "Balance retrieved.",
    "message": 200,
    "data": {
        "balance": "10,000.00",
        "pending": "0.00",
        "currency": "USD"
    },
    "timestamp": 1728676259
}
```

#### Example Error Response

<pre class="language-json"><code class="lang-json">{
<strong>    "status": "failed",
</strong>    "error": "Invalid API Key.",
    "timestamp": 1728676669
}
</code></pre>

#### Notes

* Ensure that your **Business ID** and **Secret Key** are correct and up-to-date.
* API responses are in JSON format and include a Unix timestamp for logging purposes.


# 🏧 Payout API

The Payout API allows merchants to programmatically request payouts from their Malum account. With this API, you can automate the process of transferring funds to designated crypto wallet.

By integrating the Payout API into your system, you can manage payout requests efficiently, ensuring timely disbursements without the need for manual intervention. This API is designed to enhance your control over fund transfers, whether you need to process individual payments or batch payouts.

**Key Features:**

* **Automated Payout Requests**: Submit payout requests directly from your application.
* **Secure Transactions**: Ensure your financial data and payouts are protected with robust security measures.
* **Flexible Payout Options**: Transfer funds to bank accounts, payment gateways, or other supported methods.

Ideal for merchants looking to optimize and automate their payout processes.

#### Endpoint

**POST**\
`https://malum.co/api/v3/account/payout`

#### Headers

To authenticate your request, use the following header structure:

```css
MALUM: {Business ID}:{Secret Key}
```

* **Business ID**: Your unique Malum account identifier.
* **Secret Key**: Your API secret key for secure access.

#### POST Content (JSON)

```json
{
  "amount": 1.01, // Min Amount 1.01 USD
  "currency": "BTC", // The currency in which you want to receive the payout
  "network": "BTC", // The network of the chosen currency
  "address": "your crypto address" // The cryptocurrency address to which funds will be sent
}
```

**Fields:**

* **amount**: The payout amount in USD. The minimum amount is 1.01 USD.
* **currency**: The cryptocurrency in which you want to receive the payout (e.g., "BTC").
* **network**: The network of the chosen cryptocurrency (e.g., "BTC" for Bitcoin).
* **address**: The cryptocurrency address to which the funds will be sent.

#### Success Response

When the payout request is successful, the API will return the following JSON structure:

```json
{
    "status": "success",
    "message": "Withdrawal of 1.00 USD to LXrXXXXXXXdGEkUWsXXXXXXXX initiated.",
    "data": {
        "order_id": "PO_67XXX8e1XXXXX"
    },
    "timestamp": 1728679453
}
```

* **status**: Indicates the success of the payout request.
* **message**: A descriptive message detailing the transaction and the amount sent.
* **data**:
  * **order\_id**: A unique identifier for the initiated payout order.
* **timestamp**: Unix timestamp indicating when the payout was initiated.

#### Error Response

In case of failure, the API will return an error in the following format:

```json
{
    "status": "failed",
    "error": "Amount is invalid. Amount must be larger than 1.00 USD",
    "timestamp": 1728679483
}
```

* **status**: Error status message indicating the failure.
* **error**: A descriptive error message explaining the issue (e.g., invalid amount).
* **timestamp**: Unix timestamp indicating when the error occurred.

#### Example Request

```bash
curl --location --request POST 'https://malum.co/api/v3/account/payout' \
--header 'MALUM: yourBusinessID:yourSecretKey' \
--header 'Content-Type: application/json' \
--data-raw '{
    "amount": 1.01,
    "currency": "BTC",
    "network": "BTC",
    "address": "yourCryptoAddress"
}'
```

#### Example Success Response

```json
{
    "status": "success",
    "message": "Withdrawal of 1.00 USD to LXrXXXXXXXdGEkUWsXXXXXXXX initiated.",
    "data": {
        "order_id": "PO_67XXX8e1XXXXX"
    },
    "timestamp": 1728679453
}
```

#### Example Error Response

```json
{
    "status": "failed",
    "error": "Amount is invalid. Amount must be larger than 1.00 USD",
    "timestamp": 1728679483
}
```

#### Notes and Fees

* **Irreversible Transactions**: Once a transaction has been initiated, it cannot be undone or reversed. Ensure that you provide the correct details, including the amount, currency, network, and wallet address.
* **Secure Your API Keys**: Withdrawn funds are not under Malum's control once processed. Ensure your API keys are secure to prevent unauthorized payouts.
* **Payouts requested via API are subject to an additional 1% service fee + network fees.**


# 🏦Currencies API

The Currencies API allows you to retrieve a list of all available cryptocurrencies, their networks, the minimum withdrawable amount, and associated network transaction fees. This API is useful for und

#### Endpoint

**POST**\
`https://malum.co/api/v3/account/currencies`

#### Headers

To authenticate your request, use the following header structure:

```css
MALUM: {Business ID}:{Secret Key}
```

* **Business ID**: Your unique Malum account identifier.
* **Secret Key**: Your API secret key for secure access.

#### Success Response

When the request is successful, the API will return a list of available currencies and their details in the following format:

```json
{
    "status": "success",
    "message": "Currencies retrieved.",
    "data": [{
        "short": "BTC",
        "network": "BTC",
        "min_withdraw": "0.000286",
        "tx_fee": "0.00022"
    }, {
        "short": "ETH",
        "network": "ETH",
        "min_withdraw": "0.001",
        "tx_fee": "0.00066"
    }, {
        "short": "LTC",
        "network": "LTC",
        "min_withdraw": "0.01",
        "tx_fee": "0.001"
    }, {
        "short": "USDC",
        "network": "ETH",
        "min_withdraw": "10",
        "tx_fee": "5.577"
    }, {
        "short": "USDC",
        "network": "POLYGON",
        "min_withdraw": "0.5",
        "tx_fee": "0.011"
    }, {
        "short": "USDC",
        "network": "BSC",
        "min_withdraw": "1",
        "tx_fee": "0.33"
    }, {
        "short": "USDT",
        "network": "ETH",
        "min_withdraw": "10",
        "tx_fee": "5.577"
    }, {
        "short": "USDT",
        "network": "TRON",
        "min_withdraw": "2.431",
        "tx_fee": "1.87"
    }, {
        "short": "USDT",
        "network": "BSC",
        "min_withdraw": "1",
        "tx_fee": "0.33"
    }, {
        "short": "USDT",
        "network": "POLYGON",
        "min_withdraw": "0.5",
        "tx_fee": "0.011"
    }],
    "timestamp": 1728679774
}
```

**Fields:**

* **short**: The cryptocurrency symbol (e.g., "BTC" for Bitcoin, "ETH" for Ethereum).
* **network**: The network on which the cryptocurrency operates (e.g., "BTC" for Bitcoin, "ETH" for Ethereum).
* **min\_withdraw**: The minimum amount of the cryptocurrency that can be withdrawn.
* **tx\_fee**: The network transaction fee for withdrawing that cryptocurrency.

#### Error Response

In case of failure, the API will return an error in the following format:

```json
{
    "status": "failed",
    "error": "Something went wrong for some reason even tho there cant be something wrong on this endpoint",
    "timestamp": 1728679812
}
```

#### Example Request

```bash
curl --location --request POST 'https://malum.co/api/v3/account/currencies' \
--header 'MALUM: yourBusinessID:yourSecretKey' \
--header 'Content-Type: application/json'
```

#### Example Success Response

```json
{
    "status": "success",
    "message": "Currencies retrieved.",
    "data": [{
        "short": "BTC",
        "network": "BTC",
        "min_withdraw": "0.000286",
        "tx_fee": "0.00022"
    }, {
        "short": "ETH",
        "network": "ETH",
        "min_withdraw": "0.001",
        "tx_fee": "0.00066"
    }, {
        "short": "LTC",
        "network": "LTC",
        "min_withdraw": "0.01",
        "tx_fee": "0.001"
    }, {
        "short": "USDC",
        "network": "ETH",
        "min_withdraw": "10",
        "tx_fee": "5.577"
    }, {
        "short": "USDC",
        "network": "POLYGON",
        "min_withdraw": "0.5",
        "tx_fee": "0.011"
    }, {
        "short": "USDC",
        "network": "BSC",
        "min_withdraw": "1",
        "tx_fee": "0.33"
    }, {
        "short": "USDT",
        "network": "ETH",
        "min_withdraw": "10",
        "tx_fee": "5.577"
    }, {
        "short": "USDT",
        "network": "TRON",
        "min_withdraw": "2.431",
        "tx_fee": "1.87"
    }, {
        "short": "USDT",
        "network": "BSC",
        "min_withdraw": "1",
        "tx_fee": "0.33"
    }, {
        "short": "USDT",
        "network": "POLYGON",
        "min_withdraw": "0.5",
        "tx_fee": "0.011"
    }],
    "timestamp": 1728679774
}
```

#### Example Error Response

```json
{
    "status": "failed",
    "error": "Something went wrong for some reason even tho there cant be something wrong on this endpoint",
    "timestamp": 1728679812
}
```

#### Notes

* This API provides up-to-date information about available cryptocurrencies and their transaction requirements.
* The network fees and minimum withdrawable amounts may vary over time, so ensure you retrieve fresh data when performing transactions.


# Create Transaction

The Reseller API, does not need an account. This API is whitelabel; You will reach out to Malum servers on the backend. Malum will return vanished links and information.

Malum charges a comission of 4% transaction through this API Endpoint this includes a 1,5% comission for infrastructure and 2,5% profit margin. We are open for negotiations.&#x20;

Create a new reseller checkout order and receive a `transaction_code` you can use to track the payment flow.

**Method:** `GET`\
**Endpoint:** `https://malum.co/api/v3/reseller/checkout`\
**Response format:** JSON

***

### Required query parameters

| Parameter                 | Type   | Example     | Notes                                        |
| ------------------------- | ------ | ----------- | -------------------------------------------- |
| `fiat_amount`             | number | `49.99`     | Must be numeric, `> 0` and `<= 10000`        |
| `fiat_currency`           | string | `EUR`       | (`A-Z`)                                      |
| `crypto_currency`         | string | `USDT`      | (`A-Z`)                                      |
| `crypto_currency_network` | string | `TRC20`     | (`A-Z0-9`)                                   |
| `wallet_address`          | string | `TA1b...`   | Destination wallet address (customer wallet) |
| `external_reference`      | string | `INV-10001` | Your reference (order id, invoice id, etc.)  |

***

### Optional query parameters

| Parameter     | Type | Example                               | Default                               |
| ------------- | ---- | ------------------------------------- | ------------------------------------- |
| `webhook_url` | url  | `https://merchant.tld/webhooks/malum` | `https://merchant.tld/webhooks/malum` |

***

### Partner split parameters (optional group)

If you set **any** `partner_*` parameter, then **all** partner parameters must be provided (except `partner_wallet_address` is effectively the toggle, but the API checks that the whole group is present).

| Parameter                         | Type   | Example                              | Notes                                                                                                                                  |
| --------------------------------- | ------ | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `partner_wallet_address`          | string | `0xabc...`                           | Partner wallet address                                                                                                                 |
| `partner_external_reference`      | string | `PARTNER-REF-1`                      | Your partner reference                                                                                                                 |
| `partner_crypto_currency`         | string | `USDT`                               | Same validation as `crypto_currency`                                                                                                   |
| `partner_crypto_currency_network` | string | `ERC20`                              | Same validation as `crypto_currency_network`                                                                                           |
| `partner_comission_percentage`    | number | `10`                                 | Commission percentage, must be provided if using partner split                                                                         |
| `partner_webhook_url`             | url    | `https://partner.tld/webhooks/malum` | Default if omitted is `https://merchant.tld/webhooks/malum`, but note the API also requires it to be present when partner mode is used |

***

### Validation rules

The endpoint applies these checks before creating the order:

* **Only GET parameters are processed.**
* Missing or empty required parameters return an error.
* `fiat_amount` must be numeric, greater than 0, and not greater than 10000.
* `fiat_currency` must be 2 to 4 uppercase letters.
* `crypto_currency` must be 2 to 6 uppercase letters.
* `crypto_currency_network` must be 2 to 10 uppercase letters or numbers.
* `webhook_url` (and `partner_webhook_url`) must be valid URLs.
* Crypto currency and network must be supported by the reseller system.
* Wallet addresses are stored if unknown, reused if already known.
* If `fiat_currency` is not `USD`, an exchange rate is fetched and the amount is converted to USD for internal processing.

***

### Example request (basic)

```http
GET https://malum.co/api/v3/reseller/checkout?fiat_amount=49.99&fiat_currency=EUR&crypto_currency=USDT&crypto_currency_network=TRC20&wallet_address=TA1bExampleWallet&external_reference=INV-10001&webhook_url=https%3A%2F%2Fmerchant.tld%2Fwebhooks%2Fmalum
```

***

### Example request (with partner split)

```http
GET https://malum.co/api/v3/reseller/checkout?fiat_amount=49.99&fiat_currency=EUR&crypto_currency=USDT&crypto_currency_network=TRC20&wallet_address=TA1bExampleWallet&external_reference=INV-10001&webhook_url=https%3A%2F%2Fmerchant.tld%2Fwebhooks%2Fmalum&partner_wallet_address=0xPartnerWallet&partner_external_reference=PARTNER-REF-1&partner_crypto_currency=USDT&partner_crypto_currency_network=ERC20&partner_comission_percentage=10&partner_webhook_url=https%3A%2F%2Fpartner.tld%2Fwebhooks%2Fmalum
```

***

### Success response

On success, the API returns a JSON object like:

```json
{
  "status": "success",
  "message": "Order created successfully.",
  "data": {
    "transaction_code": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "fiat_amount": "49.99",
    "fiat_currency": "EUR",
    "crypto_currency": "USDT",
    "crypto_currency_network": "TRC20",
    "wallet_address": "TA1bExampleWallet",
    "status": "pending"
  }
}
```

**Field notes**

* `transaction_code` is generated server-side (UUID4).
* `status` in `data` is returned as `pending` right after creation.

***

### Error responses

Errors return JSON with:

* `status`: `failed`
* `message`: a human-readable error message
* `data`: usually an empty object/array

Common messages include:

* `Invalid Request. Missing parameters.`
* `Invalid Request. Missing partner parameters.`
* `Invalid fiat amount.`
* `Invalid fiat currency.`
* `Invalid crypto currency.`
* `Invalid crypto currency network.`
* `Invalid webhook URL.`
* `Invalid partner webhook URL.`
* `The requested cryptocurrency or network is not supported.`
* `Could not retrieve exchange rate for the requested fiat currency.`
* `Could not create order. Please try again later.`

***

### Notes for implementers

* URL-encode your webhook URLs.
* Keep your `external_reference` unique per order to simplify reconciliation on your side.
* If you enable partner split, treat the partner parameters as an all-or-nothing block.


# Get Payment Options

Payment options will differ from the ones offered directly on Malum, direct local options are not available due to timed processing.

Retrieve available payment options for a given fiat amount and currency. The API converts the amount to USD internally and returns payment options based on the USD value.

**Method:** `GET`\
**Endpoint:** `https://malum.co/api/v3/reseller/payment_options`\
**Response format:** JSON

***

### Required query parameters

| Parameter       | Type   | Example | Notes                                            |
| --------------- | ------ | ------- | ------------------------------------------------ |
| `fiat_amount`   | number | `49.99` | Must be `> 0` and `<= 10000`                     |
| `fiat_currency` | string | `EUR`   | Must be exactly 3 letters, uppercased internally |

***

### Validation rules

* **Only GET parameters are processed.**
* `fiat_currency` must be **exactly 3 letters** (for example `EUR`, `USD`).
* `fiat_amount` must be greater than 0 and not greater than 10000.
* Fiat currency must be supported by the reseller system.
* If `fiat_currency` is not `USD`, an exchange rate is fetched and the amount is converted to USD.
* Payment options are calculated using the USD base amount.

***

### Example request

```http
GET https://malum.co/api/v3/reseller/payment_options?fiat_amount=49.99&fiat_currency=EUR
```

***

### Success response

```json
{
   "status":"success",
   "message":"Payment options retrieved successfully.",
   "data":{
      "fiat_amount":20,
      "fiat_currency":"EUR",
      "base_in_usd":"23.69",
      "payment_options":[
         {
            "name":"EasyPay",
            "show_name":"EasyPay",
            "alt":"Credit Card, Debit Card (NO KYC)",
            "processor_fee_fixed":"0.9",
            "processor_fee_percent":"9",
            "processor_min_fee":"0.99"
         },
         {
            "name":"EasyPayEUR",
            "show_name":"EasyPay (EUR)",
            "alt":"Credit Card, Debit Card (No KYC)",
            "processor_fee_fixed":"0.9",
            "processor_fee_percent":"9",
            "processor_min_fee":"0.99"
         },
         ....
      ]
   },
   "timestamp":1770079387
}
```

**Field notes**

* `base_in_usd` is the computed USD amount used for option selection.
* `payment_options` is returned as an array (the backend converts internal objects into arrays before responding).

***

### Error responses

Errors return JSON with:

* `status`: `failed`
* `message`: a human-readable error message
* `data`: usually an empty object/array

Common messages include:

* `Invalid fiat currency.`
* `Invalid fiat amount.`
* `The requested fiat currency is not supported.`
* `Could not retrieve exchange rate for the requested fiat currency.`
* `An error occurred, please try again later.`


# Get Payment Link

Generate a payment gateway link for an existing reseller transaction. This endpoint returns a redirect URL that sends the customer to the selected payment provider.

**Method:** `GET`\
**Endpoint:** `https://malum.co/api/v3/reseller/payment_link`\
**Response format:** JSON

***

### Required query parameters

<table><thead><tr><th>Parameter</th><th>Type</th><th width="201">Example</th><th>Notes</th></tr></thead><tbody><tr><td><code>transaction_code</code></td><td>string (UUID v4)</td><td><code>193a3981-XXXX-XXXX-XXXX-241a26f3b74e</code></td><td>Must be a valid UUID v4 of a previously created order</td></tr><tr><td><code>payment_method</code></td><td>string</td><td><code>WERTEUR,WERT,...</code>   </td><td>Payment gateway identifier, case-insensitive, spaces removed</td></tr></tbody></table>

***

### How it works

1. The API validates the `transaction_code` format (must be UUID v4).
2. The system normalizes `payment_method`:
   * Spaces removed
   * Converted to lowercase
3. The backend checks if a matching gateway integration file exists.
4. The transaction is loaded using `transaction_code`.
5. The transaction must exist and still be in `pending` status.
6. The selected gateway module generates a redirect URL.
7. The API responds with a URL where the customer should be redirected.

***

### Example request

```http
GET https://malum.co/api/v3/reseller/payment_link?transaction_code=193a3981-XXXX-XXXX-XXXX-241a26f3b74e&payment_method=WERTEUR
```

***

### Success response

```json
{
  "status": "success",
  "message": "Gateway http redirect",
  "data": {
    "redirect_url": "https://demo.tld/"
  },
  "timestamp": 1770161149
}
```

**Field notes**

* `redirect_url` is where you should send the customer to complete the payment.
* The URL may point to an intermediary redirect or directly to a third-party gateway page.
* `timestamp` is a server-side Unix timestamp of the response.
* Malum is hidden and not shown.

***

### Error responses

Errors return JSON with:

* `status`: `failed`
* `message`: description of the problem
* `data`: may be empty or include debug information

Common messages include:

* `Invalid Request. Missing transaction code.`
* `Invalid transaction code format.`
* `An error with the payment method occurred, please try again later.`
* `Transaction not found.`
* `Transaction is not pending anymore.`
* `An error occurred, please try again later.`

***

### Integration flow summary

1. Create an order using the **checkout** endpoint and store the `transaction_code`.
2. Retrieve available methods via **payment\_options**.
3. Call **payment\_link** with the chosen `payment_method`.
4. Redirect your customer to the returned `redirect_url`.


