Developer Documentation

Learn how to accept payments, manage transactions, and handle callbacks with YaYa Wallet's payment integration

← Back to Home

Introduction

Welcome to the YaYa Wallet Payment Integration documentation. This guide will help you integrate our payment processing system into your application. Our API is RESTful and uses JSON for request and response bodies.

Important Notice:
  • For any technical support or assistance, please call 957 or email

Developer Resources

Get started quickly with our Postman collection:

Download Postman Collection

System Architecture

Merchant YaYa Wallet Payer Bank System 1. Create Payment 2. Share Payment Link 3. Make Payment 4. Process Payment 5. Payment Notification YaYa Wallet Payment Flow

The YaYa Wallet Payment Integration consists of several key components and follows this payment flow:

  1. Create Payment: Merchant creates a payment request through the YaYa Wallet
  2. Share Payment Link: System generates a unique payment link and QR code for the payer
  3. Make Payment: Payer completes the payment using their preferred method (QR code, USSD, card, etc.)
  4. Process Payment: Bank system processes the payment and notifies the YaYa Wallet
  5. Payment Notification: Merchant receives real-time notification of successful payment

Key features of the system:

API Endpoints

OAuth2 Authentication

POST /api/auth/token

Obtain an access token for API authentication.

Request:
{
    "client_id": "your_client_id",
    "client_secret": "your_client_secret",
    "grant_type": "client_credentials"
}

Response:
{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "user"
}

Include the access token in the Authorization header for all authenticated requests:

Authorization: Bearer your_access_token

Merchant Endpoints

Create Payment Request

POST /api/payment-intent

Creates a new payment intent. Requires OAuth2 authentication.

Request:
{
    "bankBic": "YAYAETAA",
    "bankAccount": "antenehgebey",
    "amount": 1000,
    "paymentReference": "INV-005",
    "description": "June bill",
    "feeOnMerchant": true,
    "returnUrl": "https://yourwebsite.com/thank-you",
    "callbackUrl": "https://6833e09e464b499636008b3e.mockapi.io/callback",
    "meta_data": {
        "customer_id": "1234",
        "customer_name": "Abebe Kebede",
        "customer_phone": "0911059599"
    }
}

Response:
{
    "success": true,
    "data": {
        "id": "0ec6005f-820c-4ab4-84aa-2311fb8262f7",
        "urlSlug": "92AE1D227EE1",
        "paymentCode": "92AE1D227EE1",
        "paymentReference": "INV-0895",
        "amount": 1000,
        "currency": "ETB",
        "processingFee": 20,
        "total": 1020,
        "bankBic": "YAYAETAA",
        "bankAccount": "antenehgebey",
        "feeOnMerchant": true,
        "status": "pending",
        "qrCode": "00020101021228630032ee5b47b18b3544a0960673b04df2c0b70108YAYAETAA0211911655619_s52045411530323054071000.005802ET5926SUNRISE FOOD COMPLEX P L C6011Addis Abeba62430108INV-08950211911655619_s0612yayacheckout6304B01D",
        "description": "June bill",
        "cardPaymentUrl": null,
        "paymentLink": "http://localhost:8080/p/92AE1D227EE1",
        "thankYouUrl": "https://env-url/ty/92AE1D227EE1",
        "returnUrl": "https://yourwebsite.com/thank-you",
        "callbackUrl": "https://6833e09e464b499636008b3e.mockapi.io/callback",
        "metaData": {
            "customer_id": "1234",
            "customer_name": "Abebe Kebede",
            "customer_phone": "0911059599"
        },
        "createdAt": "2025-06-01T09:27:32.070Z",
        "updatedAt": "2025-06-01T09:27:32.070Z"
    }
}
Important Note:

After creating a payment intent, you must share the paymentLink with the payer to receive payment. You can either:

  • Redirect the payer to the payment link immediately after creating the payment intent
  • Share the payment link through your preferred communication channel (email, SMS, etc.)

The payment link is the primary way for payers to complete their payment. Without sharing this link, the payer won't be able to make the payment.

Alternative Payment Method: You may also share the payment code with the payer, who can then make a direct bank transfer to YaYa Wallet account 7777. The payer must include the payment code in the transfer reason/message field for proper payment matching.

Code Examples

List Payment Intents

GET /api/payment-intents

Retrieves paginated list of payment intents for the authenticated merchant. Requires OAuth2 authentication.

Headers:
Authorization: Bearer your_access_token

Query Parameters:
- page: Page number (default: 1)
- limit: Items per page (default: 10)
- status: Filter by status (pending, paid, failed)
- startDate: Filter by start date (YYYY-MM-DD)
- endDate: Filter by end date (YYYY-MM-DD)
- sortBy: Sort field (created_at, updated_at, amount, status)
- sortOrder: Sort order (asc, desc)
- customerId: Filter by customer_id from meta_data

Response:
{
    "draw": 1,
    "recordsTotal": 100,
    "recordsFiltered": 100,
    "data": [
        {
            "id": "uuid",
            "amount": 1000.00,
            "processingFee": 25.00,
            "total": 1025.00,
            "status": "paid",
            "merchantName": "Example Store",
            "paymentReference": "INV-001",
            "transactionReference": "TRX123456",
            "urlSlug": "example-store",
            "createdAt": "2024-03-20T10:00:00Z",
            "updatedAt": "2024-03-20T10:05:00Z",
            "paymentLink": "https://env-url/p/example-store",
            "thankYouUrl": "https://env-url/ty/example-store",
            "localization": {
                "formattedAmount": "ETB 1,000.00",
                "formattedProcessingFee": "ETB 25.00",
                "formattedTotal": "ETB 1,025.00",
                "createdAt": "Mar 20, 2024 10:00 AM",
                "updatedAt": "Mar 20, 2024 10:05 AM"
            },
            "urlSlug": "example-store"
        }
    ]
}

Get Payment Details

GET /api/payment-info/:urlSlug

Retrieves detailed information about a specific payment intent using the URL slug. Requires OAuth2 authentication.

Headers:
Authorization: Bearer your_access_token

Response:
{
    "id": "uuid",
    "amount": 1000.00,
    "processingFee": 25.00,
    "total": 1025.00,
    "status": "paid",
    "merchantName": "Example Store",
    "paymentReference": "INV-001",
    "transactionReference": "TRX123456",
    "urlSlug": "example-store",
    "createdAt": "2024-03-20T10:00:00Z",
    "updatedAt": "2024-03-20T10:05:00Z",
    "paymentLink": "https://env-url/p/example-store",
    "thankYouUrl": "https://env-url/ty/example-store",
    "localization": {
        "formattedAmount": "ETB 1,000.00",
        "formattedProcessingFee": "ETB 25.00",
        "formattedTotal": "ETB 1,025.00",
        "createdAt": "Mar 20, 2024 10:00 AM",
        "updatedAt": "Mar 20, 2024 10:05 AM"
    },
    "beneficiaryAccountDetails": {
        "bankBic": "YAYAETAA",
        "bankAccount": "1234567890",
        "accountHolderName": "Example Store"
    }
}

Cancel Payment Intent

DELETE /api/payment-intent/:paymentId/cancel

Cancels a pending payment intent by payment ID. Requires OAuth2 authentication.

Headers:
Authorization: Bearer your_access_token

Response:
{
    "success": true,
    "message": "Payment intent cancelled successfully",
    "data": {
        "paymentIntentId": "uuid",
        "paymentId": "uuid",
        "uniqueRef": "string"
    }
}

Generate Merchant Reference

GET /api/payment-intent/generate-reference

Generates a unique merchant reference for new transactions. Requires OAuth2 authentication.

Note: You can use your own reference numbers. The merchant reference should be unique within your merchant account.
Response:
{
    "reference": "INV-123456"
}

Lookup Endpoints

List Banks

GET /api/banks

Retrieves a list of all supported banks and their details. Requires OAuth2 authentication.

Response:
[
    {
        "bic": "CBEETAA",
        "name": "Commercial Bank of Ethiopia",
        "logo": "https://env-url/images/banks/cbe.png"
    },
    {
        "bic": "YAYAETAA",
        "name": "YaYa Wallet",
        "logo": "https://env-url/images/banks/yaya.png"
    }
]

List Merchant Categories

GET /api/merchant-categories

Retrieves a list of all supported merchant categories (MCC codes) and their descriptions. Requires OAuth2 authentication.

Response:
[
    {
        "code": "5411",
        "description": "Retail stores primarily selling food and household items"
    },
    {
        "code": "5812",
        "description": "Establishments primarily engaged in preparing and serving meals"
    },
    {
        "code": "5311",
        "description": "Retail stores selling a wide variety of merchandise"
    }
]

Field Descriptions

Below is a comprehensive list of all fields used in the payment system, their purposes, and important notes about their usage.

Field Description Notes
Request Fields Required fields in the request payload:
bankBic Bank Identifier Code for routing payments.
  • Currently only supports "YAYAETAA"
  • Required for payment routing
bankAccount Account identifier for receiving payments.
  • Must be a valid account identifier
  • Must match the specified BIC
amount Payment amount in ETB.
  • Must be a positive integer
  • No decimal places allowed
paymentReference Unique identifier for the payment.
  • Must be unique within your account
  • Used for reconciliation
feeOnMerchant Determines who pays the processing fee.
  • true: merchant pays the fee
  • false: payer pays the fee
⚠️ Warning: Based on specific agreements arranged with YaYa Wallet, the fee_on_merchant setting can be enforced at the account level. In such cases, whatever value is passed in the payload will be overridden by the enforced setting from your account configuration.
callbackUrl URL for payment status updates.
  • Required for real-time updates
  • Must be HTTPS
meta_data Optional JSON object containing additional metadata.
  • Can include customer information, order details, etc.
  • Used for filtering payment intents by customer_id
  • customer_phone is used to prefill USSD payment forms
  • Displayed in payment intent details page
Response Fields Important fields in the response:
urlSlug Short identifier for payment URLs.
  • Used in payment and thank you URLs
  • Same as paymentCode
processingFee Fee charged for processing the payment.
  • Fixed amount in ETB
  • Added to total if feeOnMerchant is false
qrCode QR code for mobile payment.
  • Contains payment details
  • Can be scanned by mobile apps
paymentLink URL for the payment page.
  • Direct link to payment page
  • Format: {baseUrl}/p/{urlSlug}

Meta Data Features

The payment intent system supports optional metadata that can be used to store additional information about the payment, such as customer details, order information, or any other relevant data.

Meta Data Structure

The meta_data field accepts a JSON object with any key-value pairs. Here are some common use cases:

{
    "customer_id": "1234",
    "customer_name": "Abebe Kebede",
    "customer_phone": "0911059599",
    "order_id": "ORD-001",
    "invoice_number": "INV-2024-001",
    "notes": "Special delivery instructions"
}

Special Meta Data Fields

Certain fields in the meta_data have special functionality:

customer_id

Used for filtering payment intents in the list API. You can retrieve all payments for a specific customer by including the customerId query parameter.

GET /api/payment-intents?customerId=1234

customer_phone

When present, this phone number will be automatically prefilled in the USSD payment form, making it easier for customers to complete their payment.

Note: The phone number should be in Ethiopian format (e.g., "0911059599" or "+251911059599"). The system will automatically format it for display and input.

Display in Payment Details

All meta_data fields are displayed in the payment intent details page under the "Additional Information" section, making it easy to view all associated data for a payment.

Integration Steps

  1. Start with Sandbox Mode:
    • Register and obtain your API credentials
    • Set your environment to sandbox mode
    • Test the integration using supported payment methods
  2. Test with Payment Simulation:
    • Use the sandbox payment simulator to create and process test payments
    • Verify that your callback endpoint receives payment notifications
    • Monitor the payment status updates in real-time
  3. Switch to Live Mode:
    • Once testing is complete, switch to live mode
    • Update your API credentials for live environment
    • Start processing real transactions
Note: The sandbox environment is designed for testing and development. Use this environment to thoroughly test your integration with all supported payment methods before switching to live mode.

Callback Implementation

Our system sends payment status updates to your callback URL. It's recommended to use a unique callback URL for each payment intent to better track and manage payments.

Callback Request Format

POST your_callback_url
Headers:
Content-Type: application/json
X-Payment-Signature: generated_signature

Request Body:
{
    "paymentId": "7d31bd3f-6223-4b14-b174-584913f39323",
    "paymentReference": "INV-005",
    "amount": 1000,
    "isFeeOnMerchant": true,
    "processingFee": "20.00",
    "status": "paid",
    "bankBic": "YAYAETAA",
    "bankAccount": "antenehgebey",
    "paymentCode": "CAE8CD8E4901",
    "transactionId": "TXN-7497B30295A1D9AD",
    "paymentLink": "https://pay.yayawallet.com/p/CAE8CD8E4901",
    "thankYouUrl": "https://env-url/ty/CAE8CD8E4901",
    "returnUrl": "https://yourwebsite.com/thank-you",
    "timestamp": "2025-06-01T08:31:46.091Z",
    "createdAt": "2025-06-01T08:30:08.046Z",
    "updatedAt": "2025-06-01T08:31:46.088Z"
}

Signature Validation

To ensure the callback is legitimate, validate the signature using the following process:

  1. Concatenate the paymentId, paymentReference, and amount in this order: paymentId + paymentReference + amount
  2. Generate an HMAC SHA-256 hash using your client secret as the key
  3. Compare the generated hash with the signature in the X-Payment-Signature header
Example validation in Node.js:
const crypto = require('crypto');

function validateSignature(paymentId, paymentReference, amount, signature, clientSecret) {
    const data = `${paymentId}${paymentReference}${amount}`;
    const expectedSignature = crypto.createHmac('sha256', clientSecret)
        .update(data)
        .digest('hex');
    return signature === expectedSignature;
}

// Example usage in Express middleware
app.post('/payment-callback', (req, res) => {
    const signature = req.headers['x-payment-signature'];
    const { paymentId, paymentReference, amount } = req.body;
    
    if (!validateSignature(paymentId, paymentReference, amount, signature, process.env.CLIENT_SECRET)) {
        return res.status(401).json({ error: 'Invalid signature' });
    }
    
    // Process the payment notification
    // ...
    
    res.status(200).json({ received: true });
});
Important:
  • Always validate the signature before processing the callback
  • Use a unique callback URL for each payment intent to prevent confusion
  • Implement proper error handling and logging for failed callbacks
  • Respond with a 200 status code to acknowledge receipt of the callback
  • Our system may retry failed callbacks multiple times. Implement idempotency to prevent duplicate processing of the same payment status update
  • Use the paymentId and transactionId to track and deduplicate callbacks

Security Considerations