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

# Create Quotation

> Creates a payin quotation that fixes the exchange rate. The quotation ID is valid for a fixed period.

<Prompt description="Create Quotation" actions={["cursor"]}>
  Add the Zapyd "Create Quotation" call (`POST /pis/api/v1/payin/quotation`) to my backend. Creates a payin quotation that fixes the exchange rate. The quotation ID is valid for a fixed period.

  * Sandbox: `POST https://api-sandbox.zapyd.com/pis/api/v1/payin/quotation`
  * Production: `POST https://api.zapyd.com/pis/api/v1/payin/quotation`

  JSON body:

  * `asset` (string, required): The cryptocurrency asset code. Example: `usdt`.
  * `fiat` (string, required): The fiat currency code. Example: `inr`.
  * `sending_amount` (string, required): The amount to be sent. Example: `51`.
  * `customer_id` (string, uuid, required): Customer's unique identifier.
  * `bank_id` (string, uuid, conditional): Required when payment\_method is ACH\_PULL: the VERIFIED linked account from Fetch Bank Accounts, which Zapyd debits. Optional otherwise.
  * `payment_method` (string, required): Payment method valid for the fiat: INR imps or upi; USD ach\_pull, wire or rtp. Limits must be configured for it. Example: `IMPS`.
  * `risk_parameters` (object, required): Send every key listed in required\_risk\_parameters for the fiat in Fetch Configuration. Send `{}` if that list is empty.
  * `network` (string, required): Blockchain network to deliver the crypto on, for example tron or polygon. Example: `tron`.

  Success: HTTP 201, `{status: true, message, data}`. `data`: `id`, `customer_id`, `bank_id`, `asset`, `fiat`, `network`, `payment_method`, `sending_amount` (Fiat amount the customer pays), `rate`, `receiving_amount`, `fees`, `deposit_instructions` (Where the customer sends fiat. For INR: account\_number, ifsc and account\_name. For USD: account\_number, routing\_number, bank\_name, bank\_address, account\_holder\_name and narrative. ACH\_PULL has none. Fields: `deep_link`, `ios_checkout_link`), `created_at`, `expiry_time`.
  Errors (`{status: false, message, err_code, errors}`):

  * 400 `Customer is unverified`: Customer is added but KYC is unverified; Customer does not belong to the organization
  * 400 `Bank account is unverified`: Bank account is not added; Bank account is added but still processing; The account holder's name doesn't match the KYC name; Bank account is linked to another customer
  * 400 `Onramp is disabled`: The customer's KYC doesn't allow payins in their market. In India, payins need an Aadhaar-verified customer
  * 400 `Entered amount is less than minimum transaction amount`: `sending_amount` is below the minimum for the payment method
  * 400 `Entered amount exceeds maximum transaction amount`: `sending_amount` is above the maximum for the payment method
  * 400 `AML SCREENING FAILED`: Customer appears in sanction lists and the Politically Exposed Persons (PEP) database and/or has material adverse media
  * 400 `EDD required`: Suspicious activity or Red Flag Indicator is triggered; Transaction milestone since last EDD is reached; Annual EDD is due or overdue
  * 400 `Daily onramp limit exhausted`
  * 500 `Internal Server Error`
  * 503 `Service unavailable`: Unexpected Error Occurred
    Every endpoint can also return 401 `AUTH_*` (signature, timestamp or key: fix, don't retry), and 429 or 5xx (retry with backoff).

  Rules:

  * Onramp: the user pays fiat and Zapyd delivers stablecoins to your organization's delivery wallet for that asset and network. The customer must be `VERIFIED`.
  * Before quoting, call `GET /ren/api/v1/payin/limits/{customer_id}`. If `available_limit` doesn't cover the amount, collect EDD (`POST /ren/api/v1/payin/edd/save`) when `is_edd_required` is true, otherwise block until `full_limit_reset_timestamp`.
  * `payment_method`: INR `IMPS` or `UPI`; USD `ACH_PULL`, `WIRE` or `RTP`. `network` must be in `supported_networks`. `risk_parameters`: send every key the fiat's `required_risk_parameters` lists in the configuration endpoint, usually `ip_address` and `device_id` of the end user plus `suspicious_activity_report` and `law_enforcement_agency_report` (booleans). Send `{}` if the list is empty.
  * `ACH_PULL` debits the account linked through `POST /cms/api/v1/bank/generate-link`, so there are no deposit instructions. Send its `id` from `GET /cms/api/v1/bank/list/{customer_id}` as `bank_id` once it's `VERIFIED`.
  * The rate is locked until `expiry_time`. Show the user `deposit_instructions`, the exact `sending_amount` and the time left. For UPI, render `deposit_instructions.deep_link` as a QR code or button (`ios_checkout_link` on iOS).
  * Tell the user to pay from an account in their own KYC name, the exact amount, in one transfer. Otherwise the payin is refunded.
  * If no delivery wallet is set up for the asset and network, the call fails with `Not configured for asset: X & network: Y`.
  * Next: `POST /pis/api/v1/payin/initiate` before `expiry_time`.

  Signing (every request):

  * Headers: `X-API-KEY`, `X-TIMESTAMP` (Unix seconds, within 300 s of server time; generate per request) and `X-SIGNATURE`.
  * `X-SIGNATURE` = Base64(HMAC-SHA256(key = API secret, message = apiKey + "|" + timestamp + "|" + canonicalBody)). Base64 of the raw digest, not hex.
  * canonicalBody: the JSON body with keys sorted at every nesting level, no whitespace (separators `,` and `:`), and every non-ASCII character escaped as lowercase `\uXXXX` (Python `json.dumps(body, sort_keys=True, separators=(",", ":"))`). Requests with no body (GET, DELETE) sign `{}`. Query parameters are not signed.
  * Send the exact canonicalBody string you signed as the request body, with `Content-Type: application/json`.
  * Test vector: key `3f1b2c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d`, secret `test-secret-do-not-use`, timestamp `1735689600`. Signing `{}` gives `6sCtVSRQjU9+2/af8gdwUAvY1l6Ii6ENcbRfanPkhY0=`. Body `{"customer_id":"78c99d71-f28f-47a9-8302-93b286efbe0e","amount":100.5,"currency":"INR","meta":{"note":"Café","b":2,"a":1}}` gives `l+DvQrzlKbsOSxSYOdWoWHEehcFRZfDJPKlLDkm2cSI=`.

  Deliver:

  1. A typed `createPayinQuotation` function in this codebase's language and HTTP client. Reuse an existing Zapyd client and signer, or write one small shared client.
  2. Config from `ZAPYD_API_KEY`, `ZAPYD_API_SECRET` and `ZAPYD_BASE_URL`. The secret stays on the server, never in a browser or app.
  3. Return `data`. When `status` is false, throw an error with the HTTP status, `err_code`, `message` and `errors`. Don't show raw errors to end users.
  4. Retry only 429 and 5xx: exponential backoff from 1 s, capped at 30 s, at most 5 attempts.
  5. Amounts as strings. Types for every field above.
  6. Tests: the signer against the test vector, and this call against sandbox.

  Reference: `https://docs.zapyd.com/api-reference-exchange/endpoint/payin/quotation/quotation.md`
</Prompt>

<Note>
  The customer must be `VERIFIED`. Check their limit with [Payin Limits](/api-reference-exchange/endpoint/payin/config/edd-limits-\{customer_id}) before quoting.
</Note>

## Payment methods by currency

`fiat` and `payment_method` pick the market and the rail. `deposit_instructions` in the response follow the rail.

| `fiat` | `payment_method` | `bank_id` | How the user pays |
| - | - | - | - |
| `INR` | `IMPS` | Optional | Bank transfer to the account in `deposit_instructions` |
| | `UPI` | Optional | Any UPI app: open `deposit_instructions.deep_link`, or `ios_checkout_link` on iOS. See [UPI QR codes](/guides/country-guides/india/qr-integration) |
| `USD` | `ACH_PULL` | Required | Nothing to do: Zapyd debits the account linked with [Generate Bank Link](/api-reference-exchange/endpoint/bank/generate-link) |
| | `WIRE` | Optional | Wire to the account and routing number in `deposit_instructions` |
| | `RTP` | Optional | Instant transfer to the account and routing number in `deposit_instructions` |

When sent, `bank_id` is a `VERIFIED` account from [Fetch Bank Accounts](/api-reference-exchange/endpoint/bank/list-\{customer_id}).

## After quoting

1. Show the user `deposit_instructions`, the exact `sending_amount` and the time left before `expiry_time`.
2. The user pays from an account in their own KYC name, the exact amount, in one transfer. Otherwise the payin is refunded.
3. Call [Create Payin](/api-reference-exchange/endpoint/payin/order/initiate) before `expiry_time`.

## Error Codes and Messages

| API Status Code | Response | Reason |
| - | - | - |
| 400 | Customer is unverified | Customer is added but KYC is unverified |
| 400 | Customer is unverified | Customer does not belong to the organization |
| 400 | Bank account is unverified | Bank account is not added |
| 400 | Bank account is unverified | Bank account is added but still processing |
| 400 | Bank account is unverified | The account holder's name doesn't match the KYC name |
| 400 | Bank account is unverified | Bank account is linked to another customer |
| 400 | Onramp is disabled | The customer's KYC doesn't allow payins in their market. In India, payins need an Aadhaar-verified customer |
| 400 | Entered amount is less than minimum transaction amount | `sending_amount` is below the minimum for the payment method |
| 400 | Entered amount exceeds maximum transaction amount | `sending_amount` is above the maximum for the payment method |
| 400 | AML SCREENING FAILED | Customer appears in sanction lists and the Politically Exposed Persons (PEP) database and/or has material adverse media |
| 400 | EDD required | Suspicious activity or Red Flag Indicator is triggered |
| 400 | EDD required | Transaction milestone since last EDD is reached |
| 400 | EDD required | Annual EDD is due or overdue |
| 400 | Daily onramp limit exhausted | Daily onramp limit exhausted |
| 500 | Internal Server Error | Internal Server Error |
| 503 | Service unavailable | Unexpected Error Occurred |


## OpenAPI

````yaml POST /payin/quotation
openapi: 3.1.0
info:
  title: Zapyd API
  description: API for Zapyd - Customer, Payout, and Webhook services
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api-sandbox.zapyd.com/pos/api/v1
    description: Payout API Base URL
    variables:
      base_url:
        default: https://api-sandbox.zapyd.com
  - url: https://api-sandbox.zapyd.com/cms/api/v1
    description: Customer API Base URL
    variables:
      base_url:
        default: https://api-sandbox.zapyd.com
security:
  - ApiKeyAuth: []
    TimestampAuth: []
    SignatureAuth: []
tags:
  - name: Customer
    description: Customer related operations
    x-displayName: Customer
    x-traitTag: true
  - name: Payout
    description: Payout related operations
  - name: Webhooks
    description: Webhook related operations
  - name: Widget
    description: Hosted buy/sell widget session initialization
paths:
  /payin/quotation:
    post:
      tags:
        - Payin
      description: >-
        Create a payin quotation: locks the fiat-to-crypto rate until
        expiry_time and returns deposit_instructions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - asset
                - fiat
                - sending_amount
                - customer_id
                - payment_method
                - risk_parameters
                - network
              properties:
                asset:
                  type: string
                  description: The cryptocurrency asset code
                  example: usdt
                fiat:
                  type: string
                  description: The fiat currency code
                  example: inr
                sending_amount:
                  type: string
                  description: The amount to be sent
                  example: '51'
                customer_id:
                  type: string
                  format: uuid
                  description: Customer's unique identifier
                  example: def8b740-99f9-4cba-bc9e-99de57e927b4
                bank_id:
                  type: string
                  format: uuid
                  description: >-
                    Required when payment_method is ACH_PULL: the VERIFIED
                    linked account from Fetch Bank Accounts, which Zapyd debits.
                    Optional otherwise.
                  example: 4e6f1b20-a73c-11ec-b909-0242ac120002
                payment_method:
                  type: string
                  example: IMPS
                  description: >-
                    Payment method valid for the fiat: INR imps or upi; USD
                    ach_pull, wire or rtp. Limits must be configured for it.
                risk_parameters:
                  type: object
                  properties:
                    ip_address:
                      type: string
                      example: 127.0.0.1
                      description: End user's IP address (IPv4 or IPv6).
                    device_id:
                      type: string
                      description: End user's device identifier.
                    suspicious_activity_report:
                      type: boolean
                      example: false
                      description: >-
                        true if you have filed a suspicious activity report on
                        this user.
                    law_enforcement_agency_report:
                      type: boolean
                      example: false
                      description: true if a law enforcement agency has reported this user.
                  description: >-
                    Required. Send every key listed in required_risk_parameters
                    for the fiat in Fetch Configuration. Send {} if that list is
                    empty.
                network:
                  type: string
                  description: >-
                    Blockchain network to deliver the crypto on, for example
                    tron or polygon.
                  example: tron
      responses:
        '201':
          description: Quotation created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Success
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        example: 6a1c0e7e-2b53-4f7e-9d2f-6d6e2b1c9a10
                        format: uuid
                      customer_id:
                        type: string
                        example: 84737c7d-7b62-4204-80d6-80f6ecb3ceb4
                        format: uuid
                      bank_id:
                        type:
                          - string
                          - 'null'
                        format: uuid
                        example: cab47575-bbcb-4294-81a3-30774104f3b6
                      asset:
                        type: string
                        example: USDT
                      fiat:
                        type: string
                        example: INR
                      network:
                        type: string
                        description: Network
                        example: tron
                      payment_method:
                        type: string
                        example: IMPS
                      sending_amount:
                        type: string
                        description: Fiat amount the customer pays
                        example: '10000.00'
                      rate:
                        type: string
                        example: '91.91'
                      receiving_amount:
                        type: string
                        description: Crypto amount delivered
                        example: '108.80'
                      fees:
                        type: object
                        properties:
                          client_fee_fiat:
                            type: number
                            format: float
                            example: 450
                          client_fee_crypto:
                            type: number
                            format: float
                            example: 5
                          zapyd_fee:
                            type: number
                            format: float
                            example: 450
                          pg_fee:
                            type: number
                            format: float
                            example: 18
                          client_gst_fiat:
                            type: number
                            format: float
                            example: 81
                          client_gst_crypto:
                            type: number
                            format: float
                            example: 0.9
                          zapyd_gst:
                            type: number
                            format: float
                            example: 81
                          pg_gst:
                            type: number
                            format: float
                            example: 81
                          tds:
                            type: number
                            format: float
                            example: 889.17
                          gross_effective_exchange_rate:
                            type: number
                            format: float
                            example: 88.92
                      deposit_instructions:
                        type: object
                        properties:
                          account_number:
                            type: string
                            example: '1234567890'
                          ifsc:
                            type: string
                            example: SBIN0000001
                          account_name:
                            type: string
                            example: Sandbox Technologies Pvt Ltd
                          deep_link:
                            type: string
                            example: upi://pay?pa=testing-payin@ybl&am=1000
                          ios_checkout_link:
                            type: string
                            example: >-
                              https://pay.google.com/upi/deeplink?pa=testing-payin@ybl&am=1000
                        description: >-
                          Where the customer sends fiat. For INR:
                          account_number, ifsc and account_name. For USD:
                          account_number, routing_number, bank_name,
                          bank_address, account_holder_name and narrative.
                          ACH_PULL has none.
                      created_at:
                        type: string
                        example: '2026-09-30T10:00:00Z'
                        format: date-time
                      expiry_time:
                        type: string
                        example: '2026-09-30T10:10:00Z'
                        format: date-time
              examples:
                IMPS:
                  summary: Quotation using IMPS
                  value:
                    status: true
                    message: Success
                    data:
                      id: 2e104290-07c8-49f1-a5ca-0d27f0078f8a
                      customer_id: def8b740-99f9-4cba-bc9e-99de57e927b4
                      bank_id: 4e6f1b20-a73c-11ec-b909-0242ac120002
                      asset: USDT
                      fiat: INR
                      network: tron
                      payment_method: IMPS
                      sending_amount: 1000
                      rate: 91.91
                      receiving_amount: 108.8
                      fees:
                        client_fee_fiat: 450
                        client_fee_crypto: 5
                        zapyd_fee: 450
                        pg_fee: 18
                        client_gst_fiat: 81
                        client_gst_crypto: 0.9
                        zapyd_gst: 81
                        pg_gst: 81
                        tds: 889.17
                        gross_effective_exchange_rate: 88.92
                      deposit_instructions:
                        account_number: '1234567890'
                        ifsc: SBIN0000001
                        account_name: Sandbox Technologies Pvt Ltd
                      created_at: '2025-03-08T07:31:11.163005Z'
                      expiry_time: '2025-03-08T07:36:11.163005Z'
                UPI:
                  summary: Quotation using UPI
                  value:
                    status: true
                    message: Success
                    data:
                      id: 8f888de9-9ac7-42be-9e8e-123456789abc
                      customer_id: def8b740-99f9-4cba-bc9e-99de57e927b4
                      bank_id: 4e6f1b20-a73c-11ec-b909-0242ac120002
                      asset: USDT
                      fiat: INR
                      network: tron
                      payment_method: UPI
                      sending_amount: 500
                      rate: 91
                      receiving_amount: 54.9
                      fees:
                        client_fee_fiat: 250
                        client_fee_crypto: 2.5
                        zapyd_fee: 250
                        pg_fee: 9
                        client_gst_fiat: 45
                        client_gst_crypto: 0.5
                        zapyd_gst: 45
                        pg_gst: 45
                        tds: 389.17
                        gross_effective_exchange_rate: 88.11
                      deposit_instructions:
                        deep_link: upi://pay?pa=testing-payin@ybl&am=1000
                        ios_checkout_link: >-
                          https://pay.google.com/upi/deeplink?pa=testing-payin@ybl&am=1000
                      created_at: '2025-07-14T16:00:00.000Z'
                      expiry_time: '2025-07-14T16:05:00.000Z'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: Bad Request
                  data:
                    type: 'null'
                  err_code:
                    type: string
                    example: REQ_FIELD_MISSING
                  errors:
                    type: object
                    additionalProperties:
                      type: array
                      items:
                        type: string
                    example:
                      amount:
                        - receiving_amount is required
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: Internal Server Error
                  data:
                    type: 'null'
                  err_code:
                    type: string
                    example: SYS_INTERNAL_ERROR
                  errors:
                    type: string
                    example: Unexpected error occurred. Please try again later.
        '503':
          description: Service unavailable
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                    example: false
                  message:
                    type: string
                    example: Service unavailable
                  data:
                    type: 'null'
                  err_code:
                    type: string
                    example: SYS_SERVICE_UNAVAILABLE
                  errors:
                    type: string
                    example: Unexpected error occurred. Please try again later.
      servers:
        - url: https://api-sandbox.zapyd.com/pis/api/v1
          description: Payin API Base URL
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
      description: API Key for authentication
    TimestampAuth:
      type: apiKey
      in: header
      name: X-TIMESTAMP
      description: Current timestamp in seconds since epoch
    SignatureAuth:
      type: apiKey
      in: header
      name: X-SIGNATURE
      description: HMAC SHA256 signature of the request encoded in Base64

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.