SolveEase Pay — API Reference
Base URL:
https://pay.solveease.in
All API requests must be made over HTTPS.
Authentication
All /api/v1/* endpoints require a Bearer API key in the Authorization header:
Authorization: Bearer se_live_xxxxxxxxxxxxxxxxxxxxxxxx
API keys are per-tenant and are issued through the admin dashboard or by the platform team.
Endpoints
POST /api/v1/orders
Create a new payment order.
Request Headers
Authorization: Bearer <API_KEY>
Content-Type: application/json
Request Body
{
"amount": 5000,
"currency": "INR",
"customer": {
"name": "Priya Sharma",
"email": "priya@example.com",
"phone": "9876543210"
},
"description": "Mridu AI Pro - Monthly Plan",
"metadata": {
"userId": "usr_abc",
"planId": "pro_monthly"
},
"returnUrl": "https://mridu-ai.com/billing/success",
"webhookUrl": "https://mridu-ai.com/api/payments/webhook"
}
Success Response 201 Created
{
"success": true,
"orderId": "se_ord_cm4xyz123",
"paymentUrl": "https://pay.solveease.in/pay/se_ord_cm4xyz123",
"expiresAt": "2026-08-03T15:05:00.000Z"
}
Error Response 400 Bad Request
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "Invalid customer phone number",
"details": [
{ "field": "customer.phone", "message": "Must be a 10-digit number" }
]
}
GET /api/v1/orders/:orderId
Retrieve the current status of an order.
Request Headers
Authorization: Bearer <API_KEY>
Success Response 200 OK
{
"success": true,
"order": {
"orderId": "se_ord_cm4xyz123",
"status": "PAID",
"amount": 5000,
"currency": "INR",
"customer": {
"name": "Priya Sharma",
"email": "priya@example.com",
"phone": "9876543210"
},
"description": "Mridu AI Pro - Monthly Plan",
"metadata": { "userId": "usr_abc" },
"paidAt": "2026-08-02T15:10:22.000Z",
"createdAt": "2026-08-02T15:05:00.000Z"
}
}
Order Status Values
| Status | Description |
|---|---|
PENDING | Order created, payment not initiated |
ACTIVE | Customer is on the checkout page |
PAID | Payment successful |
FAILED | Payment failed |
EXPIRED | Order expired (24 hours) |
CANCELLED | Order cancelled |
REFUNDED | Payment refunded |
Webhook Events
SolveEase Pay sends webhook events to your configured webhookUrl.
Signature Verification
Every webhook includes an x-solveease-signature header:
x-solveease-signature: sha256=abc123...
Verify using your webhook secret (provided separately from the API key):
import crypto from 'crypto';
function verifyWebhook(body: string, signature: string, secret: string): boolean {
const computed = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computed),
Buffer.from(signature)
);
}
Event: payment.success
{
"event": "payment.success",
"timestamp": "2026-08-02T15:10:22.000Z",
"orderId": "se_ord_cm4xyz123",
"amount": 5000,
"currency": "INR",
"paidAt": "2026-08-02T15:10:22.000Z",
"customer": {
"name": "Priya Sharma",
"email": "priya@example.com",
"phone": "9876543210"
},
"metadata": { "userId": "usr_abc", "planId": "pro_monthly" }
}
Event: payment.failed
{
"event": "payment.failed",
"timestamp": "2026-08-02T15:10:22.000Z",
"orderId": "se_ord_cm4xyz123",
"amount": 5000,
"reason": "Insufficient funds",
"metadata": { "userId": "usr_abc" }
}
Event: payment.expired
{
"event": "payment.expired",
"timestamp": "2026-08-03T15:05:00.000Z",
"orderId": "se_ord_cm4xyz123",
"amount": 5000,
"metadata": { "userId": "usr_abc" }
}
Rate Limits
| Limit | Value |
|---|---|
| Orders per minute per tenant | 100 |
| Status checks per minute per tenant | 300 |
Rate limit headers are included in all responses:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1754132460
Error Codes
| Code | HTTP | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Invalid request body |
UNAUTHORIZED | 401 | Missing or invalid API key |
FORBIDDEN | 403 | Tenant account disabled |
NOT_FOUND | 404 | Order not found or belongs to another tenant |
RATE_LIMIT | 429 | Rate limit exceeded |
CASHFREE_ERROR | 502 | Cashfree API returned an error |
INTERNAL_ERROR | 500 | Unexpected server error |