Skip to content

Pay-Out API Specification

Owner Classification Review Date Status
CDO Office Internal April 2027 Active
openapi: 3.1.0
info:
  title: Simpaisa Pay-Out API
  version: 3.0.0
  description: |
    Simpaisa Pay-Out (Disbursements) API enables merchants to send funds to
    bank accounts and mobile wallets across Pakistan, Bangladesh, Nepal,
    and Iraq. The platform supports single and batch disbursements,
    beneficiary management and real-time balance enquiries.

    Processing 270M+ transactions and over $1B in volume, the disbursement
    service provides reliable, auditable fund transfers with full idempotency
    and webhook-based status notifications.

    All requests must be signed using RSA-SHA256.
  contact:
    name: Simpaisa Platform Engineering
    url: https://www.simpaisa.com
    email: [email protected]
  license:
    name: Proprietary
    url: https://www.simpaisa.com/terms
  x-logo:
    url: https://www.simpaisa.com/logo.png

servers:
  - url: https://api.simpaisa.com
    description: Production
  - url: https://sandbox.simpaisa.com
    description: Sandbox

security:
  - rsaSha256Signature: []

paths:
  /v3/disbursements/{merchantId}/transactions/initiate:
    post:
      operationId: initiateDisbursement
      summary: Initiate a disbursement
      description: |
        Creates a new disbursement to transfer funds to a beneficiary's bank
        account or mobile wallet. The transaction is processed asynchronously;
        use the webhook callback or polling to track status.
      tags:
        - Transactions
      parameters:
        - $ref: '#/components/parameters/MerchantIdPath'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/XMerchantId'
        - $ref: '#/components/parameters/XTimestamp'
        - $ref: '#/components/parameters/XSignature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DisbursementRequest'
      responses:
        '201':
          description: Disbursement initiated
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DisbursementResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
      callbacks:
        disbursementStatusUpdate:
          '{$request.body#/callbackUrl}':
            post:
              summary: Disbursement status webhook
              requestBody:
                required: true
                content:
                  application/json:
                    schema:
                      $ref: '#/components/schemas/WebhookPayload'
              responses:
                '200':
                  description: Webhook acknowledged

  /v3/disbursements/{merchantId}/transactions/{transactionId}:
    get:
      operationId: getDisbursement
      summary: Retrieve a disbursement
      description: Returns the current state of a disbursement transaction.
      tags:
        - Transactions
      parameters:
        - $ref: '#/components/parameters/MerchantIdPath'
        - $ref: '#/components/parameters/TransactionIdPath'
        - $ref: '#/components/parameters/XMerchantId'
        - $ref: '#/components/parameters/XTimestamp'
        - $ref: '#/components/parameters/XSignature'
      responses:
        '200':
          description: Disbursement retrieved
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DisbursementResponse'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v3/disbursements/{merchantId}/transactions/batch:
    post:
      operationId: createBatchDisbursement
      summary: Create a batch disbursement
      description: |
        Submits multiple disbursement instructions in a single request. Each
        item in the batch is processed independently; partial failures are
        possible. The response includes a batch identifier for tracking.
      tags:
        - Transactions
      parameters:
        - $ref: '#/components/parameters/MerchantIdPath'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/XMerchantId'
        - $ref: '#/components/parameters/XTimestamp'
        - $ref: '#/components/parameters/XSignature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchRequest'
      responses:
        '202':
          description: Batch accepted for processing
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v3/disbursements/{merchantId}/transactions:
    get:
      operationId: listDisbursements
      summary: List disbursement transactions
      description: |
        Returns a paginated list of disbursement transactions. Uses cursor-based
        pagination for consistent results across large datasets.
      tags:
        - Transactions
      parameters:
        - $ref: '#/components/parameters/MerchantIdPath'
        - $ref: '#/components/parameters/XMerchantId'
        - $ref: '#/components/parameters/XTimestamp'
        - $ref: '#/components/parameters/XSignature'
        - name: cursor
          in: query
          description: Opaque cursor from the previous response for pagination
          schema:
            type: string
        - name: limit
          in: query
          description: Maximum number of records to return
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - name: status
          in: query
          description: Filter by transaction status
          schema:
            type: string
            enum:
              - INITIATED
              - PROCESSING
              - COMPLETED
              - FAILED
              - REVERSED
        - name: fromDate
          in: query
          description: Start date filter (ISO 8601)
          schema:
            type: string
            format: date-time
        - name: toDate
          in: query
          description: End date filter (ISO 8601)
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Transaction list retrieved
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                type: object
                required:
                  - transactions
                  - pagination
                  - traceId
                properties:
                  transactions:
                    type: array
                    items:
                      $ref: '#/components/schemas/DisbursementResponse'
                  pagination:
                    $ref: '#/components/schemas/CursorPagination'
                  traceId:
                    type: string
                    format: uuid
        '401':
          $ref: '#/components/responses/Unauthorised'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v3/disbursements/{merchantId}/balance:
    get:
      operationId: getDisbursementBalance
      summary: Retrieve disbursement balance
      description: Returns the merchant's current disbursement wallet balance.
      tags:
        - Balance
      parameters:
        - $ref: '#/components/parameters/MerchantIdPath'
        - $ref: '#/components/parameters/XMerchantId'
        - $ref: '#/components/parameters/XTimestamp'
        - $ref: '#/components/parameters/XSignature'
      responses:
        '200':
          description: Balance retrieved
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BalanceResponse'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v3/disbursements/{merchantId}/banks:
    get:
      operationId: listBanks
      summary: List supported banks
      description: |
        Returns the list of banks and mobile wallet operators available for
        disbursements in the merchant's configured corridors.
      tags:
        - Reference Data
      parameters:
        - $ref: '#/components/parameters/MerchantIdPath'
        - $ref: '#/components/parameters/XMerchantId'
        - $ref: '#/components/parameters/XTimestamp'
        - $ref: '#/components/parameters/XSignature'
      responses:
        '200':
          description: Bank list retrieved
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BankListResponse'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /v3/disbursements/{merchantId}/beneficiaries:
    post:
      operationId: createBeneficiary
      summary: Register a beneficiary
      description: |
        Creates a saved beneficiary record for recurring disbursements.
        Beneficiary details are validated against the specified bank's
        requirements.
      tags:
        - Beneficiaries
      parameters:
        - $ref: '#/components/parameters/MerchantIdPath'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/XMerchantId'
        - $ref: '#/components/parameters/XTimestamp'
        - $ref: '#/components/parameters/XSignature'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BeneficiaryRequest'
      responses:
        '201':
          description: Beneficiary created
          headers:
            X-Trace-Id:
              $ref: '#/components/headers/XTraceId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BeneficiaryResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'

components:
  securitySchemes:
    rsaSha256Signature:
      type: apiKey
      in: header
      name: X-Signature
      description: |
        RSA-SHA256 signature computed over the canonical request string.
        The merchant signs the request payload concatenated with the timestamp
        using their RSA private key.

  parameters:
    MerchantIdPath:
      name: merchantId
      in: path
      required: true
      description: Unique merchant identifier issued during onboarding
      schema:
        type: string
        example: MCH-00123
    TransactionIdPath:
      name: transactionId
      in: path
      required: true
      description: Unique transaction identifier
      schema:
        type: string
        format: uuid
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      description: |
        Client-generated unique key for idempotent request processing.
        Duplicate requests within 24 hours return the original response.
      schema:
        type: string
        format: uuid
    XMerchantId:
      name: X-Merchant-Id
      in: header
      required: true
      description: Merchant identifier for request authentication
      schema:
        type: string
    XTimestamp:
      name: X-Timestamp
      in: header
      required: true
      description: ISO 8601 timestamp of the request
      schema:
        type: string
        format: date-time
    XSignature:
      name: X-Signature
      in: header
      required: true
      description: RSA-SHA256 signature of the canonical request string
      schema:
        type: string

  headers:
    XTraceId:
      description: Unique trace identifier for request tracking
      schema:
        type: string
        format: uuid
    XRateLimitLimit:
      description: Maximum requests permitted per window
      schema:
        type: integer
    XRateLimitRemaining:
      description: Requests remaining in current window
      schema:
        type: integer
    XRateLimitReset:
      description: Unix epoch when the rate limit resets
      schema:
        type: integer

  schemas:
    DisbursementRequest:
      type: object
      required:
        - amount
        - currency
        - beneficiaryAccountNumber
        - bankCode
        - beneficiaryName
        - merchantTransactionId
      properties:
        amount:
          type: number
          format: double
          description: Disbursement amount
          example: 25000.00
        currency:
          type: string
          pattern: '^[A-Z]{3}$'
          description: ISO 4217 currency code
          example: PKR
        beneficiaryAccountNumber:
          type: string
          description: Beneficiary account number or IBAN
          example: PK36SCBL0000001123456702
        bankCode:
          type: string
          description: Bank identifier from the banks endpoint
          example: SCB
        beneficiaryName:
          type: string
          description: Full name of the beneficiary
          example: Ahmed Khan
        beneficiaryId:
          type: string
          description: Saved beneficiary identifier (alternative to inline details)
        merchantTransactionId:
          type: string
          description: Merchant's unique reference
          maxLength: 64
          example: PAYOUT-2026-00789
        purpose:
          type: string
          description: Purpose of the disbursement
          example: Salary payment
        callbackUrl:
          type: string
          format: uri
          description: URL for webhook notifications
        metadata:
          type: object
          additionalProperties:
            type: string

    DisbursementResponse:
      type: object
      required:
        - transactionId
        - merchantTransactionId
        - status
        - amount
        - currency
        - traceId
      properties:
        transactionId:
          type: string
          format: uuid
        merchantTransactionId:
          type: string
        status:
          type: string
          enum:
            - INITIATED
            - PROCESSING
            - COMPLETED
            - FAILED
            - REVERSED
        amount:
          type: number
          format: double
        currency:
          type: string
        beneficiaryAccountNumber:
          type: string
        beneficiaryName:
          type: string
        bankCode:
          type: string
        bankTransactionId:
          type: string
          description: Reference from the receiving bank
        failureReason:
          type: string
          description: Reason for failure, if applicable
        completedAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        metadata:
          type: object
          additionalProperties:
            type: string
        traceId:
          type: string
          format: uuid

    BatchRequest:
      type: object
      required:
        - items
        - merchantBatchId
      properties:
        merchantBatchId:
          type: string
          description: Merchant's unique batch reference
          maxLength: 64
          example: BATCH-2026-00123
        items:
          type: array
          minItems: 1
          maxItems: 500
          items:
            $ref: '#/components/schemas/DisbursementRequest'
          description: Individual disbursement instructions
        callbackUrl:
          type: string
          format: uri
          description: URL for batch-level webhook notifications

    BatchResponse:
      type: object
      required:
        - batchId
        - merchantBatchId
        - status
        - totalItems
        - traceId
      properties:
        batchId:
          type: string
          format: uuid
          description: Simpaisa-assigned batch identifier
        merchantBatchId:
          type: string
        status:
          type: string
          enum:
            - ACCEPTED
            - PROCESSING
            - COMPLETED
            - PARTIALLY_COMPLETED
            - FAILED
        totalItems:
          type: integer
          description: Total number of items in the batch
        acceptedItems:
          type: integer
          description: Number of items accepted for processing
        rejectedItems:
          type: integer
          description: Number of items rejected at submission
        totalAmount:
          type: number
          format: double
          description: Sum of all accepted item amounts
        currency:
          type: string
        createdAt:
          type: string
          format: date-time
        traceId:
          type: string
          format: uuid

    BalanceResponse:
      type: object
      required:
        - availableBalance
        - currency
        - traceId
      properties:
        availableBalance:
          type: number
          format: double
          description: Funds available for disbursement
          example: 5000000.00
        pendingBalance:
          type: number
          format: double
          description: Funds reserved for in-flight disbursements
          example: 150000.00
        currency:
          type: string
          example: PKR
        lastUpdatedAt:
          type: string
          format: date-time
        traceId:
          type: string
          format: uuid

    BankListResponse:
      type: object
      required:
        - banks
        - traceId
      properties:
        banks:
          type: array
          items:
            type: object
            required:
              - bankCode
              - name
              - country
              - status
            properties:
              bankCode:
                type: string
                example: HBL
              name:
                type: string
                example: Habib Bank Limited
              country:
                type: string
                description: ISO 3166-1 alpha-2 country code
                example: PK
              type:
                type: string
                enum:
                  - BANK
                  - MOBILE_WALLET
                  - MICROFINANCE
              accountNumberFormat:
                type: string
                description: Expected account number pattern
                example: '^PK[0-9]{2}[A-Z]{4}[0-9]{16}$'
              status:
                type: string
                enum:
                  - ACTIVE
                  - DEGRADED
                  - INACTIVE
        traceId:
          type: string
          format: uuid

    BeneficiaryRequest:
      type: object
      required:
        - name
        - accountNumber
        - bankCode
      properties:
        name:
          type: string
          description: Full legal name of the beneficiary
          example: Fatima Bibi
        accountNumber:
          type: string
          description: Account number or IBAN
          example: PK36SCBL0000001123456702
        bankCode:
          type: string
          description: Bank identifier
          example: SCB
        accountType:
          type: string
          enum:
            - CURRENT
            - SAVINGS
            - WALLET
          description: Type of account
        msisdn:
          type: string
          description: Mobile number in E.164 format (required for wallet disbursements)
        email:
          type: string
          format: email
          description: Beneficiary email for notifications
        metadata:
          type: object
          additionalProperties:
            type: string

    BeneficiaryResponse:
      type: object
      required:
        - beneficiaryId
        - name
        - accountNumber
        - bankCode
        - traceId
      properties:
        beneficiaryId:
          type: string
          format: uuid
        name:
          type: string
        accountNumber:
          type: string
        bankCode:
          type: string
        accountType:
          type: string
        msisdn:
          type: string
        email:
          type: string
        createdAt:
          type: string
          format: date-time
        traceId:
          type: string
          format: uuid

    CursorPagination:
      type: object
      required:
        - hasMore
      properties:
        cursor:
          type: string
          description: Opaque cursor to fetch the next page
        hasMore:
          type: boolean
          description: Whether additional pages exist
        totalCount:
          type: integer
          description: Total number of matching records (when available)

    WebhookPayload:
      type: object
      required:
        - event
        - transactionId
        - merchantTransactionId
        - status
        - timestamp
        - signature
      properties:
        event:
          type: string
          enum:
            - DISBURSEMENT_COMPLETED
            - DISBURSEMENT_FAILED
            - DISBURSEMENT_REVERSED
            - BATCH_COMPLETED
            - BATCH_PARTIALLY_COMPLETED
        transactionId:
          type: string
          format: uuid
        merchantTransactionId:
          type: string
        batchId:
          type: string
          format: uuid
        status:
          type: string
        amount:
          type: number
          format: double
        currency:
          type: string
        bankTransactionId:
          type: string
        failureReason:
          type: string
        timestamp:
          type: string
          format: date-time
        signature:
          type: string
          description: RSA-SHA256 signature for webhook verification

    ErrorResponse:
      type: object
      required:
        - error
        - traceId
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              example: INSUFFICIENT_BALANCE
            message:
              type: string
              example: Insufficient funds for this disbursement.
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                  reason:
                    type: string
        traceId:
          type: string
          format: uuid

  responses:
    BadRequest:
      description: Invalid request parameters
      headers:
        X-Trace-Id:
          $ref: '#/components/headers/XTraceId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorised:
      description: Authentication failed
      headers:
        X-Trace-Id:
          $ref: '#/components/headers/XTraceId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Resource not found
      headers:
        X-Trace-Id:
          $ref: '#/components/headers/XTraceId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Conflict:
      description: Duplicate Idempotency-Key with different request body
      headers:
        X-Trace-Id:
          $ref: '#/components/headers/XTraceId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    UnprocessableEntity:
      description: Request understood but cannot be processed
      headers:
        X-Trace-Id:
          $ref: '#/components/headers/XTraceId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    TooManyRequests:
      description: Rate limit exceeded
      headers:
        X-Trace-Id:
          $ref: '#/components/headers/XTraceId'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalServerError:
      description: Unexpected server error
      headers:
        X-Trace-Id:
          $ref: '#/components/headers/XTraceId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

tags:
  - name: Transactions
    description: Disbursement transaction lifecycle operations
  - name: Balance
    description: Wallet balance enquiries
  - name: Reference Data
    description: Banks and operator discovery
  - name: Beneficiaries
    description: Saved beneficiary management