<!-- ZenPays documentation · https://docs.zenpayz.com/docs/rest-api/endpoints/payments/create-payment-intent -->

# Create Payment Intent

Create a new payment intent to initiate a payment flow.

<EndpointHeader verb="POST" path="/api/v1/payment-intents" />

## Request

### Headers

<ParamTable
  label="Header"
  rows={[
    { name: "Authorization", required: true, desc: "`Bearer {api_key}`" },
    { name: "X-Signature", required: true, desc: "HMAC-SHA256 signature" },
    { name: "X-Timestamp", required: true, desc: "ISO 8601 timestamp" },
    { name: "X-Secret-Salt", required: true, desc: "Secret salt for HMAC validation" },
    { name: "Content-Type", required: true, desc: "`application/json`" },
    { name: "X-Idempotency-Key", desc: "Unique key to prevent duplicates" },
  ]}
/>

### Body Parameters

<ParamTable
  rows={[
    { name: "amount", type: "integer", required: true, desc: "Amount in smallest currency unit (e.g., cents)" },
    { name: "currency", type: "string", required: true, desc: "ISO 4217 currency code (e.g., `USD`, `INR`)" },
    { name: "paymentMethod", type: "string", desc: "Preferred payment method" },
    { name: "customerEmail", type: "string", desc: "Customer email address" },
    { name: "customerPhone", type: "string", desc: "Customer phone number" },
    { name: "customerFirstName", type: "string", desc: "Customer first name" },
    { name: "customerLastName", type: "string", desc: "Customer last name" },
    { name: "customerCountry", type: "string", desc: "ISO country code (e.g., `IN`, `US`)" },
    { name: "description", type: "string", desc: "Payment description" },
    { name: "successUrl", type: "string", desc: "Redirect URL on success" },
    { name: "cancelUrl", type: "string", desc: "Redirect URL on cancel" },
  ]}
/>

```json
{
  "amount": 100,
  "currency": "INR",
  "paymentMethod": "upi",
  "customerEmail": "test@example.com",
  "customerPhone": "+911234567890",
  "customerFirstName": "Test",
  "customerLastName": "Customer",
  "customerCountry": "IN",
  "description": "Test payment"
}
```

### Payment Methods

| Value | Description |
|-------|-------------|
| `credit_card` | Credit card |
| `upi` | UPI (India) |
| `net_banking` | Net banking |
| `crypto` | Cryptocurrency |

:::note
- `credit_card` is currently supported for TWD (Taiwan Dollar) payments. The `customerPhone` field must be a 10-digit number starting with `09` (e.g., `0912345678`).
- `upi` is used for INR (Indian Rupee) payments.
- For crypto payments (USDT, USDC, BTC, ETH, SOL, BNB), the `paymentMethod` field is optional — the system auto-detects the payment method from the crypto currency.
:::

:::tip Try it out
Test payment intent creation interactively using the [API Simulator](https://merchant-sample.zenpayz.com/).
:::

```json
{
  "amount": 100,
  "currency": "INR",
  "paymentMethod": "upi",
  "customerEmail": "test@example.com",
  "customerPhone": "+911234567890",
  "customerFirstName": "Test",
  "customerLastName": "Customer",
  "customerCountry": "IN",
  "description": "Test payment"
}
```

## Response

### Success (201 Created)

```json
{
  "success": true,
  "data": {
    "intentId": "pi_1771910100598_prckpcg01",
    "merchantId": "mer_3630198df5cb479b",
    "customerId": null,
    "amount": 100,
    "currency": "INR",
    "status": "requires_payment_method",
    "description": "Test payment",
    "expiresAt": "2026-02-24T05:20:00.598Z",
    "estimatedCompletionTime": 30000,
    "processingFee": 0,
    "createdAt": "2026-02-24T05:15:00.599Z",
    "metadata": {},
    "paymentPageUrl": "https://checkout.zenpayz.com/pay/pi_1771910100598_prckpcg01?token=pi_1771910100598_secret_csit7h",
    "routingDecision": {
      "reason": "Initial routing - will be optimized with customer intelligence",
      "paymentMethods": ["UPI", "PIX", "FPS"],
      "supportedCountries": ["IN", "BR", "HK"]
    }
  }
}
```

### Error Responses

<ErrorTable
  rows={[
    { code: "INVALID_AMOUNT", status: "400", message: "Amount must be greater than 0" },
    { code: "INVALID_CURRENCY", status: "400", message: "Currency not supported" },
    { code: "UNAUTHORIZED", status: "401", message: "Invalid API key" },
    { code: "LIMIT_EXCEEDED", status: "403", message: "Transaction limit exceeded" },
    { code: "VALIDATION_ERROR", status: "422", message: "Request validation failed" },
  ]}
/>

<CodeRail>

## Examples

<Tabs groupId="language">
  <TabItem value="curl" label="cURL" default>

```bash
curl -X POST https://api.zenpayz.com/api/v1/payment-intents \
  -H "Authorization: Bearer zp_test_xxxxx" \
  -H "X-Timestamp: 2026-02-24T05:15:00.000Z" \
  -H "X-Signature: a1b2c3d4e5f6..." \
  -H "X-Secret-Salt: your_secret_salt" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100,
    "currency": "INR",
    "paymentMethod": "upi",
    "customerEmail": "test@example.com",
    "customerPhone": "+911234567890",
    "customerFirstName": "Test",
    "customerLastName": "Customer",
    "customerCountry": "IN",
    "description": "Test payment"
  }'
```

  </TabItem>
  <TabItem value="javascript" label="JavaScript">

```javascript
const crypto = require('crypto');

const apiKey = process.env.ZENPAYS_API_KEY;
const secretSalt = process.env.ZENPAYS_SECRET_SALT;
const timestamp = new Date().toISOString();

const body = {
  amount: 100,
  currency: 'INR',
  paymentMethod: 'upi',
  customerEmail: 'test@example.com',
  customerPhone: '+911234567890',
  customerFirstName: 'Test',
  customerLastName: 'Customer',
  customerCountry: 'IN',
  description: 'Test payment',
};

const signature = crypto
  .createHmac('sha256', secretSalt)
  .update(timestamp + JSON.stringify(body))
  .digest('hex');

const response = await fetch('https://api.zenpayz.com/api/v1/payment-intents', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'X-Timestamp': timestamp,
    'X-Signature': signature,
    'X-Secret-Salt': secretSalt,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(body),
});

const result = await response.json();
console.log(result.data.intentId); // pi_1771910100598_prckpcg01
console.log(result.data.paymentPageUrl); // checkout URL
```

  </TabItem>
  <TabItem value="python" label="Python">

```python
import hmac
import hashlib
import json
import os
from datetime import datetime
import requests

api_key = os.environ["ZENPAYS_API_KEY"]
secret_salt = os.environ["ZENPAYS_SECRET_SALT"]
timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.000Z")

body = {
    "amount": 100,
    "currency": "INR",
    "paymentMethod": "upi",
    "customerEmail": "test@example.com",
    "customerPhone": "+911234567890",
    "customerFirstName": "Test",
    "customerLastName": "Customer",
    "customerCountry": "IN",
    "description": "Test payment",
}

data = timestamp + json.dumps(body, separators=(",", ":"))
signature = hmac.new(
    secret_salt.encode(),
    data.encode(),
    hashlib.sha256
).hexdigest()

response = requests.post(
    "https://api.zenpayz.com/api/v1/payment-intents",
    headers={
        "Authorization": f"Bearer {api_key}",
        "X-Timestamp": timestamp,
        "X-Signature": signature,
        "X-Secret-Salt": secret_salt,
        "Content-Type": "application/json",
    },
    json=body,
)

result = response.json()
print(result["data"]["intentId"])  # pi_1771910100598_prckpcg01
print(result["data"]["paymentPageUrl"])  # checkout URL
```

  </TabItem>
  <TabItem value="sdk" label="SDK (Recommended)">

```javascript
// JavaScript SDK - handles authentication automatically
const intent = await zenpays.payments.createPaymentIntent({
  amount: 100,
  currency: 'INR',
  paymentMethod: 'upi',
  customerEmail: 'test@example.com',
  customerPhone: '+911234567890',
  customerFirstName: 'Test',
  customerLastName: 'Customer',
  customerCountry: 'IN',
  description: 'Test payment',
});

console.log(intent.intentId); // pi_1771910100598_prckpcg01
console.log(intent.paymentPageUrl); // checkout URL
```

  </TabItem>
</Tabs>

</CodeRail>

## Payment Intent Status

| Status | Description |
|--------|-------------|
| `requires_payment_method` | Awaiting payment method selection |
| `processing` | Payment is being processed |
| `succeeded` | Payment completed successfully |
| `failed` | Payment failed |
| `cancelled` | Payment was cancelled |
| `expired` | Payment intent expired |

## Next Steps

After creating a payment intent:

1. Redirect customer to checkout or confirm payment
2. [Get Payment Intent](/docs/rest-api/endpoints/payments/get-payment-intent) to check status
3. [Confirm Payment](/docs/rest-api/endpoints/payments/confirm-payment) with customer details
4. Set up [Webhooks](/docs/guides/webhooks) for async status updates
