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

# Create Transaction

> Create a new transaction (sell, pool settlement, or buy)

# Create Transaction

Creates a new transaction. The `type` parameter determines the flow.

See the [Transaction Lifecycle](/guides/transaction-lifecycle) guide for status flows and the [Pool Settlement](/guides/pool-settlement) guide for the two-step pool workflow.

<Warning>
  **Idempotency Required**: Include an `Idempotency-Key` header (UUID) to prevent duplicate transactions. See [Idempotency](/guides/idempotency) for details.
</Warning>

## Headers

<ParamField header="Idempotency-Key" type="string" required>
  A unique UUID for each transaction. One key = one transaction.
</ParamField>

## Body Parameters

<ParamField body="type" type="string" required>
  Transaction type: `sell`, `pool_settlement`, or `buy`. (`payout` is an accepted alias for `pool_settlement`.)
</ParamField>

<ParamField body="userId" type="string" required>
  The user ID. Must have completed KYC when KYC is enforced on your account.
</ParamField>

<ParamField body="amountInr" type="string" required>
  **`pool_settlement` only.** Gross INR to disburse from your escrow balance. TDS (if enabled) is withheld from this — the user receives the net.
</ParamField>

<ParamField body="amount" type="string" required>
  **`sell` only.** Amount in stablecoin units (e.g., "100").
</ParamField>

<ParamField body="asset" type="string" required>
  **`sell` only.** Stablecoin: `USDC` or `USDT`
</ParamField>

<ParamField body="network" type="string" required>
  **`sell` only.** Blockchain: `polygon`, `ethereum`, `arbitrum`, `base`, `tron`
</ParamField>

<ParamField body="partnerReference" type="string">
  Your internal reference ID. For `pool_settlement`, this is also a **business idempotency key**: retrying with the same `partnerReference` returns the original payout and never sends a second transfer.
</ParamField>

<ParamField body="metadata" type="object">
  Custom key-value metadata
</ParamField>

## Request

<Tabs>
  <Tab title="sell">
    ```bash theme={null}
    curl -X POST https://api.stablepay.global/v2/transactions \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
      -d '{
        "type": "sell",
        "userId": "usr_abc123",
        "amount": "100",
        "asset": "USDT",
        "network": "ethereum",
        "partnerReference": "order_456"
      }'
    ```

    <Note>
      Only available on accounts with `transactionMode: sell` or `transactionMode: both`.
    </Note>
  </Tab>

  <Tab title="pool_settlement">
    ```bash theme={null}
    curl -X POST https://api.stablepay.global/v2/transactions \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
      -d '{
        "type": "pool_settlement",
        "userId": "usr_abc123",
        "amountInr": "100000",
        "partnerReference": "disbursal_789"
      }'
    ```

    <Note>
      Disburses INR from your escrow balance to a user's verified bank account. **Single call** — the payout is initiated immediately; there is no separate step. See [Pool Settlement](/guides/pool-settlement) for how the balance is funded.

      `type: "payout"` is an accepted alias for the same flow.
    </Note>
  </Tab>
</Tabs>

## Response

<Tabs>
  <Tab title="sell">
    ```json theme={null}
    {
      "success": true,
      "data": {
        "transactionId": "txn_xyz789",
        "type": "sell",
        "status": "deposit_pending",
        "depositAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f3A123",
        "depositNetwork": "ethereum",
        "depositAsset": "USDT",
        "expectedAmount": "100",
        "quote": {
          "exchangeRate": 84.50,
          "feePercent": 0.005,
          "feeInr": "42.25",
          "grossInr": "8450.00",
          "netInr": "8407.75"
        },
        "expiresAt": "2025-06-16T10:30:00Z"
      }
    }
    ```
  </Tab>

  <Tab title="pool_settlement">
    ```json theme={null}
    {
      "success": true,
      "data": {
        "transactionId": "tx-uuid",
        "status": "payout_processing",
        "type": "pool_settlement",
        "amountInr": "100000.00",
        "settlementInr": "99000.00",
        "tds": { "applicable": true, "percent": "1", "amountInr": "1000.00" },
        "recipient": { "bank": "HDFC Bank", "account": "XXXXXX7890", "name": "RAHUL KUMAR" },
        "payout": { "status": "processing", "amountInr": "99000.00", "rail": "imps" }
      }
    }
    ```

    `amountInr` is the **gross** debited from your escrow; `settlementInr` is the **net** the user receives (gross − TDS). A replay of the same `partnerReference` returns the original transaction with `idempotentReplayed: true`. See the [Pool Settlement guide](/guides/pool-settlement) for the payout lifecycle, TDS, and failure handling.
  </Tab>
</Tabs>

## Errors

| Code                          | Description                                                 | Applies To       |
| ----------------------------- | ----------------------------------------------------------- | ---------------- |
| `IDEMPOTENCY_KEY_REQUIRED`    | Missing Idempotency-Key header                              | All              |
| `INVALID_TYPE`                | Invalid transaction type                                    | All              |
| `USER_NOT_FOUND`              | User doesn't exist                                          | All              |
| `KYC_INCOMPLETE`              | User hasn't completed KYC                                   | All              |
| `NO_BANK_ACCOUNT`             | No verified bank account                                    | All              |
| `AMOUNT_TOO_LOW`              | Below minimum (\$10)                                        | sell             |
| `AMOUNT_TOO_HIGH`             | Above maximum (\$50,000)                                    | sell             |
| `PENDING_TRANSACTION_EXISTS`  | User has an active transaction                              | sell             |
| `INVALID_AMOUNT`              | `amountInr` is not a positive number                        | pool\_settlement |
| `AMOUNT_EXCEEDS_IMPS_LIMIT`   | Above the ₹5,00,000 per-transaction IMPS cap                | pool\_settlement |
| `INSUFFICIENT_BALANCE`        | `amountInr` exceeds your available escrow INR balance       | pool\_settlement |
| `DUPLICATE_PARTNER_REFERENCE` | A payout with this `partnerReference` already exists        | pool\_settlement |
| `PAYOUT_FAILED`               | The bank rail rejected the transfer (escrow debit reversed) | pool\_settlement |

<ResponseExample>
  ```json 201 (sell) theme={null}
  {
    "success": true,
    "data": {
      "transactionId": "txn_xyz789",
      "type": "sell",
      "status": "deposit_pending",
      "depositAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f3A123",
      "depositNetwork": "ethereum",
      "depositAsset": "USDT",
      "expectedAmount": "100",
      "quote": {
        "exchangeRate": 84.50,
        "feePercent": 0.005,
        "feeInr": "42.25",
        "grossInr": "8450.00",
        "netInr": "8407.75"
      },
      "expiresAt": "2025-06-16T10:30:00Z"
    }
  }
  ```

  ```json 201 (pool_settlement) theme={null}
  {
    "success": true,
    "data": {
      "transactionId": "tx-uuid",
      "type": "pool_settlement",
      "status": "payout_processing",
      "amountInr": "100000.00",
      "settlementInr": "99000.00",
      "tds": { "applicable": true, "percent": "1", "amountInr": "1000.00" },
      "recipient": { "bank": "HDFC Bank", "account": "XXXXXX7890", "name": "RAHUL KUMAR" },
      "payout": { "status": "processing", "amountInr": "99000.00", "rail": "imps" }
    }
  }
  ```

  ```json 400 (INSUFFICIENT_BALANCE) theme={null}
  {
    "error": "INSUFFICIENT_BALANCE",
    "message": "Amount exceeds available INR balance (₹5000.00)"
  }
  ```

  ```json 400 (KYC_INCOMPLETE) theme={null}
  {
    "error": "KYC_INCOMPLETE",
    "message": "User KYC is not complete"
  }
  ```
</ResponseExample>
