> For the complete documentation index, see [llms.txt](https://moonie.gitbook.io/mooniepay/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://moonie.gitbook.io/mooniepay/payments/initiate-payment.md).

# Initiate payment

***

### Endpoint

```
POST https://api.pay.movemoonie.com/v1/payments/initiate
```

***

### Request

#### Headers

| Header               | Required | Description                       |
| -------------------- | -------- | --------------------------------- |
| `Authorization`      | ✅        | Your **Payment** public key       |
| `X-TTUM-Timestamp`   | ✅        | Current Unix timestamp in seconds |
| `X-TTUM-Signature`   | ✅        | HMAC-SHA256 signature             |
| `X-TTUM-Environment` | ✅        | `sandbox` or `live`               |
| `Content-Type`       | ✅        | `application/json`                |

> 💡 Use your **Payment** key pair — not your Payout key. See [Authentication](https://claude.ai/introduction/authentication.md) for signature details.

#### Body Parameters

| Parameter             | Type      | Required | Description                                                                             |
| --------------------- | --------- | -------- | --------------------------------------------------------------------------------------- |
| `payment_method`      | `string`  | ✅        | Payment method code. See [Available Methods](/mooniepay/payments/available-methods.md). |
| `amount`              | `numeric` | ✅        | Amount in the smallest currency unit (e.g. `5000` = 5,000 XAF).                         |
| `phone_number`        | `string`  | ✅        | Customer's phone number in international format (e.g. `+237620000001`).                 |
| `customer`            | `object`  | ✅        | Customer information object (see below).                                                |
| `customer.first_name` | `string`  | ✅        | Customer's first name. Max 100 characters.                                              |
| `customer.last_name`  | `string`  | ✅        | Customer's last name. Max 100 characters.                                               |
| `customer.email`      | `string`  | ✅        | Customer's email address.                                                               |
| `customer.metadata`   | `object`  | ❌        | Any additional customer data you want to store.                                         |
| `external_id`         | `string`  | ❌        | Your own reference ID for this transaction — useful for reconciliation.                 |
| `description`         | `string`  | ❌        | A short description of the payment (e.g. `Order #1234`).                                |
| `metadata`            | `object`  | ❌        | Any additional key-value data to attach to the transaction and echo back in webhooks.   |

#### Example Request Body

```json
{
  "payment_method": "momo_cm",
  "amount": 5000,
  "phone_number": "+237620000001",
  "customer": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "metadata": {
      "user_id": "42"
    }
  },
  "external_id": "ORD-9876",
  "description": "Order #1234 payment",
  "metadata": {
    "order_id": "ORD-9876",
    "plan": "pro"
  }
}
```

***

### Code Examples

{% tabs %}
{% tab title="PHP" %}

```php
<?php

$publicKey   = 'pk_sandbox_payment_xxxxxxxxxxxx';
$secretKey   = 'your_secret_key_here';
$environment = 'sandbox';
$timestamp   = time();

$method  = 'POST';
$path    = '/v1/payments/initiate';
$payload = json_encode([
    'payment_method' => 'mooniepay_demo',
    'amount'         => 5000,
    'phone_number'   => '+237620000001',
    'customer'       => [
        'first_name' => 'Jane',
        'last_name'  => 'Doe',
        'email'      => 'jane@example.com',
    ],
    'external_id'    => 'ORD-9876',
    'description'    => 'Order #1234 payment',
    'metadata'       => ['order_id' => 'ORD-9876'],
]);

$stringToSign = "{$publicKey}.{$timestamp}.{$method}.{$path}.{$payload}";
$signature    = hash_hmac('sha256', $stringToSign, $secretKey);

$ch = curl_init('https://api.pay.movemoonie.com/v1/payments/initiate');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $payload,
    CURLOPT_HTTPHEADER     => [
        "Authorization: {$publicKey}",
        "X-TTUM-Timestamp: {$timestamp}",
        "X-TTUM-Signature: {$signature}",
        "X-TTUM-Environment: {$environment}",
        "Content-Type: application/json",
    ],
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);
```

{% endtab %}

{% tab title="Node.Js" %}

```javascript
const crypto = require('crypto');
const https  = require('https');

const publicKey   = 'pk_sandbox_payment_xxxxxxxxxxxx';
const secretKey   = 'your_secret_key_here';
const environment = 'sandbox';
const timestamp   = Math.floor(Date.now() / 1000);

const method  = 'POST';
const path    = '/v1/payments/initiate';
const payload = JSON.stringify({
  payment_method: 'mooniepay_demo',
  amount: 5000,
  phone_number: '+237620000001',
  customer: { first_name: 'Jane', last_name: 'Doe', email: 'jane@example.com' },
  external_id: 'ORD-9876',
  description: 'Order #1234 payment',
  metadata: { order_id: 'ORD-9876' },
});

const stringToSign = `${publicKey}.${timestamp}.${method}.${path}.${payload}`;
const signature    = crypto.createHmac('sha256', secretKey).update(stringToSign).digest('hex');

const req = https.request({
  hostname: 'api.pay.movemoonie.com',
  path, method,
  headers: {
    'Authorization': publicKey, 'X-TTUM-Timestamp': timestamp.toString(),
    'X-TTUM-Signature': signature, 'X-TTUM-Environment': environment,
    'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload),
  },
}, (res) => {
  let data = '';
  res.on('data', chunk => data += chunk);
  res.on('end', () => console.log(JSON.parse(data)));
});

req.write(payload);
req.end();
```

{% endtab %}

{% tab title="Python" %}

```python
import hmac, hashlib, time, json, requests

public_key   = 'pk_sandbox_payment_xxxxxxxxxxxx'
secret_key   = 'your_secret_key_here'
environment  = 'sandbox'
timestamp    = int(time.time())

method  = 'POST'
path    = '/v1/payments/initiate'
payload = json.dumps({
    'payment_method': 'mooniepay_demo',
    'amount': 5000,
    'phone_number': '+237620000001',
    'customer': {'first_name': 'Jane', 'last_name': 'Doe', 'email': 'jane@example.com'},
    'external_id': 'ORD-9876',
    'description': 'Order #1234 payment',
    'metadata': {'order_id': 'ORD-9876'},
}, separators=(',', ':'))

string_to_sign = f"{public_key}.{timestamp}.{method}.{path}.{payload}"
signature = hmac.new(secret_key.encode(), string_to_sign.encode(), hashlib.sha256).hexdigest()

response = requests.post(
    'https://api.pay.movemoonie.com/v1/payments/initiate',
    data=payload,
    headers={
        'Authorization': public_key, 'X-TTUM-Timestamp': str(timestamp),
        'X-TTUM-Signature': signature, 'X-TTUM-Environment': environment,
        'Content-Type': 'application/json',
    }
)
print(response.json())
```

{% endtab %}

{% tab title="cURL" %}

```shellscript
PUBLIC_KEY="pk_sandbox_payment_xxxxxxxxxxxx"
SECRET_KEY="your_secret_key_here"
ENVIRONMENT="sandbox"
TIMESTAMP=$(date +%s)
METHOD="POST"
PATH="/v1/payments/initiate"
PAYLOAD='{"payment_method":"mooniepay_demo","amount":5000,"phone_number":"+237620000001","customer":{"first_name":"Jane","last_name":"Doe","email":"jane@example.com"},"external_id":"ORD-9876","description":"Order #1234 payment"}'

STRING_TO_SIGN="${PUBLIC_KEY}.${TIMESTAMP}.${METHOD}.${PATH}.${PAYLOAD}"
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -hmac "$SECRET_KEY" | awk '{print $2}')

curl https://api.pay.movemoonie.com/v1/payments/initiate \
  -X POST \
  -H "Authorization: $PUBLIC_KEY" \
  -H "X-TTUM-Timestamp: $TIMESTAMP" \
  -H "X-TTUM-Signature: $SIGNATURE" \
  -H "X-TTUM-Environment: $ENVIRONMENT" \
  -H "Content-Type: application/json" \
  -d "$PAYLOAD"
```

{% endtab %}
{% endtabs %}

***

### Response

#### Success — `200 OK`

```json
{
  "success": true,
  "message": "Payment initiated. Customer will receive a prompt to approve.",
  "data": {
    "transaction_id": "TE_XXXXXXXXXXXXXXX",
    "ref": "f83a0235-892b-44c0-bad5-a4e8f32ceb3d",
    "external_id": "your_mechant_transaction_id",
    "type": "payment",
    "status": "initiated" or "processing",
    "amount": 5000,
    "currency": "XAF",
    "description": "Order #1234 payment",
    "account_name": "Jane Doe",
    "account_number": "6XXXXXXX",
    "account_type": "mobile_money",
    "reason": null,
    "failed_code": null,
    "failed_at": null,
    "cancelled_at": null,
    "completed_at": "2024-06-10T12:00:05.000000Z",
    "customer": {
      "ref": "cus_ref_xxxxxxxx",
      "first_name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "metadata": {
        "user_id": "42"
      }
    },
    "payment_method": {
      "ref": "f83a0235-892b-44c0-bad5-a4e8f32ceb3d",
      "name": "Mooniepay testing payment",
      "code": "mooniepay_demo"
    },
    "metadata": {
      "order_id": "ORD-9876",
      "user_id": "42"
    },
    "created_at": "2024-06-10T12:00:00.000000Z",
    "updated_at": "2024-06-10T12:00:05.000000Z"
  }
}
```

> ⚠️ The initial status is typically `processing` or `initiated`— the customer has received a prompt on their phone but has not yet approved or declined. Subscribe to [webhooks](/mooniepay/introduction/webhooks.md) or use the [Verify endpoint](/mooniepay/payments/verify-payment.md) to track the final outcome.

#### Error Responses

Check the different [errors](/mooniepay/introduction/errors.md#payment-errors).

#### Failed code&#x20;

| Code                                 | Reason                                       |
| ------------------------------------ | -------------------------------------------- |
| `PAYER_NOT_FOUND`                    | Payer account not found.                     |
| `NOT_ENOUGH_FUNDS`                   | Funds not enough.                            |
| `EXPIRED`                            | Transaction timeout.                         |
| `TRANASACTION_CANCELLED`             | Transaction has been cancelled by the payer. |
| `SERVICE_UNAVAILABLE`                | Service not available.                       |
| `PROVIDER_INTERNAL_PROCESSING_ERROR` | Internal error from the provider.            |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://moonie.gitbook.io/mooniepay/payments/initiate-payment.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
