Spaces:
Running
Wallet Management API - Quick Reference
Authentication
All wallet endpoints require JWT authentication. Include the token in the Authorization header:
Authorization: Bearer <your_jwt_token>
The partner_id is automatically extracted from the JWT token - you don't need to provide it in the request body.
Base URL
http://localhost:8000/wallet
Endpoints
1. Create Wallet
POST /wallet/create
Create a new wallet for the authenticated service professional.
Headers:
Authorization: Bearer <jwt_token>
Content-Type: application/json
Request:
{
"initial_balance": 5000.00,
"currency": "INR"
}
Response:
{
"success": true,
"message": "Wallet created successfully",
"data": {
"wallet_id": "550e8400-e29b-41d4-a716-446655440000",
"partner_id": "staff_123",
"balance": 5000.00,
"currency": "INR",
"status": "active",
"last_transaction_at": null,
"created_at": "2024-01-20T10:00:00",
"updated_at": "2024-01-20T10:00:00"
}
}
2. Get My Wallet
GET /wallet/me
Retrieve complete wallet information for the authenticated user.
Headers:
Authorization: Bearer <jwt_token>
Response:
{
"success": true,
"message": "Wallet retrieved successfully",
"data": {
"wallet_id": "550e8400-e29b-41d4-a716-446655440000",
"partner_id": "staff_123",
"balance": 5000.00,
"currency": "INR",
"status": "active",
"last_transaction_at": "2024-01-20T10:30:00",
"created_at": "2024-01-20T10:00:00",
"updated_at": "2024-01-20T10:30:00"
}
}
3. Get My Balance
GET /wallet/balance
Quick endpoint to check current balance for the authenticated user.
Headers:
Authorization: Bearer <jwt_token>
Response:
{
"success": true,
"message": "Balance retrieved successfully",
"data": {
"partner_id": "staff_123",
"balance": 5000.00,
"currency": "INR",
"status": "active"
}
}
4. Create Transaction
POST /wallet/transaction
Add or deduct money from the authenticated user's wallet.
Headers:
Authorization: Bearer <jwt_token>
Content-Type: application/json
Credit Transaction (Add Money):
{
"transaction_type": "credit",
"amount": 1000.00,
"reference_type": "topup",
"reference_id": "TOPUP-2024-001",
"description": "Wallet recharge via UPI",
"metadata": {
"payment_method": "upi",
"upi_id": "user@paytm",
"transaction_ref": "UPI123456"
}
}
Debit Transaction (Deduct Money):
{
"transaction_type": "debit",
"amount": 500.00,
"reference_type": "order",
"reference_id": "ORDER-123",
"description": "Payment for order ORDER-123"
}
Response:
{
"success": true,
"message": "Transaction completed successfully",
"data": {
"transaction_id": "660e8400-e29b-41d4-a716-446655440000",
"wallet_id": "550e8400-e29b-41d4-a716-446655440000",
"partner_id": "staff_123",
"transaction_type": "credit",
"amount": 1000.00,
"balance_after": 6000.00,
"reference_type": "topup",
"reference_id": "TOPUP-2024-001",
"description": "Wallet recharge via UPI",
"metadata": {
"payment_method": "upi",
"upi_id": "user@paytm"
},
"created_at": "2024-01-20T10:30:00"
}
}
Transaction Types:
credit- Add moneydebit- Deduct money
Reference Types:
order- Payment for ordersrefund- Refund from cancelled orderstopup- Manual wallet rechargecommission- Commission earningswithdrawal- Money withdrawal
5. List My Transactions
POST /wallet/transactions/list
Get transaction history for the authenticated user with filters.
Headers:
Authorization: Bearer <jwt_token>
Content-Type: application/json
Request:
{
"transaction_type": "credit",
"reference_type": "topup",
"start_date": "2024-01-01T00:00:00",
"end_date": "2024-12-31T23:59:59",
"limit": 20,
"offset": 0
}
Response:
{
"success": true,
"message": "Transactions retrieved successfully",
"data": {
"transactions": [
{
"transaction_id": "660e8400-e29b-41d4-a716-446655440000",
"wallet_id": "550e8400-e29b-41d4-a716-446655440000",
"partner_id": "staff_123",
"transaction_type": "credit",
"amount": 1000.00,
"balance_after": 6000.00,
"reference_type": "topup",
"reference_id": "TOPUP-2024-001",
"description": "Wallet recharge",
"metadata": {},
"created_at": "2024-01-20T10:30:00"
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total": 45
}
}
}
Admin Endpoints
6. [Admin] Get Wallet by Partner ID
GET /wallet/admin/{partner_id}
Admin endpoint to retrieve any wallet by partner ID.
Headers:
Authorization: Bearer <admin_jwt_token>
Response: Same as "Get My Wallet"
7. [Admin] Update Wallet Status
PATCH /wallet/admin/{partner_id}/status?status={status}
Admin endpoint to change wallet status.
Headers:
Authorization: Bearer <admin_jwt_token>
Query Parameters:
status- New status:active|suspended|closed
Example:
PATCH /wallet/admin/staff_123/status?status=suspended
Status Values:
active- Normal operation (default)suspended- Temporarily disabled, no transactions allowedclosed- Permanently disabled
Error Responses
Unauthorized (Missing/Invalid Token)
{
"detail": "Authorization header missing"
}
Status Code: 401
Wallet Not Found
{
"detail": "Wallet not found. Please create a wallet first."
}
Status Code: 404
Wallet Already Exists
{
"detail": "Wallet already exists for partner_id: staff_123"
}
Status Code: 400
Insufficient Balance
{
"detail": "Insufficient balance. Current: 100.00, Required: 500.00"
}
Status Code: 400
Wallet Not Active
{
"detail": "Wallet is not active. Current status: suspended"
}
Status Code: 400
cURL Examples
Create Wallet
curl -X POST "http://localhost:8000/wallet/create" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"initial_balance": 5000.00
}'
Get My Balance
curl "http://localhost:8000/wallet/balance" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Add Money (Credit)
curl -X POST "http://localhost:8000/wallet/transaction" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transaction_type": "credit",
"amount": 1000.00,
"reference_type": "topup",
"description": "Wallet top-up"
}'
Deduct Money (Debit)
curl -X POST "http://localhost:8000/wallet/transaction" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transaction_type": "debit",
"amount": 500.00,
"reference_type": "order",
"reference_id": "ORDER-123",
"description": "Payment for order"
}'
List My Transactions
curl -X POST "http://localhost:8000/wallet/transactions/list" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"limit": 20,
"offset": 0
}'
JWT Token Structure
Your JWT token should contain the following claims:
{
"partner_id": "staff_123",
"user_id": "staff_123",
"merchant_id": "merchant_456",
"role": "service_professional",
"email": "staff@example.com",
"phone": "+919876543210",
"exp": 1234567890
}
The API will extract partner_id from the token. If partner_id is not present, it will fall back to user_id or staff_id.
Security Notes
- JWT Authentication: All endpoints require valid JWT token
- Encrypted Balance: Wallet balance is encrypted in the database using AES encryption
- Partner Isolation: Users can only access their own wallet data
- Admin Endpoints: Admin endpoints should verify admin role (TODO: implement role check)
- Rate Limiting: Implement rate limiting in production to prevent abuse
Integration Example
Order Payment with Wallet
from app.wallet.services.service import WalletService
from app.wallet.schemas.schema import WalletTransactionRequest
from app.dependencies.auth import get_partner_id
# In your order endpoint
@router.post("/orders/create")
async def create_order(
order_data: OrderCreateRequest,
db: AsyncSession = Depends(get_db),
token_data: dict = Depends(verify_token)
):
partner_id = get_partner_id(token_data)
# Create order
order = await create_order_logic(order_data, partner_id)
# If payment mode is wallet, debit the wallet
if order_data.payment_mode == "wallet":
try:
transaction = await WalletService.create_transaction(
db,
partner_id,
WalletTransactionRequest(
transaction_type="debit",
amount=order.net_amount,
reference_type="order",
reference_id=str(order.order_id),
description=f"Payment for order {order.order_number}",
metadata={
"order_number": order.order_number,
"items_count": len(order.items)
}
)
)
order.payment_status = "paid"
await db.commit()
except ValueError as e:
# Handle insufficient balance
raise HTTPException(status_code=400, detail=str(e))
return order
Refund to Wallet
# When cancelling an order
@router.post("/orders/{order_id}/cancel")
async def cancel_order(
order_id: UUID,
db: AsyncSession = Depends(get_db),
token_data: dict = Depends(verify_token)
):
partner_id = get_partner_id(token_data)
# Get order
order = await get_order_by_id(order_id, partner_id)
# Refund to wallet if paid via wallet
if order.payment_mode == "wallet" and order.payment_status == "paid":
transaction = await WalletService.create_transaction(
db,
partner_id,
WalletTransactionRequest(
transaction_type="credit",
amount=order.net_amount,
reference_type="refund",
reference_id=str(order.order_id),
description=f"Refund for cancelled order {order.order_number}"
)
)
# Cancel order
order.order_status = "cancelled"
order.payment_status = "refunded"
await db.commit()
return order