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

# Payin Integration Guide

<Highlight># Payin Integration Guide</Highlight>

## What Are Payins and Why They Matter

Payins enable your application to seamlessly accept fiat payments from your customers' bank accounts, which will be converted to cryptocurrency. Whether you're a developer or a business owner, this guide will help you integrate DollarPe's Payin system.

<Note>
  **Prerequisites:**

  * Ensure you have completed the [authentication setup](/guides/development-and-testing/authentication)
  * Configure your [webhook endpoint](/guides/development-and-testing/webhooks) for real-time updates
  * Review the following guides to ensure compatibility:
    * **[supported geographies](/guides/support/geographies)**
    * **[supported stablecoins and blockchains](/guides/support/stablecoins_and_blockchains)**
    * **[supported fiat methods](/guides/support/fiatMethods)**
    * Verify your users have completed KYC and have at least one verified bank account
</Note>

<Warning>
  **Warning**: Initiate the payin before the quotation expiry time.
</Warning>

## Integration at a Glance

The Payin integration flow for centralized exchanges involves the following key steps:

1. **Fetch Configurations** - Retrieve the basic configuration to understand supported assets, networks, and limits.
2. **Validate user requirements** – Ensure the customer has completed KYC verification and has at least one verified bank account added
3. **Fetch payin limits** – Retrieve payin limits to check daily limits, available limits, and whether Enhanced Due Diligence (EDD) is required.
4. **Fetch exchange rates** – Retrieve the latest cryptocurrency exchange rates
5. **Create a quotation** – Generate a quote for the desired payin amount
6. **Send fiat payment** – Transfer the fiat amount to the provided bank details
7. **Initiate the payin** – Start the payin using the UTR from the fiat payment
8. **Link exchange transfer ID** – Link the exchange transfer ID with the payin.
9. **Monitor transaction status** – Track the progress of the transaction
10. **Handle completion** – Finalize the payin once the transaction is confirmed

## Visual Integration Flow

### Process Flow Diagram

```mermaid theme={null}
%%{init: {'themeVariables': { 'fontSize': '18px', 'nodeWidth': '300', 'nodeHeight': '60' }}}%%
flowchart TD
    Start([Start Process]) --> CheckKYC[Check KYC & Bank Status]
    CheckKYC -->|YES| CheckLimit["Check Payin Limit"]
    CheckKYC -->|NO| AddKYC["Complete KYC & Bank<br/>Verification"]

    AddKYC -->|API Call| KycAPI["/API: /kyc/add-kyc-data/"]
    KycAPI --> CheckKYC

    CheckLimit -->|Limit Available| FetchRate["Fetch Exchange Rate"]
    CheckLimit -->|EDD Required| EDDStep["Complete EDD<br/>(Enhanced Due Diligence)"]
    CheckLimit -->|Limit Exhausted &<br/>EDD Done| LimitError["Show Limit Exhausted/Error"]

    EDDStep -->|API Call| EddAPI["/API: /kyc/add-edd-data"]
    EddAPI --> CheckLimit

    FetchRate -->|API Call| RateAPI["/API: /payin/fetch-rate/"]
    RateAPI --> CreateQuote["Create Quotation"]

    CreateQuote -->|API Call| QuoteAPI["/API: /payin/quotation/"]
    QuoteAPI --> AMLScreening["AML Screening"]

    AMLScreening -->|PASSED| ShowBankDetails["Show Bank Details"]
    AMLScreening -->|FAILED| ContactSupport["Contact Support"]

    ShowBankDetails --> SendFiat["Send Fiat Payment"]
    SendFiat --> InitiatePayin["Initiate Payin with UTR"]

    InitiatePayin -->|API Call| PayinAPI["/API: /payin/initiate/"]
    PayinAPI --> WebhookNotification["Webhook Notification"]
    PayinAPI --> PollStatus["Order Polling"]

    WebhookNotification --> PayinStatus{"Check Payin Status"}
    PollStatus --> PayinStatus

    PayinStatus -->|SUCCESS| PayinDone["Payin Done"]
    PayinStatus -->|FAILED| HandleFail["Handle Failure"]
    PayinStatus -->|PROCESSING| WaitRetry["Recheck Later"]

    HandleFail --> ContactSupport
    PayinDone --> End([End Process])

    classDef startEndNode fill:#dcedc8,stroke:#558b2f,stroke-width:2px,color:#000
    classDef mainNode fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000
    classDef apiNode fill:#f3e5f5,stroke:#8e24aa,stroke-width:2px,color:#000
    classDef stateNode fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#000
    classDef failureNode fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#000
    classDef waitNode fill:#fff8e1,stroke:#ff8f00,stroke-width:2px,color:#000

    class Start,End startEndNode
    class CheckKYC,AddKYC,FetchRate,CreateQuote,AMLScreening,ShowBankDetails,SendFiat,InitiatePayin,HandleFail,ContactSupport,WaitRetry mainNode
    class KycAPI,RateAPI,QuoteAPI,PayinAPI apiNode
    class WebhookNotification,PollStatus waitNode
    class PayinDone stateNode
    class PayinStatus decision
```

### Sequence Diagram: Detailed Process Flow

```mermaid theme={null}
sequenceDiagram
    participant Exchange as Centralized Exchange
    participant API as DollarPe API
    participant Bank as Banking System
    participant Webhook as Webhook System

    Exchange->>API: Check KYC & Bank Status
    API->>Exchange: Return KYC & Bank Status

    alt KYC & Bank Verified
        Exchange->>API: Check Payin Limit
        API->>Exchange: Return Limit Info
        alt Limit Available
            Exchange->>API: Fetch Exchange Rate
            API->>Exchange: Return Current Rate

            Exchange->>API: Create Quotation
            Note over API: Internal AML Screening
            alt AML Passed
                API->>Exchange: Return Bank Details for Payment
            else AML Failed
                API->>Exchange: Return AML Error
                Exchange->>Exchange: Contact Support
            end

            Exchange->>Bank: Send Fiat Payment
            Note over Exchange: Get UTR from Bank

            Exchange->>API: Initiate Payin with UTR
            API->>Exchange: Payin Created with payin_id

            alt Successful Transaction
                API->>Bank: Verify Payment
                Bank->>API: Payment Verified

                API->>Webhook: Send Status Update (COMPLETED)
                Webhook->>Exchange: Webhook Notification (COMPLETED)

                Exchange->>API: Poll for Status Updates (optional)
                API->>Exchange: Status: COMPLETED
            else Failed Transaction
                API->>Bank: Payment Verification Failed

                API->>Webhook: Send Status Update (FAILED)
                Webhook->>Exchange: Webhook Notification (FAILED)

                Exchange->>API: Poll for Status Updates (optional)
                API->>Exchange: Status: FAILED
                Exchange->>Exchange: Handle Error & Notify User
            end
        else EDD Required
            Exchange->>API: Complete EDD (Enhanced Due Diligence)
            API->>Exchange: EDD Result
            Exchange->>API: Check Payin Limit (again)
        else Limit Exhausted & EDD Done
            API->>Exchange: Show Limit Exhausted/Error (No further payins allowed)
        end
    else KYC & Bank Not Verified
        API->>Exchange: KYC/Bank Verification Required
        Exchange->>Exchange: Complete KYC & Bank Verification
    end
```

## Step-by-Step Integration Guide

### Step 1: Fetch Configurations

Before starting the integration, fetch the basic configuration to understand supported assets, networks, and limits:

<Tabs>
  <Tab title="API Request">
    ```javascript theme={null}
    GET /payin/configuration
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
    "status": true,
    "message": "Success",
    "data": {
      "inr": {
        "supported_assets": [
          "usdt",
          "usdc"
        ],
        "coin_limits": {
          "usdt": {
            "imps": {
              "min": 28,
              "max": 5563
            },
            "upi": {
              "min": 28,
              "max": 1113
            }
          },
          "usdc": {
            "imps": {
              "min": 28,
              "max": 5563
            },
            "upi": {
              "min": 28,
              "max": 1113
            }
          }
        },
        "required_risk_parameters": [
          "ip_address",
          "device_id",
          "suspicious_activity_report",
          "law_enforcement_agency_report"
        ]
      }
    }
    }
    ```
  </Tab>
</Tabs>

**Key Fields:**

* `supported_fiats`: List of supported fiat currencies
* `supported_assets`: List of supported cryptocurrencies
* `supported_networks`: List of supported blockchain networks
* `coin_limits`: Minimum and maximum limits for each supported cryptocurrency

<Tip>
  If you are storing these configurations in your application to validate user
  inputs and display appropriate options, make sure to update this data
  periodically.
</Tip>

### Step 2: Check Customer KYC and Bank Account status

Before initiating any payin, ensure the customer is KYC-verified and has a verified bank account.

<Tabs>
  <Tab title="Fetch Customer Info">
    ```javascript theme={null}
    GET /customer/{customer_id}
    Response:
    {
        "status": true,
        "message": "Success",
        "data": {
            "id": "8da49e5e-33d1-48b2-b107-eb34f851b2fd",
            "client_reference_id": "client_id_1",
            "full_name": "John Doe",
            "email": "john@example.com",
            "phone": "+911234123412",
            "country": "IND",
            "type": "INDIVIDUAL",
            "status": "UNVERIFIED",
            "failure_reason": null
        }
    }
    ```
  </Tab>

  <Tab title="Fetch Bank Account Info">
    ```javascript theme={null}
    GET /bank/list/{customer_id}
    {
      "status": true,
      "message": "Success",
      "data": {
        "count": 1,
        "next": null,
        "previous": "<url>",
        "results": [
          {
            "id": "4e6f1b20-a73c-11ec-b909-0242ac120002",
            "customer_id": "550e8400-e29b-41d4-a716-446655440000",
            "account_number": "123456789012",
            "ifsc_code": "ABC123456",
            "vpa": "testing@upi",
            "bank_account_type": "ACCOUNT_DETAILS",
            "bank_account_status": "VERIFIED"
          }
        ]
      }
    }
    ```
  </Tab>
</Tabs>

### Step 3: Check Payin Limit

Before creating a quotation, check the customer's available payin limit to ensure they are eligible to create a new order.

<Tabs>
  <Tab title="API Request">
    ```javascript theme={null}
    GET /payin/limit/{customer_id}
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "status": true,
      "message": "Success",
      "data": {
        "daily_limit": 20000,
        "available_limit": 20000,
        "payment_method_limits": {
            "per_transaction_limit": {
                "UPI": 20000,
                "IMPS": 20000
            },
            "total_available_limit": {
                "UPI": 20000,
                "IMPS": 20000
            }
        },
        "full_limit_reset_timestamp": "2024-03-13T10:00:00Z",
        "is_edd_required": false,
        "is_limit_increase_available": true
      }
    }
    ```
  </Tab>
</Tabs>

**Key Fields:**

* `daily_limit`: Maximum daily payin limit for the asset
* `available_limit`: Remaining available payin limit for the current day
* `limit_reset_timestamp`: Unix timestamp when the daily limit will reset
* `is_edd_required`: Whether Enhanced Due Diligence (EDD) is required (true or false)
* `is_limit_increase_available`: Whether the customer can apply for a higher daily limit

**How to use:**

* If `is_limit_increase_available` is sufficient for the intended transaction and `is_edd_required` is false, proceed to the next step.
* If `is_edd_required` is true and the limit is not available, direct the user to complete EDD as part of the KYC process before proceeding. After EDD, recheck the limit.
* If `is_edd_required` is false and the limit is not available (i.e., user has already completed EDD and limit is still exhausted), do not allow the user to create a new payin order and show an appropriate error message. No further action is possible until the limit resets.

### Step 4: Fetch Exchange Rate

Get the real-time exchange rate for a given crypto asset.

<Tabs>
  <Tab title="API Request">
    ```javascript theme={null}
    GET /payin/fetch-rate
    {
      "asset": "usdt",
      "fiat": "inr",
    }
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "status": true,
      "message": "Success",
      "data": {
        "asset": "USDT",
        "fiat": "INR",
        "rate": 87.2
      }
    }
    ```
  </Tab>
</Tabs>

**Key Fields:**

* `asset`: Cryptocurrency to be received (e.g., "USDT", "USDC")
* `fiat`: Fiat currency to send (e.g., "INR" for Indian Rupee)
* `rate`: Current exchange rate (amount of fiat per 1 unit of crypto)

<Tip>
  Rates fluctuate constantly based on market conditions. We recommend fetching a
  new rate before each transaction to ensure accuracy.
</Tip>

### Step 5: Create a Quotation

After getting the current rate, create a quotation to lock in the rate.

<Tabs>
  <Tab title="API Request">
    ```javascript theme={null}
    POST /payin/quotation
    {
        "asset": "USDC",
        "fiat": "INR",
        "sending_amount": "10000",
        "customer_id": "8da49e5e-33d1-48b2-b107-eb34f851b2fd",
        "bank_id": "8da49e5e-33d1-48b2-b107-eb34f851b2fd",
        "payment_method": "IMPS",
        "risk_parameters": {
            "ip_address": "127.0.0.1",
            "device_id": "",
            "suspicious_activity_report": "True",
            "law_enforcement_agency_report": "False"
        }
    }
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "status": true,
      "message": "Success",
      "data": {
          "id": "da43453c-f854-42ac-9a1e-619b37060bbc",
          "customer_id": "8da49e5e-33d1-48b2-b107-eb34f851b2fd",
          "bank_id": "8da49e5e-33d1-48b2-b107-eb34f851b2fd",
          "asset": "USDC",
          "fiat": "INR",
          "payment_method": "IMPS",
          "sending_amount": "10000.00000000",
          "rate": "91.91",
          "receiving_amount": "108.80",
          "quotation_fee": {
              "client_fee": "0.00",
              "client_fee_usdt": "0.00",
              "dollarpe_fee": "0.00",
              "pg_fee": "0.00",
              "client_gst": "0.00",
              "client_gst_usdt": "0.00",
              "dollarpe_gst": "0.00",
              "pg_gst": "0.00",
              "tds": "0",
              "gross_effective_exchange_rate": "91.91"
          },
          "deposit_instructions": {
              "account_number": "1234567890",
              "ifsc": "1234567890",
              "account_name": "Sandbox Technologies Pvt Ltd"
          },
          "created_at": "2025-04-17T14:10:27.567448+00:00",
          "expiry_time": "2025-04-17T14:20:27.566842+00:00"
      }
    }
    ```
  </Tab>
</Tabs>

**Key Fields:**

* `asset`: Cryptocurrency to be received
* `fiat`: Fiat currency to send (e.g., "INR" for Indian Rupee)
* `receiving_amount`: Amount in cryptocurrency to receive
* `customer_id`: ID of the KYC-verified customer
* `bank_id`: ID of the verified bank account
* `bank_details`: Bank account details for sending the fiat payment
* `expiry_time`: Time until the quotation expires

<Note>You must complete your transaction before this time expires.</Note>

### Step 6: Send Fiat Payment

Once you have the quotation and bank details, instruct the customer to send the fiat payment:

1. Use the provided bank account details to make the payment
2. Ensure the exact amount is sent as specified in the quotation
3. Keep the UTR (Unique Transaction Reference) from the bank
4. Complete the payment before the quotation expires

### Step 7: Initiate the Payin

After the fiat payment is completed, create a payin request with the UTR:

<Tabs>
  <Tab title="API Request">
    ```javascript theme={null}
    POST /payin/initiate
    {
      "quotation_id": "2e104290-07c8-49f1-a5ca-0d27f0078f8a",
      "customer_id": "def8b740-99f9-4cba-bc9e-99de57e927b4",
      "client_reference_id": "testUser123",
      "utr": "UTR123456789"
    }
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "status": true,
      "message": "Success",
      "data": {
          "id": "9e67356c-cf5e-4fa2-958f-411e7607a307",
          "customer_id": "8da49e5e-33d1-48b2-b107-eb34f851b2fd",
          "quotation_id": "da43453c-f854-42ac-9a1e-619b37060bbc",
          "client_reference_id": "payin_first_test_3",
          "utr": "ICICRC20250110C9876546",
          "status": "PROCESSING",
          "created_at": "2025-04-17T14:11:35.504428Z",
          "asset": "USDC",
          "fiat": "INR",
          "payment_method": "IMPS",
          "sending_amount": 10000.0,
          "dollarpe_rate": 91.91,
          "receiving_amount": 108.8,
          "deposit_instructions": {
              "ifsc": "1234567890",
              "account_number": "1234567890",
              "account_name": "Sandbox Technologies Pvt Ltd"
          },
          "fees": {
              "client_fee": 0.0,
              "client_fee_usdt": 0.0,
              "dollarpe_fee": 0.0,
              "pg_fee": 0.0,
              "client_gst": 0.0,
              "client_gst_usdt": 0.0,
              "dollarpe_gst": 0.0,
              "pg_gst": 0.0,
              "tds": 0.0,
              "gross_effective_exchange_rate": 91.91
          }
      }
    }
    ```
  </Tab>
</Tabs>

**Key Fields:**

* `quotation_id`: ID received from Step 3
* `customer_id`: ID of the KYC-verified customer
* `client_reference_id`: Your internal reference ID for tracking (optional)
* `bank_id`: ID of the verified bank account
* `utr`: Unique Transaction Reference from the bank payment
* `status`: Current status of the payin

### Step 8: Monitor Transaction Status

After initiating the payin, you need to track the payin status. There are two ways to monitor this status:

#### Option A: Webhook Integration (Recommended)

Webhooks provide real-time updates about payin status changes. Configure your webhook endpoint to receive these notifications:

```javascript theme={null}
// Sample webhook payload for payin status updates
{
  "type": "PAYIN",
  "id": "ac7c5360-0b57-4fb7-88f2-df1c371930ee",
  "event": "COMPLETED", // or "FAILED", "PROCESSING"
  "failure_reason": null, // Contains failure reason if status is "FAILED"
  "timestamp": "2025-03-21T13:37:53.208137Z",
  "data": {
    "utr": "123456789012", // Bank reference number
    "sending_amount": "858.96000000",
    "fiat": "INR",
    "receiving_amount": "10.00000000",
    "asset": "USDT"
  }
}
```

<Tip>
  If using webhooks, ensure your server acknowledges receipt with a 200 OK
  response to prevent duplicate notifications.
</Tip>

#### Option B: Status Polling

If webhooks aren't feasible, you can periodically check the status using the payin endpoint:

<Tabs>
  <Tab title="API Request">
    ```javascript theme={null}
    GET /payin/{payin_id}
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "status": true,
      "message": "Success",
      "data": {
          "id": "ac7c5360-0b57-4fb7-88f2-df1c371930ee",
          "quotation_id": "c9f343b5-ff56-4d52-93af-0962f75242b7",
          "customer_id": "8da49e5e-33d1-48b2-b107-eb34f851b2fd",
          "client_reference_id": "payin_first_test",
          "bank_id": "c863b696-7fbd-4b16-b3a7-134aefffb2fe",
          "asset": "USDT",
          "network": "BSC",
          "fiat": "INR",
          "sending_amount": "858.96000000",
          "rate": "87.20000000",
          "receiving_amount": "10.00000000",
          "fees": {
              "client_fee": "",
              "dollarpe_fee": "",
              "pg_fee": "",
              "client_gst": "",
              "dollarpe_gst": "",
              "pg_gst": "",
              "tds": "",
              "gross_exchange_rate": ""
          },
          "utr": "123456789012",
          "status": "PROCESSING",
          "failure_reason": "",
          "created_at": "2025-03-21T13:37:53.208137Z",
          "updated_at": "2025-03-21T13:37:53.208142Z"
      }
    }
    ```
  </Tab>
</Tabs>

<Tip>
  If using the polling approach, we recommend checking no more frequently than
  once every 60 seconds to avoid API rate limits.
</Tip>

**Possible Status Values:**

* `PROCESSING`: Initial state, waiting for payment verification
* `SUCCESS`: Payin has been successfully completed
* `FAILED`: Payin has failed and failure\_reason is updated

### Step 9: Handle Transaction Completion

#### Successful Transactions

When a payin is completed successfully:

1. Update your internal records with the transaction details
2. Credit the cryptocurrency to your user's account
3. Notify your user that the funds have been received
4. Store the transaction details for future reference and customer support

### Step 10: Link Exchange Order ID with Exchange Transfer ID

Upon successful payin, ensure the exchange transfer ID (associated with the sent cryptocurrency) is linked to the corresponding exchange order ID.

<Tabs>
  <Tab title="API Request">
    ```javascript theme={null}
    PATCH /payin/update-transfer-id
    {
      "payin_id": "c9f343b5-ff56-4d52-93af-0962f75242b7",
      "exchange_transfer_id": "9282391023212"
    }
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "status": true,
      "message": "Success",
      "data": {
          "payin_id": "c9f343b5-ff56-4d52-93af-0962f75242b7",
          "exchange_transfer_id": "9282391023212"
      }
    }
    ```
  </Tab>
</Tabs>

## Testing Your Integration

### Sandbox Environment

Before going live, test your integration thoroughly in our sandbox environment:

1. Use the base URL: `https://sandbox-api.dollarpe.xyz`
2. Follow the same steps as production
3. Test both successful and failed transaction scenarios

<Tip>
  In the sandbox environment, you can simulate different failure scenarios by
  using specific test values. Refer to our [Sandbox Testing
  Guide](/guides/sandbox-testing) for details.
</Tip>

## Getting Help

If you encounter any issues with your payin integration:

* Check our [API documentation](/api-reference-exchange/overview/introduction) for detailed endpoint information
* Visit the [Troubleshooting Guide](/guides/faq) for common solutions
* Contact our [support team](mailto:support@dollarpe.xyz) with your customer\_id and transaction logs

<Note>
  Our support team is available 24/7 to help with integration issues. For urgent
  matters, use the in-app chat or call our technical support hotline.
</Note>
