Curlec Transfers API

Fund transfers from a merchant, payment, or order to a Linked Account (Route). Supports payment-based splits, direct on-demand transfers, settlement hold controls, and full/partial reversals. INR only, minimum ₹100. Direct transfers support idempotency via X-Transfer-Idempotency header.

OpenAPI Specification

curlec-transfers-api-openapi.yml Raw ↑
openapi: 3.0.0
info:
  title: Razorpay Bills Transfers API
  version: 1.0.0
  description: Razorpay payment gateway APIs for accepting payments, managing orders, processing refunds, payouts, and subscriptions. All amounts are in the smallest currency sub-unit (e.g. paise for INR). Supports 180+ payment methods including UPI, cards, netbanking, wallets, and EMI.
  termsOfService: https://razorpay.com/terms/
  contact:
    name: Razorpay Support
    url: https://razorpay.com/support/
    email: support@razorpay.com
  license:
    name: Proprietary
    url: https://razorpay.com/terms/
  x-logo:
    url: https://razorpay.com/favicon.png
  x-auth-environments:
    test:
      keyPrefix: rzp_test_
      description: Test mode — keys prefixed rzp_test_. Same API endpoint (https://api.razorpay.com/v1). No real money movement. Use test card numbers from https://razorpay.com/docs/payments/payments/test-card-details/.
    live:
      keyPrefix: rzp_live_
      description: Live mode — keys prefixed rzp_live_. Real money movement. Requires KYC and business activation on the Razorpay Dashboard.
servers:
- url: https://api.razorpay.com/v1
  description: Production
security:
- basicAuth: []
- oauth2:
  - read_only
tags:
- name: Transfers
  description: Fund transfers from a merchant, payment, or order to a Linked Account (Route). Supports payment-based splits, direct on-demand transfers, settlement hold controls, and full/partial reversals. INR only, minimum ₹100. Direct transfers support idempotency via X-Transfer-Idempotency header.
paths:
  /payments/{id}/transfers:
    post:
      operationId: createTransfersFromPayment
      summary: Create transfers from a payment
      description: Split a captured payment to one or more Linked Accounts. Amount is deducted from the payment and transferred to the recipient. INR only, minimum ₹100 per transfer.
      tags:
      - Transfers
      parameters:
      - name: id
        in: path
        required: true
        description: Payment ID (pay_*).
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - transfers
              properties:
                transfers:
                  type: array
                  items:
                    type: object
                    required:
                    - account
                    - amount
                    - currency
                    properties:
                      account:
                        type: string
                        description: Linked Account ID (acc_*).
                      amount:
                        type: integer
                        description: Amount in paise. Minimum 10000.
                      currency:
                        type: string
                        enum:
                        - INR
                      notes:
                        $ref: '#/components/schemas/Notes'
                      linked_account_notes:
                        type: array
                        items:
                          type: string
                      on_hold:
                        type: boolean
                      on_hold_until:
                        type: integer
      responses:
        '200':
          description: Transfers created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    type: string
                  count:
                    type: integer
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Transfer'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '429':
          $ref: '#/components/responses/429'
    get:
      operationId: fetchTransfersForPayment
      summary: Fetch transfers for a payment
      description: Retrieve all transfers created from a specific payment.
      tags:
      - Transfers
      parameters:
      - name: id
        in: path
        required: true
        description: Payment ID (pay_*).
        schema:
          type: string
      responses:
        '200':
          description: List of transfers for the payment.
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    type: string
                  count:
                    type: integer
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Transfer'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '429':
          $ref: '#/components/responses/429'
  /transfers:
    post:
      operationId: createDirectTransfer
      summary: Create a direct transfer
      description: Create an on-demand direct transfer from the merchant account to a Linked Account. Requires the Direct Transfer feature to be enabled on the account. Supports idempotency via the X-Transfer-Idempotency header (unique to direct transfers).
      tags:
      - Transfers
      parameters:
      - name: X-Transfer-Idempotency
        in: header
        required: false
        description: Idempotency key for direct transfers. If provided, retrying with the same key within 24 hours returns the original transfer instead of creating a duplicate.
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - account
              - amount
              - currency
              properties:
                account:
                  type: string
                  description: Linked Account ID (acc_*).
                amount:
                  type: integer
                  description: Amount in paise. Minimum 10000 (₹100).
                currency:
                  type: string
                  enum:
                  - INR
                notes:
                  $ref: '#/components/schemas/Notes'
                linked_account_notes:
                  type: array
                  items:
                    type: string
                on_hold:
                  type: boolean
                on_hold_until:
                  type: integer
      responses:
        '200':
          description: Transfer created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transfer'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '429':
          $ref: '#/components/responses/429'
    get:
      operationId: listTransfers
      summary: List transfers
      description: Retrieve a paginated list of transfers. Filter by recipient_settlement_id to fetch transfers included in a specific settlement. Use expand[]=recipient_settlement to include settlement details.
      tags:
      - Transfers
      parameters:
      - name: from
        in: query
        schema:
          type: integer
        description: Unix timestamp filter (start).
      - name: to
        in: query
        schema:
          type: integer
        description: Unix timestamp filter (end).
      - name: count
        in: query
        schema:
          type: integer
          default: 10
          maximum: 100
        description: 'Number of records to return. Default: 10. Maximum: 100.'
      - name: skip
        in: query
        schema:
          type: integer
          default: 0
        description: 'Number of records to skip. Use for pagination. Default: 0.'
      - name: recipient_settlement_id
        in: query
        schema:
          type: string
        description: Filter transfers by settlement ID in the Linked Account.
      - name: expand[]
        in: query
        schema:
          type: string
          enum:
          - recipient_settlement
        description: Expand recipient_settlement to include full settlement object.
      responses:
        '200':
          description: List of transfers.
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    type: string
                  count:
                    type: integer
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Transfer'
        '401':
          $ref: '#/components/responses/401'
        '429':
          $ref: '#/components/responses/429'
  /transfers/{id}:
    get:
      operationId: fetchTransfer
      summary: Fetch a transfer
      description: Retrieve details of a specific transfer by ID.
      tags:
      - Transfers
      parameters:
      - name: id
        in: path
        required: true
        description: Transfer ID (trf_*).
        schema:
          type: string
      responses:
        '200':
          description: Transfer details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transfer'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '429':
          $ref: '#/components/responses/429'
    patch:
      operationId: modifyTransferSettlementHold
      summary: Modify settlement hold on a transfer
      description: Put a transfer's settlement on hold or release an existing hold. Use on_hold=true to hold settlement, on_hold=false to release. on_hold_until sets a future timestamp for automatic hold release.
      tags:
      - Transfers
      parameters:
      - name: id
        in: path
        required: true
        description: Transfer ID (trf_*).
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                on_hold:
                  type: boolean
                  description: true to hold settlement; false to release.
                on_hold_until:
                  type: integer
                  description: Unix timestamp for automatic hold release. null = hold indefinitely until manually released.
      responses:
        '200':
          description: Transfer settlement hold updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Transfer'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '429':
          $ref: '#/components/responses/429'
  /transfers/{id}/reversals:
    post:
      operationId: reverseTransfer
      summary: Reverse a transfer
      description: Move funds from a Linked Account back to the merchant. Partial reversals are supported. Multiple reversals per transfer are allowed as long as the total reversed amount does not exceed the transfer amount.
      tags:
      - Transfers
      parameters:
      - name: id
        in: path
        required: true
        description: Transfer ID (trf_*).
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                  description: Amount to reverse in paise. Omit to reverse the full remaining amount.
                notes:
                  $ref: '#/components/schemas/Notes'
      responses:
        '200':
          description: Reversal created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Reversal'
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '429':
          $ref: '#/components/responses/429'
    get:
      operationId: listReversals
      summary: List reversals for a transfer
      description: Retrieve all reversals for a specific transfer.
      tags:
      - Transfers
      parameters:
      - name: id
        in: path
        required: true
        description: Transfer ID (trf_*).
        schema:
          type: string
      responses:
        '200':
          description: List of reversals.
          content:
            application/json:
              schema:
                type: object
                properties:
                  entity:
                    type: string
                  count:
                    type: integer
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/Reversal'
        '401':
          $ref: '#/components/responses/401'
        '404':
          $ref: '#/components/responses/404'
        '429':
          $ref: '#/components/responses/429'
components:
  schemas:
    Reversal:
      type: object
      description: 'A reversal of a transfer — moves funds back from the Linked Account to the merchant. Partial reversals are supported and multiple reversals per transfer are allowed. Prefix: rvrsl_'
      properties:
        id:
          type: string
          description: 'Reversal ID. Prefix: rvrsl_'
        entity:
          type: string
          enum:
          - reversal
        transfer_id:
          type: string
          description: Transfer ID being reversed (trf_*).
        amount:
          type: integer
          description: Reversed amount in paise.
        currency:
          type: string
          enum:
          - INR
        notes:
          $ref: '#/components/schemas/Notes'
        initiator_id:
          type: string
          description: ID of the entity that initiated the reversal.
        created_at:
          type: integer
    Notes:
      type: object
      description: Key-value pairs for storing custom metadata. Maximum 15 pairs. Each key and value must not exceed 256 characters.
      additionalProperties:
        type: string
      maxProperties: 15
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: 'Error code. Examples: BAD_REQUEST_ERROR, GATEWAY_ERROR, SERVER_ERROR.'
            description:
              type: string
            source:
              type: string
              description: Where the error originated (e.g. business, gateway).
            step:
              type: string
            reason:
              type: string
              description: 'Machine-readable reason. Examples: insufficient_funds, invalid_expiry_date, declined_by_bank.'
            metadata:
              type: object
            field:
              type: string
    Transfer:
      type: object
      description: 'A fund transfer from a merchant or captured payment to a Linked Account (Route). Minimum amount is ₹100 (10000 paise). INR only. Prefix: trf_'
      properties:
        id:
          type: string
          description: 'Transfer ID. Prefix: trf_'
        entity:
          type: string
          enum:
          - transfer
        source:
          type: string
          description: Source entity ID (payment ID, order ID, or merchant account ID for direct transfers).
        recipient:
          type: string
          description: Destination Linked Account ID (acc_*).
        amount:
          type: integer
          description: Transfer amount in paise. Minimum 10000 (₹100).
        currency:
          type: string
          enum:
          - INR
          description: Always INR for transfers.
        amount_reversed:
          type: integer
          description: Total amount reversed so far in paise.
        fees:
          type: integer
          description: Transfer fee charged in paise.
        tax:
          type: integer
          description: GST on transfer fee in paise.
        transfer_status:
          type: string
          enum:
          - created
          - pending
          - processed
          - failed
          - reversed
          - partially_reversed
          description: Transfer processing status.
        settlement_status:
          type: string
          enum:
          - pending
          - on_hold
          - settled
          description: Settlement status of the transferred funds in the Linked Account.
        on_hold:
          type: boolean
          description: If true, settlement of this transfer is on hold.
        on_hold_until:
          type: integer
          description: Unix timestamp until which settlement is on hold. null means indefinite hold.
        recipient_settlement_id:
          type: string
          description: Settlement ID (setl_*) in the Linked Account once settled.
        notes:
          $ref: '#/components/schemas/Notes'
        linked_account_notes:
          type: array
          items:
            type: string
          description: Keys from notes that will be visible to the Linked Account in their dashboard.
        created_at:
          type: integer
        processed_at:
          type: integer
          description: Unix timestamp when the transfer was processed.
  responses:
    '404':
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '400':
      description: Bad request. Invalid parameters or missing required fields.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '401':
      description: Authentication failed. Invalid or missing API key credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    '429':
      description: Rate limit exceeded. Implement exponential backoff with jitter before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: HTTP Basic authentication using your Razorpay API key pair. Use key_id as the username and key_secret as the password. Encode as Base64(key_id:key_secret). Keys are environment-scoped (Test vs Live). Obtain keys at https://dashboard.razorpay.com/app/keys. Keys are case-sensitive.
    oauth2:
      type: oauth2
      description: OAuth 2.0 via the Razorpay MCP server (mcp.razorpay.com). Supports Authorization Code with PKCE (S256) for user-delegated access and Client Credentials for server-to-server access. Tokens expire in 3600 seconds. Dynamic Client Registration available at the registration endpoint. For integration setup see https://razorpay.com/docs/build/llm-docs/mcp-server/oauth.md.
      flows:
        authorizationCode:
          authorizationUrl: https://mcp.razorpay.com/authorize
          tokenUrl: https://mcp.razorpay.com/token
          refreshUrl: https://mcp.razorpay.com/token
          scopes:
            read_only: Read-only access to Razorpay account data (payments, orders, refunds, payouts, subscriptions, invoices)
        clientCredentials:
          tokenUrl: https://mcp.razorpay.com/token
          scopes:
            read_only: Read-only access to Razorpay account data (payments, orders, refunds, payouts, subscriptions, invoices)
externalDocs:
  description: Razorpay API Documentation
  url: https://razorpay.com/docs/api/
x-tagGroups:
- name: Core Payments
  tags:
  - Orders
  - Payments
  - Refunds
  - Payment Downtimes
- name: Payment Collection
  tags:
  - Payment Links
  - QR Codes
- name: Billing & Subscriptions
  tags:
  - Items
  - Invoices
  - Plans
  - Subscriptions
- name: Customer Management
  tags:
  - Customers
  - Documents
- name: Finance & Reconciliation
  tags:
  - Settlements
  - Instant Settlements
  - Disputes
- name: Route & Marketplace
  tags:
  - Linked Accounts
  - Transfers
- name: Smart Collect
  tags:
  - Virtual Accounts
- name: Partners & Onboarding
  tags:
  - Partner Accounts
  - Partner Products
  - Partner Stakeholders
  - Partner Documents
  - Partner Webhooks
- name: Bills
  tags:
  - Bills
- name: RazorpayX
  tags:
  - X Contacts
  - X Fund Accounts
  - X Account Validation
  - X Banking Balances
  - X Payouts
  - X Payout Links
  - X Transactions
x-rateLimit:
  description: Razorpay does not publish specific rate limits. If you receive HTTP 429, implement exponential backoff with jitter and retry. Add randomisation to avoid thundering-herd effects.
  throttleStatus: 429
  strategy: exponential backoff with jitter
x-pagination:
  description: All list endpoints return at most 100 records per call (1000 for settlement recon). Use count and skip together to paginate. Date range filters (from/to) use Unix timestamps in seconds.
  example: GET /payments?from=1700000000&to=1700086400&count=100&skip=100
x-amountEncoding:
  description: 'All monetary amounts are in the smallest currency sub-unit. For INR: 1 rupee = 100 paise, so ₹500 = 50000. Minimum for INR is 100 paise (₹1). Three-decimal currencies (KWD, BHD, OMR): drop last decimal digit. Zero-decimal currencies (JPY): pass value as-is.'