Skip to content

Direct Pay-In

Initiates a server-to-server deposit where the end user sends funds to the merchant. This flow does not require a user redirect — the payment is triggered directly (e.g., via a mobile money STK push).


Endpoint

POST /gateway/mmo/v2/direct/payin/{method}
Parameter Location Type Required Description
method Path string Yes Payment method key configured for your brand (e.g., mpesa-ke, airtel-ug). Max 100 characters.

Request Body

Required Fields

Field Type Description
amount Money Payment amount and currency
amount.value decimal Amount value. Must be greater than 0.
amount.currency string ISO 4217 currency code (e.g., "KES")
payer Msisdn Party End user initiating the payment
payer.id string Your identifier for the end user (max 255 chars)
payer.msisdn string Phone number in international format (3-20 chars)
country string ISO 3166-1 alpha-2 country code (max 10 chars)
resultUrl string HTTPS URL to receive the async result callback (max 2048 chars)
merchantReference string Unique idempotency key for this transaction (max 255 chars)

Optional Fields

Field Type Description
payer.firstName string End user's first name (max 255 chars)
payer.lastName string End user's last name (max 255 chars)
payer.email string End user's email address (max 320 chars)
reconciliationReference string Your reconciliation identifier (max 255 chars). Defaults to merchantReference if omitted.
labels object Key-value metadata (max 10 entries). See Labels.

Example Request

POST /gateway/mmo/v2/direct/payin/mpesa-ke HTTP/1.1
Host: api.payalo.com
X-Api-Key: <your-api-key>
Content-Type: application/json

{
  "amount": {
    "value": 500.00,
    "currency": "KES"
  },
  "payer": {
    "id": "user-42",
    "msisdn": "+254712345678",
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "[email protected]"
  },
  "country": "KE",
  "resultUrl": "https://merchant.example.com/webhooks/payalo",
  "merchantReference": "dep-20240601-001",
  "reconciliationReference": "INV-2024-001",
  "labels": {
    "orderId": "ORD-2024-001",
    "channel": "mobile-app"
  }
}

Response

Success — 200 OK

Returns the Initiate Payment response.

Field Type Description
status string Always "pending"
gatewayReference string Unique transaction ID (ULID format)
merchantReference string Echo of your request
reconciliationReference string Your reconciliation reference, or merchantReference if not provided
createdAt string ISO 8601 timestamp

Example Success Response

{
  "status": "pending",
  "gatewayReference": "b2p01j3abcdef0000000000000000a1b2",
  "merchantReference": "dep-20240601-001",
  "reconciliationReference": "INV-2024-001",
  "createdAt": "2024-06-01T12:34:56+00:00"
}

Error Responses

HTTP Status errorCode Specific code in type URL Scenario
400 validation_failed validation_failed A required field is missing or invalid.
400 validation_failed config_unsupported_country / config_unsupported_currency / config_unsupported_payment_method / config_method_transaction_min_limit / config_method_transaction_max_limit Country, currency, payment method, or amount is not allowed by your brand configuration.
400 validation_failed merchant_disabled Your brand has been disabled.
400 bad_request bad_request Request body is malformed or unreadable.
401 unauthorized unauthorized API key is missing or invalid.
404 not_found not_found Resource not found.
422 merchant_transactionid_duplicate merchant_transactionid_duplicate Duplicate merchantReference.
500 internal_server_error internal_server_error Unexpected server error.

See Error Handling for the full error response structure and error code reference.

Example Error Response — 400 Bad Request

{
  "type": "https://docs.payalo.com/errors/validation_failed",
  "title": "Validation failed",
  "status": 400,
  "detail": "Payer Msisdn is required.",
  "errorCode": "validation_failed"
}

Example Error Response — 422 Unprocessable Entity

{
  "type": "https://docs.payalo.com/errors/merchant_transactionid_duplicate",
  "title": "Business logic error",
  "status": 422,
  "detail": "Duplicate merchant transaction ID.",
  "errorCode": "merchant_transactionid_duplicate"
}

Callback

When the transaction reaches a terminal state (success or failed), the gateway sends a webhook to your resultUrl. See Callback Documentation for payload format, signature verification, and retry policy.


Status Flow

graph LR
    pending --> success
    pending --> failed

The transaction enters pending on creation. After asynchronous processing it moves to either success or failed. See Transaction Lifecycle for full details.