> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waftpay.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Initiate Collection

> Create a customer collection request.

## 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**

| Header          | Required | Notes                       |
| --------------- | -------- | --------------------------- |
| `Authorization` | Yes      | `Bearer <collection_token>` |
| `Content-Type`  | Yes      | `application/json`          |

***

## Request body

**Top-level fields**

| Field          | Type   | Required | Notes                                             |
| -------------- | ------ | -------- | ------------------------------------------------- |
| `transaction`  | object | Yes      | Collection details and idempotency reference.     |
| `originator`   | object | Yes      | Customer details.                                 |
| `recipient`    | object | Yes      | Collection recipient details.                     |
| `callback_url` | string | Yes      | HTTPS URL for final status callbacks.             |
| `meta`         | object | No       | Arbitrary key/value metadata echoed in callbacks. |

**transaction**

| Field          | Type    | Required | Notes                                                |
| -------------- | ------- | -------- | ---------------------------------------------------- |
| `reference`    | string  | Yes      | Client-generated unique reference (idempotency key). |
| `amount`       | integer | Yes      | Amount in major units (e.g., 1000 = 1000 KES).       |
| `currency`     | string  | Yes      | ISO 4217 currency code (e.g., KES, USD).             |
| `description`  | string  | Yes      | Short narrative for the collection.                  |
| `timestamp`    | string  | Yes      | ISO 8601 UTC timestamp (must end with `Z`).          |
| `service_code` | string  | No       | Collection service code if enabled on your account.  |

**originator**

| Field     | Type   | Required | Notes                                 |
| --------- | ------ | -------- | ------------------------------------- |
| `msisdn`  | string | Yes      | MSISDN format (e.g., 2547XXXXXXXX).   |
| `channel` | string | Yes      | Initiation channel (e.g., USSD, API). |
| `country` | string | Yes      | ISO 3166-1 country code (e.g., KE).   |
| `name`    | string | Yes      | Customer full name.                   |
| `purpose` | string | Yes      | Purpose of the collection.            |

**recipient**

| Field            | Type   | Required | Notes                                                          |
| ---------------- | ------ | -------- | -------------------------------------------------------------- |
| `invoice_number` | string | No       | Invoice number for reconciliation (if applicable).             |
| `reference`      | string | Yes      | Client-generated reference for recipient-side tracking.        |
| `account`        | string | Yes      | Recipient account identifier (phone, wallet, or bank account). |

***

## Example request

```json theme={null}
{
  "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)

```json theme={null}
{
  "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](/pages/webhooks/overview).
* Errors follow the standard error shape. See [Errors](/errors).


## OpenAPI

````yaml POST /payments/api/v1/collections
openapi: 3.1.0
info:
  title: Waftpay Payments API
  description: >-
    Process payments, collect funds, and remit payouts with Waftpay. Includes
    Authentication Token, idempotency, webhooks, and sandbox support.
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://dev.waftpay.io
    description: Sandbox (dev)
security:
  - bearerAuth: []
tags:
  - name: Authentication
    description: Obtain and manage access tokens
  - name: Payments
    description: Charge a customer and track status
  - name: Collections
    description: Customer-initiated payments and hosted checkouts
  - name: Checkout
    description: >-
      Hosted checkout flow for customer payments.


      Flow:

      1. Ensure the Collections service is enabled for your account.

      2. Use `consumer_key` and `consumer_secret` to generate a Bearer token via
      **Get Authentication Token**.

      3. Cache the token and refresh only on expiry.

      4. Call **Create Checkout Request** with customer details, amount, and
      redirect URLs.

      5. Use the returned `checkout_url` for redirect or iframe.

      6. The `callback_url` receives a payload matching the `CheckoutCallback`
      schema.
  - name: Remittance
    description: Send payouts to mobile wallets and bank accounts
  - name: Webhooks
    description: Receive asynchronous notifications
  - name: Utilities
    description: Common utilities (idempotency, health)
paths:
  /payments/api/v1/collections:
    post:
      tags:
        - Collections
      summary: Initiate Collection
      description: >-
        Create a customer collection request. Provide a unique
        `transaction.reference` for idempotency. Uses the same authentication
        and signature flow as payouts.
      operationId: initiateCollection
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCollectionRequestV1'
            examples:
              default:
                value:
                  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
      responses:
        '201':
          description: Accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PayoutInitiationResponse'
              examples:
                accepted:
                  summary: Accepted for processing
                  value:
                    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'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                required:
                  - code
                  - status
                  - description
                  - data
                properties:
                  code:
                    type: string
                  status:
                    type: string
                  description:
                    type: string
                  data:
                    type: object
              examples:
                missingAuthorization:
                  value:
                    code: 400.008.100
                    status: REJECTED
                    description: Missing or invalid Authorization header
                    data: {}
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    CreateCollectionRequestV1:
      type: object
      required:
        - transaction
        - originator
        - recipient
        - callback_url
      properties:
        transaction:
          type: object
          required:
            - reference
            - amount
            - currency
            - description
            - timestamp
          properties:
            reference:
              type: string
              description: >-
                Client-generated unique reference (idempotency key). Reuse to
                safely retry.
            amount:
              type: integer
              description: Amount in major units (e.g., 1000 = 1000 KES).
            currency:
              type: string
              description: ISO 4217 currency code in upper-case, e.g., KES, USD.
            description:
              type: string
              description: Short narrative for the collection.
            service_code:
              type: string
              description: Service the client wants to consume (e.g., RMT_WU, MPESA_STK).
            timestamp:
              type: string
              format: date-time
              description: >-
                ISO 8601 UTC timestamp (e.g., 2025-01-21T12:30:10Z). **Must end
                with 'Z'**.
        originator:
          type: object
          required:
            - msisdn
            - channel
            - country
            - name
            - purpose
          properties:
            msisdn:
              type: string
              description: Originator phone number in MSISDN format (e.g., 2547XXXXXXXX).
            channel:
              type: string
              description: Channel used to initiate the collection (e.g., USSD, API).
            country:
              type: string
              description: Country code (ISO 3166-1 like 'KE').
            name:
              type: string
              description: Originator/customer full name.
            purpose:
              type: string
              description: Purpose of the collection (e.g., Salary Payment).
        recipient:
          type: object
          required:
            - reference
            - account
          properties:
            invoice_number:
              type: string
              description: Optional invoice number associated with the transaction.
            reference:
              type: string
              description: Client-generated unique reference for recipient context.
            account:
              type: string
              description: Customer account identifier (phone, wallet, bank account, etc.).
        callback_url:
          type: string
          format: uri
          description: HTTPS URL to receive final status callbacks.
        meta:
          type: object
          description: Arbitrary key-value metadata echoed back in callbacks.
          additionalProperties: true
      examples:
        - 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
    PayoutInitiationResponse:
      type: object
      required:
        - status
        - code
        - description
        - data
      properties:
        status:
          type: string
          description: e.g., 200.100
        code:
          type: string
          description: ACCEPTED, REJECTED.
        description:
          type: string
        data:
          type: object
          required:
            - amount
            - transaction_reference
            - payment_uuid
            - payment_reference
            - time_received
          properties:
            amount:
              type: number
            transaction_reference:
              type: string
            payment_uuid:
              type: string
              description: UUID or numeric string identifier.
            payment_reference:
              type: string
            time_received:
              type: string
              format: date-time
              description: ISO 8601 UTC timestamp. **Always ends with 'Z'**.
          additionalProperties: true
      examples:
        accepted:
          summary: Accepted for processing
          value:
            status: '200.100'
            code: ACCEPTED
            description: Accepted for processing
            data: {}
        duplicateIgnored:
          summary: Duplicate ignored
          value:
            status: '200.100'
            code: REJECTED
            description: Duplicate payout ignored
            data: {}
        rejected:
          summary: Rejected
          value:
            status: '400.100'
            code: REJECTED
            description: Invalid recipient account number
            data: null
    WaftpayErrorEnvelope:
      type: object
      required:
        - code
        - status
        - description
      properties:
        code:
          type: string
          description: >-
            Application code. Can be a top-level code (e.g., 400.600) or a
            granular code (e.g., 404.001.000).
        status:
          type: string
          description: >-
            Semantic status, e.g., REJECTED, FAILED, UNAUTHORIZED, FORBIDDEN,
            NOT_FOUND, ACCEPTED.
        description:
          type: string
          description: Human-readable description.
        data:
          type: object
          description: Additional details (may be empty).
          additionalProperties: true
          nullable: true
      examples:
        notFoundGranular:
          summary: 404 with granular code
          value:
            code: 404.001.000
            status: REJECTED
            description: Requested resource not found
            data: {}
        validationFailed:
          summary: 400 validation failed
          value:
            code: '400.100'
            status: REJECTED
            description: Validation failed
            data:
              field_errors:
                - field: recipient.account
                  message: Invalid account
        unauthorized:
          summary: 401 failed authentication
          value:
            code: '400.200'
            status: REJECTED
            description: Failed Authentication
            data: null
        forbidden:
          summary: 403 failed authorization
          value:
            code: '403.300'
            status: REJECTED
            description: Failed Authorization
            data: null
        internal:
          summary: 500 internal server error
          value:
            code: '400.500'
            status: FAILED
            description: Internal server error
            data: null
  responses:
    Unauthorized:
      description: Missing or invalid token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WaftpayErrorEnvelope'
          examples:
            unauthorized:
              value:
                code: 400.001.100
                status: REJECTED
                description: Invalid or expired token
                data: {}
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````