Skip to main content

Quick Starts

This guide is designed for developers to help you integrate Papi into your website or application. Follow these steps to set up a payment system that works seamlessly for your customers.

Prerequisites

  1. Your application is online and ready to accept payments.
  2. You have your API Key from the Papi dashboard (see Where to Find Your API Key below).
  3. Choose a URL that you want Papi to redirect to after a payment success (successUrl).
  4. Choose a URL that you want Papi to redirect to after a payment failure (failureUrl).
  5. Choose a URL for your server that will receive payment notifications from Papi (notificationUrl).

Where to Find Your API Key

  1. Log in to your dashboard: https://dashboard.papi.mg.
  2. In the top right corner, click your avatar icon (your profile picture or initials).
  3. Click Boutiques in the dropdown menu.
  4. Click on the application you want to use.
  5. Inside the application's dashboard, click the Developer tab.
  6. Under API Key, you will see your key (a long string).

Important: Keep your API Key secret. Anyone with this key can create payments on your behalf.

Workflow Overview

Before diving into the steps, here's how everything will fit together:

  1. A customer places an order on your website.
  2. You create a secure payment link using Papi.
  3. The customer is redirected to the payment page to complete their payment.
  4. Papi sends the payment result to your system using your notification URL (POST request).
  5. Your system verifies the notification and updates the order status (success or failure).
  6. The customer is shown the result on your website (success or failure).

To let customers pay, you need to create a secure link that will direct them to a payment page. This link includes the payment amount, customer details, and the URL where Papi will notify your system about the payment result.

What You Need to Do

Send a POST request to the following endpoint:

POST https://app.papi.mg/dashboard/api/payment-links

Authentication

Every request must include your API Key in the headers:

Content-Type: application/json
Token: <YOUR_API_KEY>

Request body

Send a JSON body with the required and optional fields. Example:

{
"amount": 15000.0,
"clientName": "Client Name",
"reference": "ORDER-123",
"description": "Payment for Order #123",
"successUrl": "https://yourapp.com/payment-success",
"failureUrl": "https://yourapp.com/payment-failure",
"notificationUrl": "https://yourapp.com/payment-notify",
"validDuration": 60,
"provider": "MVOLA",
"payerEmail": "customer@example.com",
"payerPhone": "+261340000000",
"testReason": "Internal QA",
"isTestMode": false
}
Field nameTypeRequiredDescription
clientNamestringCustomer's name.
amountnumberPayment amount (>= 300).
referencestringYour unique reference for this payment.
descriptionstringPayment description (max 255 characters).
successUrlstring×URL to redirect after success (http(s)://).
failureUrlstring×URL to redirect after failure (http(s)://).
notificationUrlstringURL to receive payment notifications (http(s)://).
validDurationinteger×Validity in minutes (>0). Default: 1.
providerstring×One of: MVOLA, ARTEL_MONEY, ORANGE_MONEY, BRED.
payerEmailstring×Customer's email address.
payerPhonestring×Customer's phone number (e.g., +261340000000).
testReasonstring×Reason for test mode (if isTestMode=true).
isTestModeboolean×Set to true to enable test mode.

Success response

If your request is valid, you receive:

{
"data": {
"amount": 15000.0,
"currency": "MGA",
"linkCreationDateTime": 1723850012,
"linkExpirationDateTime": 1723853612,
"paymentLink": "https://pay.papi.mg/payment/abc123",
"clientName": "Client Name",
"paymentReference": "ORDER-123",
"description": "Payment for Order #123",
"successUrl": "https://yourapp.com/payment-success",
"failureUrl": "https://yourapp.com/payment-failure",
"notificationUrl": "https://yourapp.com/payment-notify",
"payerEmail": "customer@example.com",
"payerPhone": "+261340000000",
"notificationToken": "xyz789",
"testReason": "Internal QA",
"isTestMode": false
}
}
  • paymentLink — Redirect your customer to this URL to complete the payment.
  • notificationToken — Store this and use it later to verify that notifications are genuine.

Error response

If something goes wrong, you may receive:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Le montant est requis"
}
}

Examples

<?php
$apiUrl = "https://app.papi.mg/dashboard/api/payment-links";
$apiKey = "<YOUR_API_KEY>";

$data = [
"amount" => 15000.0,
"clientName" => "Client Name",
"reference" => "ORDER-123",
"description" => "Payment for Order #123",
"successUrl" => "https://yourapp.com/payment-success",
"failureUrl" => "https://yourapp.com/payment-failure",
"notificationUrl" => "https://yourapp.com/payment-notify",
"validDuration" => 60,
"provider" => "MVOLA",
"payerEmail" => "customer@example.com",
"payerPhone" => "+261340000000",
];

$options = [
"http" => [
"header" => "Content-Type: application/json\r\nToken: $apiKey\r\n",
"method" => "POST",
"content" => json_encode($data),
],
];

$context = stream_context_create($options);
$response = file_get_contents($apiUrl, false, $context);

if ($response !== false) {
$result = json_decode($response, true);
if (isset($result["data"]["paymentLink"])) {
$paymentLink = $result["data"]["paymentLink"];
$notificationToken = $result["data"]["notificationToken"] ?? null;
// Store $notificationToken to verify notifications later
echo "Payment Link: $paymentLink\n";
} else {
echo "Error: " . json_encode($result["error"] ?? $result) . "\n";
}
} else {
echo "Failed to generate payment link.\n";
}
?>

Step 2: Redirect the customer to the payment page

Once the payment link is generated, your customer must complete the payment using that link.

What You Need to Do

  1. Extract paymentLink from the response of Step 1.
  2. Redirect the customer to that URL (e.g. open in the same tab, new tab, or WebView in mobile apps).

Mobile apps: Use a WebView or the device's default browser. Note that some platforms reset WebViews when the app goes to the background; handle this to avoid losing state.

Examples

<?php
// After obtaining $paymentLink from Step 1:
header("Location: " . $paymentLink);
exit();
?>

Step 3: Set up a notification endpoint

After the customer completes the payment on Papi's payment page, Papi sends a POST request to your notificationUrl to inform your system of the payment result.

What you need to do

  1. Create an endpoint that accepts POST requests and reads the JSON body (the URL you gave as notificationUrl in Step 1).
  2. In this script, verify the notification, then update your system (e.g. mark the order as paid or failed).

Notification payload (example)

Papi sends a JSON body like:

{
"paymentStatus": "SUCCESS",
"paymentMethod": "MVOLA",
"currency": "MGA",
"amount": 15000,
"fee": 500,
"clientName": "Client Name",
"description": "Payment for Order #123",
"merchantPaymentReference": "MERCHANT-0001",
"paymentReference": "ORDER-123",
"notificationToken": "xyz789",
"message": "Payment completed successfully.",
"payerEmail": "customer@example.com",
"payerPhone": "+261340000000"
}
Field nameTypeDescription
paymentStatusstringSUCCESS, PENDING, or FAILED.
paymentMethodstringThe method used (e.g. MVOLA).
currencystringCurrency code.
amountintegerPaid amount.
feeintegerTransaction fee.
clientNamestringCustomer's name.
descriptionstringYour description.
merchantPaymentReferencestringPayment system reference.
paymentReferencestringYour reference (same as in Step 1).
notificationTokenstringUse to verify authenticity.
messagestringAdditional details.
payerEmailstringCustomer email.
payerPhonestringCustomer phone.

How to verify the notification

  1. Check that paymentReference matches the reference you sent when creating the payment link.
  2. Check that notificationToken matches the token you received in the Step 1 response.

If both match, treat the notification as genuine and update your records.

Example PHP notification endpoint

<?php
// payment-notify.php (or the path matching your notificationUrl)

$data = json_decode(file_get_contents("php://input"), true);
if (!$data) {
http_response_code(400);
exit();
}

$paymentReference = $data["paymentReference"] ?? "";
$notificationToken = $data["notificationToken"] ?? "";
$paymentStatus = $data["paymentStatus"] ?? "";
$amount = $data["amount"] ?? 0;

// Verify: compare with the reference and notificationToken you stored when creating the link
$expectedToken = "xyz789"; // Retrieve the token you stored in Step 1 for this payment
$expectedReference = "ORDER-123"; // Or from your database for this order

if ($paymentReference !== $expectedReference || $notificationToken !== $expectedToken) {
http_response_code(403);
exit();
}

if ($paymentStatus === "SUCCESS") {
file_put_contents("log.txt", "Payment $paymentReference: SUCCESS (amount: $amount)\n", FILE_APPEND);
// Update your database to mark the order as paid
} elseif ($paymentStatus === "FAILED") {
file_put_contents("log.txt", "Payment $paymentReference: FAILED\n", FILE_APPEND);
// Handle failure (e.g. notify the customer)
} else {
// PENDING or other
file_put_contents("log.txt", "Payment $paymentReference: $paymentStatus\n", FILE_APPEND);
}

http_response_code(200); // Tell Papi the notification was received
?>

Step 4: Create pages for payment results

When the payment process is complete, Papi shows the user a success or failure message, then redirects them to the URLs you provided in Step 1 (successUrl and failureUrl).

What you need to do

Option 1: Use a single URL for both success and failure (e.g. return the user to the home page or order details).

Option 2: Use two separate pages:

  • A page for successful payments, served at the URL you set as successUrl (e.g. next steps, delivery info).
  • A page for failed payments, served at the URL you set as failureUrl (e.g. "Payment failed", "Try again" or contact support).

Test mode

To test your integration:

  1. isTestMode=true — Marks the transaction as a test (note: may still move real money depending on configuration).
  2. Application Test Mode (cards only) — In your dashboard, enable Test Mode in the Application settings. You can use this test card:
    • Card Number: 4000 0000 0000 5126
    • Expiry: 01/2028
    • CVV: 123

Note: Mobile money does not support non-real test transactions.