Payments¶
7 endpoint(s).
| Endpoint | Method | Summary | Auth |
|---|---|---|---|
/api/v1/payments/check |
POST |
Check entitlement for a paid product | |
/api/v1/payments/download/{token} |
GET |
Download a paid kundali report (tokenised, no login) | |
/api/v1/payments/lalkitab-pdf |
POST |
Download a paid Lal Kitab report as a PDF | |
/api/v1/payments/order |
POST |
Create Razorpay order | |
/api/v1/payments/status/{order_id} |
GET |
Poll payment status | |
/api/v1/payments/verify |
POST |
Verify Razorpay payment signature & grant entitlement | |
/api/v1/payments/webhook |
POST |
Razorpay webhook receiver |
POST /api/v1/payments/check¶
Check entitlement for a paid product
Returns 200 + {entitled: true} if user has access to product_id, or HTTP 402 with payment instructions if not.
Priority order:
1. JWT in Authorization header — if role=admin, instant entitled.
Otherwise use the JWT's sub (email) for the purchase lookup.
2. Body email field (legacy / frontend-typed value).
Without this JWT path, a signed-in admin visiting a tool page would see the paywall UI because the frontend never put their email in the body.
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string |
yes | Product id ('lalkitab', 'prashna', etc) — mapped to its flag |
email |
any |
no | User email — required for paid-phase check |
Response 422 — HTTPValidationError
Example
curl -X POST 'https://api.example.com/api/v1/payments/check' \
-H 'Authorization: Bearer <API_KEY>'
GET /api/v1/payments/download/{token}¶
Download a paid kundali report (tokenised, no login)
Serve a paid kundali PDF straight from a tokenised link — no login.
The token is "
| Param | In | Type | Required | Description |
|---|---|---|---|---|
token |
path | string | yes |
Response 422 — HTTPValidationError
Example
curl -X GET 'https://api.example.com/api/v1/payments/download/${token}' \
-H 'Authorization: Bearer <API_KEY>'
POST /api/v1/payments/lalkitab-pdf¶
Download a paid Lal Kitab report as a PDF
Regenerate the Lal Kitab report from birth data and stream it back as a
downloadable PDF. Gated on a valid lalkitab purchase (admin JWT bypasses).
Reuses the exact chart-build + orchestrator + HTML path the webhook uses to
email the report, so the download matches the emailed copy byte-for-byte.
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string |
no | |
user_email |
email |
yes | Used to verify a valid purchase exists |
name |
string |
yes | |
date |
string |
yes | YYYY-MM-DD |
time |
string |
yes | HH:MM or HH:MM:SS |
latitude |
number |
yes | |
longitude |
number |
yes | |
timezone |
any |
no | |
place_name |
any |
no | |
gender |
any |
no | |
marital_status |
any |
no | |
lang |
any |
no | Report language: 'en' or 'hi' |
detail_level |
any |
no | 'detailed' or 'standard' |
Response 422 — HTTPValidationError
Example
curl -X POST 'https://api.example.com/api/v1/payments/lalkitab-pdf' \
-H 'Authorization: Bearer <API_KEY>'
POST /api/v1/payments/order¶
Create Razorpay order
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
product_id |
string |
yes | Internal product identifier (e.g. 'pdae_daily', 'karma_one_time') |
amount_paise |
integer |
yes | Amount in smallest currency unit (paise for INR, cents for USD) |
currency |
string |
no | ISO 4217 currency code. INR primary, USD secondary. |
user_email |
email |
yes | Customer email — receipt + lookup key |
report_inputs |
any |
no | Inputs needed to generate the deliverable report (e.g. birth data for kundali). Stored on the payments row so the webhook can build + email the report once payment is captured. Kundali expects: {name, date, time, latitude, longitude, timezone_offset, tier, language}. |
Response 200 — OrderResponse
Example
curl -X POST 'https://api.example.com/api/v1/payments/order' \
-H 'Authorization: Bearer <API_KEY>'
GET /api/v1/payments/status/{order_id}¶
Poll payment status
| Param | In | Type | Required | Description |
|---|---|---|---|---|
order_id |
path | string | yes |
Response 200 — StatusResponse
Example
curl -X GET 'https://api.example.com/api/v1/payments/status/${order_id}' \
-H 'Authorization: Bearer <API_KEY>'
POST /api/v1/payments/verify¶
Verify Razorpay payment signature & grant entitlement
Client-side verification path — frontend calls this immediately after the Razorpay modal returns success. Verifies the HMAC-SHA256 signature using RAZORPAY_KEY_SECRET, then atomically: 1. UPDATEs payments.status='paid' 2. INSERTs user_purchases row (grants entitlement) — idempotent on order_id
Does NOT depend on RAZORPAY_WEBHOOK_SECRET; uses the order/payment-id pair signed with the regular key_secret. Webhook still runs as a redundant path.
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
razorpay_order_id |
string |
yes | |
razorpay_payment_id |
string |
yes | |
razorpay_signature |
string |
yes |
Response 422 — HTTPValidationError
Example
curl -X POST 'https://api.example.com/api/v1/payments/verify' \
-H 'Authorization: Bearer <API_KEY>'
POST /api/v1/payments/webhook¶
Razorpay webhook receiver
Example
curl -X POST 'https://api.example.com/api/v1/payments/webhook' \
-H 'Authorization: Bearer <API_KEY>'