Skip to main content
POST
/
payments
/
api
/
v1
/
collections
Initiate Collection
curl --request POST \
  --url https://dev.waftpay.io/payments/api/v1/collections \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "transaction": {
    "reference": "TNC000008",
    "amount": 1000,
    "currency": "KES",
    "description": "Test description",
    "service_code": "RMT_WU",
    "timestamp": "2025-01-21T12:30:10Z"
  },
  "originator": {
    "msisdn": "254712345678",
    "channel": "USSD",
    "country": "KE",
    "name": "John Doe",
    "purpose": "Salary Payment"
  },
  "recipient": {
    "invoice_number": "3456789987654",
    "reference": "INVJMA01",
    "account": "254712345678"
  },
  "callback_url": "https://merchant.example.com/callbacks/collection",
  "meta": {
    "note": "This info is returned as part of the callback",
    "agent_id": "AGENT456"
  }
}
'
import requests

url = "https://dev.waftpay.io/payments/api/v1/collections"

payload = {
"transaction": {
"reference": "TNC000008",
"amount": 1000,
"currency": "KES",
"description": "Test description",
"service_code": "RMT_WU",
"timestamp": "2025-01-21T12:30:10Z"
},
"originator": {
"msisdn": "254712345678",
"channel": "USSD",
"country": "KE",
"name": "John Doe",
"purpose": "Salary Payment"
},
"recipient": {
"invoice_number": "3456789987654",
"reference": "INVJMA01",
"account": "254712345678"
},
"callback_url": "https://merchant.example.com/callbacks/collection",
"meta": {
"note": "This info is returned as part of the callback",
"agent_id": "AGENT456"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
transaction: {
reference: 'TNC000008',
amount: 1000,
currency: 'KES',
description: 'Test description',
service_code: 'RMT_WU',
timestamp: '2025-01-21T12:30:10Z'
},
originator: {
msisdn: '254712345678',
channel: 'USSD',
country: 'KE',
name: 'John Doe',
purpose: 'Salary Payment'
},
recipient: {
invoice_number: '3456789987654',
reference: 'INVJMA01',
account: '254712345678'
},
callback_url: 'https://merchant.example.com/callbacks/collection',
meta: {note: 'This info is returned as part of the callback', agent_id: 'AGENT456'}
})
};

fetch('https://dev.waftpay.io/payments/api/v1/collections', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://dev.waftpay.io/payments/api/v1/collections",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'transaction' => [
'reference' => 'TNC000008',
'amount' => 1000,
'currency' => 'KES',
'description' => 'Test description',
'service_code' => 'RMT_WU',
'timestamp' => '2025-01-21T12:30:10Z'
],
'originator' => [
'msisdn' => '254712345678',
'channel' => 'USSD',
'country' => 'KE',
'name' => 'John Doe',
'purpose' => 'Salary Payment'
],
'recipient' => [
'invoice_number' => '3456789987654',
'reference' => 'INVJMA01',
'account' => '254712345678'
],
'callback_url' => 'https://merchant.example.com/callbacks/collection',
'meta' => [
'note' => 'This info is returned as part of the callback',
'agent_id' => 'AGENT456'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://dev.waftpay.io/payments/api/v1/collections"

payload := strings.NewReader("{\n \"transaction\": {\n \"reference\": \"TNC000008\",\n \"amount\": 1000,\n \"currency\": \"KES\",\n \"description\": \"Test description\",\n \"service_code\": \"RMT_WU\",\n \"timestamp\": \"2025-01-21T12:30:10Z\"\n },\n \"originator\": {\n \"msisdn\": \"254712345678\",\n \"channel\": \"USSD\",\n \"country\": \"KE\",\n \"name\": \"John Doe\",\n \"purpose\": \"Salary Payment\"\n },\n \"recipient\": {\n \"invoice_number\": \"3456789987654\",\n \"reference\": \"INVJMA01\",\n \"account\": \"254712345678\"\n },\n \"callback_url\": \"https://merchant.example.com/callbacks/collection\",\n \"meta\": {\n \"note\": \"This info is returned as part of the callback\",\n \"agent_id\": \"AGENT456\"\n }\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://dev.waftpay.io/payments/api/v1/collections")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"transaction\": {\n \"reference\": \"TNC000008\",\n \"amount\": 1000,\n \"currency\": \"KES\",\n \"description\": \"Test description\",\n \"service_code\": \"RMT_WU\",\n \"timestamp\": \"2025-01-21T12:30:10Z\"\n },\n \"originator\": {\n \"msisdn\": \"254712345678\",\n \"channel\": \"USSD\",\n \"country\": \"KE\",\n \"name\": \"John Doe\",\n \"purpose\": \"Salary Payment\"\n },\n \"recipient\": {\n \"invoice_number\": \"3456789987654\",\n \"reference\": \"INVJMA01\",\n \"account\": \"254712345678\"\n },\n \"callback_url\": \"https://merchant.example.com/callbacks/collection\",\n \"meta\": {\n \"note\": \"This info is returned as part of the callback\",\n \"agent_id\": \"AGENT456\"\n }\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://dev.waftpay.io/payments/api/v1/collections")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"transaction\": {\n \"reference\": \"TNC000008\",\n \"amount\": 1000,\n \"currency\": \"KES\",\n \"description\": \"Test description\",\n \"service_code\": \"RMT_WU\",\n \"timestamp\": \"2025-01-21T12:30:10Z\"\n },\n \"originator\": {\n \"msisdn\": \"254712345678\",\n \"channel\": \"USSD\",\n \"country\": \"KE\",\n \"name\": \"John Doe\",\n \"purpose\": \"Salary Payment\"\n },\n \"recipient\": {\n \"invoice_number\": \"3456789987654\",\n \"reference\": \"INVJMA01\",\n \"account\": \"254712345678\"\n },\n \"callback_url\": \"https://merchant.example.com/callbacks/collection\",\n \"meta\": {\n \"note\": \"This info is returned as part of the callback\",\n \"agent_id\": \"AGENT456\"\n }\n}"

response = http.request(request)
puts response.read_body
{
  "code": "100",
  "status": "ACCEPTED",
  "description": "Accepted for processing",
  "data": {
    "amount": 100,
    "transaction_reference": "919938",
    "payment_uuid": "413283551143664292",
    "payment_reference": "351CSICLV0",
    "time_received": "2026-01-07T09:44:43.558023Z"
  }
}
{
"code": "400.008.100",
"status": "REJECTED",
"description": "Missing or invalid Authorization header",
"data": {}
}
{
"code": "400.001.100",
"status": "REJECTED",
"description": "Invalid or expired token",
"data": {}
}

Overview

Use the Collections API to request money from a customer. Collections are asynchronous: you receive an acceptance response immediately, then a final outcome via webhook. This call is idempotent. Reuse the same transaction.reference to safely retry the same logical collection.

Authentication and signature

Required headers
HeaderRequiredNotes
AuthorizationYesBearer <collection_token>
Content-TypeYesapplication/json

Request body

Top-level fields
FieldTypeRequiredNotes
transactionobjectYesCollection details and idempotency reference.
originatorobjectYesCustomer details.
recipientobjectYesCollection recipient details.
callback_urlstringYesHTTPS URL for final status callbacks.
metaobjectNoArbitrary key/value metadata echoed in callbacks.
transaction
FieldTypeRequiredNotes
referencestringYesClient-generated unique reference (idempotency key).
amountintegerYesAmount in major units (e.g., 1000 = 1000 KES).
currencystringYesISO 4217 currency code (e.g., KES, USD).
descriptionstringYesShort narrative for the collection.
timestampstringYesISO 8601 UTC timestamp (must end with Z).
service_codestringNoCollection service code if enabled on your account.
originator
FieldTypeRequiredNotes
msisdnstringYesMSISDN format (e.g., 2547XXXXXXXX).
channelstringYesInitiation channel (e.g., USSD, API).
countrystringYesISO 3166-1 country code (e.g., KE).
namestringYesCustomer full name.
purposestringYesPurpose of the collection.
recipient
FieldTypeRequiredNotes
invoice_numberstringNoInvoice number for reconciliation (if applicable).
referencestringYesClient-generated reference for recipient-side tracking.
accountstringYesRecipient account identifier (phone, wallet, or bank account).

Example request

{
  "transaction": {
    "reference": "TNC000008",
    "amount": 1000,
    "currency": "KES",
    "description": "Test description",
    "timestamp": "2025-01-21T12:30:10Z",
    "service_code": "RMT_WU"
  },
  "originator": {
    "msisdn": "254712345678",
    "channel": "USSD",
    "country": "KE",
    "name": "John Doe",
    "purpose": "Salary Payment"
  },
  "recipient": {
    "invoice_number": "3456789987654",
    "reference": "INVJMA01",
    "account": "254712345678"
  },
  "callback_url": "https://merchant.example.com/callbacks/collection",
  "meta": {
    "note": "This info is returned as part of the callback",
    "agent_id": "AGENT456"
  }
}

Example response (accepted)

{
  "code": "100",
  "status": "ACCEPTED",
  "description": "Accepted for processing",
  "data": {
    "amount": 100,
    "transaction_reference": "919938",
    "payment_uuid": "413283551143664292",
    "payment_reference": "351CSICLV0",
    "time_received": "2026-01-07T09:44:43.558023Z"
  }
}

Notes

  • Final outcome is delivered via webhook. See Webhooks overview.
  • Errors follow the standard error shape. See Errors.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json
transaction
object
required
originator
object
required
recipient
object
required
callback_url
string<uri>
required

HTTPS URL to receive final status callbacks.

meta
object

Arbitrary key-value metadata echoed back in callbacks.

Response

Accepted

status
string
required

e.g., 200.100

code
string
required

ACCEPTED, REJECTED.

description
string
required
data
object
required