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

# Verify Transfer

> Submits the OTP for a wallet transfer that was initiated with mode `OTP_VERIFICATION`. 
Use **Get Transfer Details** or webhooks for terminal status.


<Note>
  Call this API after [Initiate Transfer](/api-reference/prepaid-payment-instruments/transfers/initiate-transfer). Use [Get Transfer Details](/api-reference/prepaid-payment-instruments/transfers/get-transfer-details) to proceed with bank processing after OTP succeeds.
</Note>

You can submit an OTP for verification **at most three times** per transfer.


## OpenAPI

````yaml /openapi/ppi/ppi.yaml post /ppi/wallet/transfer/verify
openapi: 3.0.3
info:
  title: PPI Wallet API
  description: >-
    API for managing PPI (Prepaid Payment Instrument) wallets and sub-wallets,
    including credit and debit operations.
  version: 1.0.0
  contact:
    name: PPI Service Team
    email: support@cashfree.com
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
servers:
  - url: https://api.cashfree.com
    description: Production server.
  - url: https://sandbox.cashfree.com
    description: Sandbox server.
security:
  - XClientID: []
    XClientSecret: []
tags:
  - name: Wallet Management
    description: Operations related to PPI wallet management.
  - name: User Management
    description: Operations related to user management within the PPI system.
  - name: Beneficiary Management
    description: Operations related to beneficiary management for users.
  - name: KYC Management
    description: Operations related to KYC (Know Your Customer) management.
  - name: Transfers
    description: Operations related to transfer.
paths:
  /ppi/wallet/transfer/verify:
    post:
      tags:
        - Transfers
      summary: Verify Transfer
      description: >
        Submits the OTP for a wallet transfer that was initiated with mode
        `OTP_VERIFICATION`. 

        Use **Get Transfer Details** or webhooks for terminal status.
      operationId: verifyWalletTransferOtp
      parameters:
        - $ref: '#/components/parameters/global_x_api_version'
      requestBody:
        $ref: '#/components/requestBodies/VerifyWalletTransferOtpRequest'
      responses:
        '200':
          description: Success response for verifying a wallet transfer OTP.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletTransferVerifyOtpResponse'
              examples:
                transfer_verify_success_response:
                  $ref: '#/components/examples/transfer_verify_success_response'
        '400':
          description: >-
            Bad request - Invalid OTP, expired OTP, validation failure, or
            attempts exhausted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StructuredErrorResponse'
              examples:
                otp_invalid:
                  $ref: '#/components/examples/transfer_otp_invalid'
                otp_expired:
                  $ref: '#/components/examples/transfer_otp_expired'
                otp_verification_exhausted:
                  $ref: '#/components/examples/transfer_otp_verification_exhausted'
                transfer_id_missing:
                  $ref: '#/components/examples/transfer_id_missing'
        '401':
          $ref: '#/components/responses/Response401'
        '403':
          $ref: '#/components/responses/Response403'
        '404':
          description: Not found - Transfer not found or not awaiting OTP verification.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StructuredErrorResponse'
              examples:
                transferNotFound:
                  summary: Transfer not found
                  value:
                    code: transfer_id_not_found
                    type: validation_error
                    message: No transfer found with the provided transfer_id
        '429':
          $ref: '#/components/responses/Response429'
        '500':
          $ref: '#/components/responses/Response500'
      security:
        - XClientID: []
          XClientSecret: []
components:
  parameters:
    global_x_api_version:
      description: API version to be used. Format is in YYYY-MM-DD.
      name: x-api-version
      in: header
      required: true
      schema:
        type: string
        default: '2025-11-01'
        example: '2025-11-01'
      example: '2025-11-01'
  requestBodies:
    VerifyWalletTransferOtpRequest:
      description: Request parameters to verify the OTP for a wallet transfer request.
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WalletTransferVerifyRequest'
          examples:
            verifyTransferOtp:
              summary: Verify transfer OTP
              value:
                transfer_id: TRANSFER123456
                otp: '222113'
  schemas:
    WalletTransferVerifyOtpResponse:
      type: object
      properties:
        user_id:
          type: string
          description: >-
            Unique identifier for the user, as provided by you during PPI user
            creation.
          example: USER827364
        wallet_id:
          type: string
          description: >-
            Unique identifier for the wallet, as provided by you during wallet
            creation.
          example: WALLET936721
        cf_transfer_id:
          type: string
          description: >-
            Unique identifier for the transfer transaction, generated by
            Cashfree.
          example: '8901234567890123456'
        transfer_id:
          type: string
          description: >-
            Unique identifier for the transfer transaction, as provided by you
            during the transfer request.
          example: TRANSFER123456
        amount:
          type: number
          format: double
          description: Amount that was transferred.
          example: 1250.5
        transfer_mode:
          type: string
          description: Mode of transfer used.
          enum:
            - RTGS
            - NEFT
            - IMPS
            - UPI
          example: IMPS
        sub_wallet:
          $ref: '#/components/schemas/SubWallet'
        status:
          type: string
          description: |
            Status of the transfer operation.
          enum:
            - RECEIVED
            - PENDING
            - SUCCESS
            - FAILED
            - REJECTED
            - VALIDATION_PENDING
            - REVERSED
            - APPROVAL_PENDING
            - QUEUED
            - MANUALLY_REJECTED
          example: PENDING
        bank_ref_no:
          type: string
          nullable: true
          description: >-
            Bank reference number for the transfer. Will be null if transfer is
            not yet processed.
          example: BNK202502101530001
        status_code:
          type: string
          description: |
            Status code for detailed tracking of transfer progress.
          example: TRANSFER_INITIATED
        bene_details:
          $ref: '#/components/schemas/BeneDetails'
        purpose:
          type: string
          description: Purpose of the transfer.
          example: SALARY
        remarks:
          type: string
          description: Remarks for the transfer transaction.
          example: Monthly groceries transfer
        notes:
          $ref: '#/components/schemas/Notes'
        initiated_at:
          type: string
          format: date-time
          description: Timestamp when the transfer transaction was initiated.
          example: '2025-09-02T10:15:30Z'
        processed_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Timestamp when the transfer transaction was processed. Will be null
            if still pending.
          example: '2025-09-02T10:17:45Z'
    StructuredErrorResponse:
      type: object
      properties:
        type:
          type: string
          description: A broad category of the error.
          example: internal_error
        code:
          type: string
          description: A machine-readable error code specific to the issue.
          example: internal_server_error
        message:
          type: string
          description: >-
            A message providing more details about the error, dynamic based on
            the specific issue.
          example: Internal server error
    WalletTransferVerifyRequest:
      type: object
      required:
        - transfer_id
        - otp
      properties:
        transfer_id:
          type: string
          description: >-
            Transfer identifier from the initiate transfer request
            (`transfer_id` you supplied while initiating the transfer).
          example: TRANSFER123456
          minLength: 1
          maxLength: 50
        otp:
          type: string
          description: >-
            One-time password received by the end user on the configured
            notification channels.
          example: '222113'
          minLength: 4
          maxLength: 10
    SubWallet:
      type: object
      properties:
        cf_sub_wallet_id:
          type: string
          description: >-
            Unique identifier for the sub-wallet provided in response while
            creating the wallet.
          example: '5432109876543210987'
        name:
          type: string
          description: Name for the sub-wallet.
          example: Gift Wallet
        type:
          type: string
          description: Type of the sub-wallet.
          example: GIFT_PPI
        status:
          type: string
          description: Status of the sub-wallet.
          example: ACTIVE
        balance:
          type: number
          format: double
          description: Current balance of the sub-wallet.
          example: 1500.75
        available_balance:
          type: number
          format: double
          description: Available balance in the sub-wallet.
          example: 1500.75
        funds_on_hold:
          type: number
          format: double
          description: Funds on hold in the sub-wallet.
          example: 0
    BeneDetails:
      type: object
      description: Beneficiary details used for the transfer.
      properties:
        bene_id:
          type: string
          description: Beneficiary ID assigned by Cashfree.
          example: BENE789
        cf_bene_instrument_id:
          type: string
          description: Instrument ID assigned by Cashfree for the beneficiary.
          example: INST123456
        instrument_details:
          $ref: '#/components/schemas/BeneTransferInstrumentDetails'
    Notes:
      type: object
      description: >-
        Optional key-value pairs for any extra information. Keys and values must
        be strings.
      properties:
        example_key:
          type: string
          description: value of the note
          example: example_value
    BeneTransferInstrumentDetails:
      type: object
      description: Instrument details used for the transfer.
      oneOf:
        - type: object
          additionalProperties: false
          properties:
            bank_account_number:
              type: string
              description: Bank account number of the beneficiary.
              example: '1234567890'
            ifsc:
              type: string
              description: IFSC code of the beneficiary's bank.
              example: HDFC0000123
        - type: object
          additionalProperties: false
          properties:
            vpa:
              type: string
              description: Virtual Payment Address (UPI ID) of the beneficiary.
              example: john.doe@paytm
  examples:
    transfer_verify_success_response:
      summary: OTP verified; transfer submitted for processing
      value:
        user_id: USER827364
        wallet_id: WALLET936721
        cf_transfer_id: '8901234567890123456'
        transfer_id: TRANSFER123456
        amount: 500.75
        transfer_mode: NEFT
        sub_wallet:
          cf_sub_wallet_id: '35246543210987654321'
          name: Cashfree payout Wallet
          type: FULL_KYC_PPI
          status: ACTIVE
          balance: 9500.86
          available_balance: 9500.86
          funds_on_hold: 0
        status: PENDING
        status_code: TRANSFER_INITIATED
        bank_ref_no: null
        bene_details:
          bene_id: BENE123
          cf_bene_instrument_id: '35246543210987654323'
          instrument_details:
            bank_account_number: '1234567890'
            ifsc: HDFC0000123
        purpose: BUSINESS
        remarks: Vendor payment
        notes:
          example_key: example_value
        initiated_at: '2025-09-02T10:15:30Z'
        processed_at: null
    transfer_otp_invalid:
      summary: Incorrect OTP
      value:
        code: otp_invalid
        type: validation_error
        message: The provided OTP is incorrect
    transfer_otp_expired:
      summary: Expired OTP
      value:
        code: otp_expired
        type: validation_error
        message: The provided OTP has expired
    transfer_otp_verification_exhausted:
      summary: OTP verification attempts exhausted
      value:
        code: otp_verification_attempt_exhausted
        type: validation_error
        message: Maximum OTP verification attempts exceeded
    transfer_id_missing:
      description: Missing transfer_id
      value:
        type: validation_error
        code: transfer_id_missing
        message: transfer_id parameter missing in the request
  responses:
    Response401:
      description: Unauthorised - Invalid or missing authentication.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/StructuredErrorResponse'
          examples:
            invalidCredentials:
              summary: Invalid client credentials
              value:
                code: authentication_failed
                type: authentication_error
                message: Invalid client ID and client secret combination
    Response403:
      description: Forbidden - Access denied.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/StructuredErrorResponse'
          examples:
            ipNotWhitelisted:
              summary: IP not whitelisted
              value:
                code: ip_not_whitelisted
                type: authentication_error
                message: Authentication error (IP not whitelisted)
    Response429:
      description: Too Many Requests - Rate limit exceeded.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/StructuredErrorResponse'
          examples:
            internalError:
              summary: Internal server error
              value:
                code: too_many_requests_per_operation
                type: rate_limit_error
                message: Rate limit exceeded. Please try again after some time
    Response500:
      description: Internal server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/StructuredErrorResponse'
          examples:
            internalError:
              summary: Internal server error
              value:
                code: internal_server_error
                type: internal_error
                message: An internal error occurred while processing the request
  securitySchemes:
    XClientID:
      type: apiKey
      in: header
      name: x-client-id
      description: >-
        Your unique client identifier issued by Cashfree. You can find this in
        your [Merchant
        Dashboard](https://merchant.cashfree.com/merchants/landing?env=prod).
    XClientSecret:
      type: apiKey
      in: header
      name: x-client-secret
      description: >-
        The secret key associated with your client ID. Use this to authenticate
        your API requests. You can find this in your [Merchant
        Dashboard](https://merchant.cashfree.com/merchants/landing?env=prod).

````