# API changes — September 2026 (new and updated endpoints)

For the customer app, the astrologer app and the web app. This lists every endpoint added or
changed in this round, with URL, request and response. The horoscope flow is covered in more depth
in [horoscope_api.md](horoscope_api.md).

Base URL: `https://<api-host>/api` (local `http://localhost:8080/api`)

| # | Endpoint | Status |
|---|---|---|
| 1 | `GET /user/horoscope/signs`, `GET /astrologer/horoscope/signs` | **New** |
| 2 | `POST /user/horoscope/feedback` | **New** |
| 3 | `POST /astrologer/horoscope/{daily, daily-moon, daily-nakshatra, weekly, yearly}` | **New** |
| 4 | 32 astrologer astrology services: `/astrologer/{kundali, matching, panchang, numerology, tarot}/...` | **New** |
| 5 | `POST /user/horoscope/{daily, daily-moon, daily-nakshatra, weekly, yearly}` | Updated |
| 6 | `GET /astrologer/wallet/transactions` | Updated |
| 7 | All 45 customer astrology service routes | Updated (usage tracking, admin on/off, wallet charging + 402 recharge) |

---

## 0. Common to every call

**Headers**

| Header | Required | Value |
|---|---|---|
| `Authorization` | yes, except public routes | `Bearer <token>`: a customer token for `/user`, an astrologer token for `/astrologer` |
| `Content-Type` | for POST | `application/json` |
| `X-Platform` | recommended | `customer_app`, `web`, `astrologer_app` or `astrologer_web` |
| `X-Device-Type` | recommended | `android`, `ios` or `web` |
| `X-App-Version` | recommended (mobile) | e.g. `3.5.0` |

The three `X-` values may also be sent in any JSON body as `platform`, `device_type` and
`app_version`. A header wins when both are sent. They feed the admin reports (Horoscope, Service
Usage) and never change a response. If they are left out, a browser is detected as `web` and
anything else is counted as the app.

**Envelope** (most endpoints):

```json
{ "status": true,  "message": "...", "data": { ... } }
{ "status": false, "message": "reason" }
```

**Service switched off by the admin.** Any astrology service route can return this when the admin
has disabled the service for your audience at Astrology Services > Settings:

```
HTTP 403
{ "status": false, "message": "This service is currently unavailable." }
```

Hide or grey out the feature when you get it. Do not retry.

**Paid services and the wallet.** The admin sets each service to Free, Free quota (the first *N*
uses per day, month or lifetime are free) or Paid, with a price, at Astrology Services > Settings.
For a signed-in customer:

| Situation | What happens |
|---|---|
| Free, or still within the free quota | Served, `charged: 0` |
| Priced and the wallet covers it | Served; the price is debited once the result is ready, a `wallettransaction` row is written (e.g. `HoroscopeView`, `KundaliMatching`), and the response carries `charged: <amount>` |
| Priced and the wallet does not cover it | **HTTP 402**, nothing is called and nothing is charged (below) |
| The call fails (bad input, provider error) | Nothing is charged, and a free-quota use is not used up |

```
HTTP 402
{
  "status": false,
  "message": "Insufficient wallet balance. Yearly horoscope costs ₹49.00 and your wallet has ₹20.00. Please recharge your wallet to continue.",
  "data": {
    "error_code": "INSUFFICIENT_BALANCE",
    "recharge_required": true,
    "service_code": "horoscope.yearly",
    "service_name": "Yearly horoscope",
    "required_amount": 49,
    "wallet_balance": 20,
    "shortfall": 29
  }
}
```

On a 402 (or `data.error_code = INSUFFICIENT_BALANCE`), show the message and open the wallet recharge
screen, prefilled with at least `shortfall`. After a charged call, refresh the wallet balance.
Astrologers and guests are never charged.

---

## 1. NEW: Sign list

`GET /api/user/horoscope/signs` (public, no token)
`GET /api/astrologer/horoscope/signs` (public, same response)

No request parameters.

```json
{
  "status": true,
  "message": "Horoscope signs fetched successfully.",
  "data": [
    {
      "zodiac": 1,
      "sign_id": 1,
      "name": "Aries",
      "image": "https://dev-admin.astrology.togwe.com/storage/images/sign_11787220687.png",
      "image_path": "storage/images/sign_11787220687.png",
      "svg_image": "<svg xmlns=\"http://www.w3.org/2000/svg\" ...>...</svg>"
    }
  ]
}
```

| Field | Meaning |
|---|---|
| `zodiac` | 1–12 (1 Aries … 12 Pisces). **Send this** to the horoscope endpoints |
| `sign_id` | `hororscope_signs.id`, which skips 2. Display only, never send it as `zodiac` |
| `image` | Full image URL (the admin host comes from `ADMIN_URL`) |
| `image_path` | The stored relative path |
| `svg_image` | Inline SVG markup, or `null`. Web: `data:image/svg+xml;charset=utf-8,` + `encodeURIComponent(svg)`. Flutter: `SvgPicture.string` |

---

## 2. NEW: Horoscope feedback

`POST /api/user/horoscope/feedback` (customer token)

| Field | Type | Required | Notes |
|---|---|---|---|
| `feedbacktype` | string | yes | `Great`, `Average` or `Poor` (case-sensitive) |
| `feedback` | string | no | At most 1000 characters |
| `horoscope_type` | string | no | `daily`, `daily_moon`, `daily_nakshatra`, `weekly` or `yearly` |
| `zodiac` | int | no | 1–12 |
| `platform` | string | no | If not sent as a header |

```json
{ "feedbacktype": "Great", "feedback": "Very accurate", "horoscope_type": "daily", "zodiac": 1 }
```

```json
{ "status": true, "message": "Feedback submitted", "data": null }
```

Saved to `horoscopefeedback`, shown on the admin Horoscope > Feedback screen.

---

## 3. NEW: Astrologer horoscope

Astrologer token. Same bodies and responses as section 5. The astrologer is **never charged**, and
the view is logged against the astrologer.

| Endpoint | Body |
|---|---|
| `POST /api/astrologer/horoscope/daily` | as 5.1 |
| `POST /api/astrologer/horoscope/daily-moon` | as 5.2 |
| `POST /api/astrologer/horoscope/daily-nakshatra` | as 5.3 |
| `POST /api/astrologer/horoscope/weekly` | as 5.4 |
| `POST /api/astrologer/horoscope/yearly` | as 5.5 |

Extra error: `404 { "status": false, "message": "astrologer not found" }` when the token's user has
no astrologer profile.

---

## 4. NEW: Astrologer astrology services

Astrologer token. These are **the customer endpoints under `/api/astrologer`**, with identical
requests and responses (see section 8 for every body). Differences from the customer versions:

- Nothing is ever charged: `charged` is always `0` and no wallet is touched.
- Usage is logged as `ASTROLOGER` in the admin Service Usage report.
- Only services the admin catalogue marks available to astrologers exist here. Saving, listing and
  deleting are customer-only.

| Method | Astrologer endpoint | Request (section 8) |
|---|---|---|
| POST | `/astrologer/kundali/generate` | 8.1 |
| GET | `/astrologer/kundali/chart-image` | 8.2 |
| GET | `/astrologer/kundali/show/:id` | a kundali generated by this astrologer |
| POST | `/astrologer/matching/aggregate` | 8.3 |
| POST | `/astrologer/matching/ashtakoot` | 8.3 |
| POST | `/astrologer/matching/dashakoot` | 8.3 |
| POST | `/astrologer/matching/papasamaya` | 8.3 |
| POST | `/astrologer/matching/rajju-vedha` | 8.3 |
| POST | `/astrologer/matching/nakshatra` | 8.4 |
| POST | `/astrologer/matching/western` | 8.5 |
| POST | `/astrologer/panchang/today` | 8.6 |
| POST | `/astrologer/panchang/monthly` | 8.6 |
| POST | `/astrologer/panchang/choghadiya` | 8.6 |
| POST | `/astrologer/panchang/hora` | 8.6 |
| POST | `/astrologer/panchang/festivals` | 8.6 |
| POST | `/astrologer/panchang/sun-moon` | 8.6 |
| POST | `/astrologer/numerology/report` | 8.7 |
| POST | `/astrologer/numerology/day-number` | 8.8 |
| POST | `/astrologer/numerology/table` | 8.9 |
| POST | `/astrologer/numerology/radical-number` | 8.10 |
| GET | `/astrologer/tarot/cards` | 8.11 |
| GET | `/astrologer/tarot/cards/:id` | 8.11 |
| GET | `/astrologer/tarot/shuffle` | 8.12 |
| POST | `/astrologer/tarot/one-card` | 8.13 |
| POST | `/astrologer/tarot/love` | 8.13 (+ `style`) |
| POST | `/astrologer/tarot/yes-no` | 8.13 |
| POST | `/astrologer/tarot/career` | 8.13 |
| POST | `/astrologer/tarot/three-card` | 8.14 |
| POST | `/astrologer/tarot/love-triangle` | 8.15 |
| POST | `/astrologer/tarot/breakup` | 8.16 |
| GET | `/astrologer/tarot/fortune-cookie` | none |

---

## 5. UPDATED: Customer horoscope

Customer token. **What changed:** each body now also accepts `platform`, `device_type` and
`app_version`; `lang` defaults to `en`; and every view is logged for the admin Horoscope screens.
Responses are unchanged:

```json
{
  "status": true,
  "message": "Daily horoscope fetched successfully.",
  "data": { "charged": 0, "data": { "...": "VedicAstroAPI prediction, unchanged" } }
}
```

`data.charged` is the amount debited (`HoroscopePrice` in systemflag; `0` when free).

### 5.1 `POST /api/user/horoscope/daily`

| Field | Type | Required | Notes |
|---|---|---|---|
| `zodiac` | int | yes | 1–12 |
| `date` | string | no | `YYYY-MM-DD`; today when empty |
| `type` | string | no | `big` (default) or `small` |
| `split` | bool | no | Split the prediction into sections |
| `lang` | string | no | default `en` |

### 5.2 `POST /api/user/horoscope/daily-moon`
`zodiac` (required), `date`, `lang`.

### 5.3 `POST /api/user/horoscope/daily-nakshatra`
`nakshatra` (required, 1–27), `date`, `lang`.

### 5.4 `POST /api/user/horoscope/weekly`
`zodiac` (required), `week` (`thisweek` default or `nextweek`), `show_same` (bool), `lang`.

### 5.5 `POST /api/user/horoscope/yearly`
`zodiac` (required), `year` (current year when omitted), `lang`.

```json
{ "zodiac": 1, "lang": "en", "platform": "customer_app", "device_type": "android", "app_version": "3.5.0" }
```

---

## 6. UPDATED: Astrologer wallet transactions

`GET /api/astrologer/wallet/transactions?page=1&limit=10&type=ALL` (astrologer token)

**What changed:** the list used to show only wallet-ledger entries. It now merges chat, audio call
and video call sessions, Astromall orders and withdrawals, newest first, matching the Figma
Transaction History screen.

| Query | Default | Values |
|---|---|---|
| `page` | 1 | |
| `limit` | 10 | at most 100 |
| `type` | `ALL` | `ALL` · `EARNINGS` (Earnings tab) · `WITHDRAWALS` (Withdrawals tab) · `CHAT` · `CALL` · `AUDIO_CALL` · `VIDEO_CALL` · `ORDER` · `GIFT` · `REPORT` · `REFUND` · `ADMIN` · `SETTLEMENT` |

```json
{
  "status": true,
  "message": "Wallet transactions fetched successfully.",
  "data": {
    "page": 1, "limit": 10, "total": 9,
    "transactions": [
      {
        "id": 3,
        "transactionId": "CON-3",
        "source": "CONSULTATION",
        "referenceId": 3,
        "referenceNo": "CON00003",
        "transactionType": "VIDEO_CALL",
        "category": "EARNING",
        "title": "Video Call Consultation",
        "description": "with Sumit · 5 min",
        "amount": 150, "creditAmount": 150, "debitAmount": 0, "balanceAfter": 0,
        "isCredit": true,
        "status": "Completed", "statusCode": "COMPLETED",
        "icon": "video",
        "settlementStatus": "PENDING",
        "settlementLabel": "Settlement pending",
        "customerName": "Sumit",
        "durationMinutes": 5,
        "transactionDate": "22 Sep 2026",
        "transactionTime": "06:05 PM",
        "transactionDateTime": "22 Sep 2026, 06:05 PM",
        "createdAt": "2026-09-22T18:05:00+05:30"
      }
    ]
  }
}
```

New fields: `transactionId`, `source`, `referenceNo`, `category`, `statusCode`, `settlementStatus`,
`settlementLabel`, `customerName`, `durationMinutes`, `transactionDateTime` and `createdAt`. All
earlier fields are still there.

| `source` | `title` | `status` values |
|---|---|---|
| `CONSULTATION` | Chat / Audio Call / Video Call Consultation | Completed, On Hold, Rejected |
| `ORDER` | Astromall Order | Pending, Processing, Completed |
| `LEDGER` | Withdrawal to Bank / UPI, Gift Received, Report Earnings, Refund, Admin Adjustment, Earning Reversed | Withdrawals: Pending, Processing, Processed, Rejected, Failed. Others: Completed |

- Show `+amount` in green when `isCredit` is true, and `-amount` in red otherwise.
- Key rows on `transactionId`. `id` is unique only within one `source`.
- `settlementLabel` tells the astrologer whether a session's earning has reached the wallet yet.
- **Row tap:** `GET /wallet/transaction/:id` only resolves `LEDGER` rows. Open `CONSULTATION` and
  `ORDER` rows by `referenceId` in their own detail screens.

---

## 7. UPDATED: Customer astrology services (usage tracking)

No request or response changes. Each call is now counted in the admin's Astrology Services > Service
Usage report, and the admin can switch each service off (you then get the 403 from section 0). Send
the section 0 headers so the report can split web, app and device.

| Family | Customer endpoints (all under `/api/user`) | Login |
|---|---|---|
| Kundali | `POST /kundali/generate`, `GET /kundali/chart-image` | public (token optional, credits the user when sent) |
| Kundali | `POST /kundali/add`, `POST /kundali/list`, `GET /kundali/show/:id`, `PUT\|POST /kundali/update/:id`, `DELETE /kundali/delete`, `GET /kundali/download/:id` | required |
| Matching | `POST /matching/{aggregate, ashtakoot, dashakoot, papasamaya, rajju-vedha, nakshatra, western, add, list}`, `GET /matching/show/:id` | required |
| Horoscope | `POST /horoscope/{daily, daily-moon, daily-nakshatra, weekly, yearly}` | required |
| Panchang | `POST /panchang/{today, monthly, choghadiya, hora, festivals, sun-moon}` | required |
| Numerology | `POST /numerology/{report, day-number, table, radical-number}` | required |
| Tarot | `GET /tarot/cards`, `GET /tarot/cards/:id`, `GET /tarot/shuffle`, `POST /tarot/{one-card, three-card, love, love-triangle, yes-no, career, breakup}`, `GET /tarot/fortune-cookie` | public (token optional) |

On the public routes, send the customer token if the user is signed in, so the view is credited to
them rather than counted as a guest.

---

## 8. Request reference for the astrology services

Dates are `YYYY-MM-DD`, times `HH:MM`, and `lang` defaults to `en` throughout.

**PersonInput**, used by matching:

| Field | Type | Required |
|---|---|---|
| `name` | string | yes |
| `gender` | string | no |
| `birth_date` | string | yes |
| `birth_time` | string | yes |
| `birth_place` | string | no |
| `latitude`, `longitude` | number | yes |
| `timezone` | number | no (defaults to 5.5) |

### 8.1 Kundali generate: `POST .../kundali/generate`

```json
{
  "kundali": [{
    "name": "Ravi", "gender": "male",
    "birthDate": "1990-05-15", "birthTime": "10:30", "birthPlace": "Mumbai",
    "latitude": 19.07, "longitude": 72.87, "timezone": 5.5, "lang": "en"
  }],
  "is_match": false
}
```
Required per person: `name`, `birthDate`, `birthTime`, `birthPlace`, `latitude`/`longitude`.
Response: `{ "status", "message", "recordList": [...], "complete_details": [...] }`. Sections may be
missing when an upstream section fails; treat a missing section as normal. `amount` is ignored.

### 8.2 Chart image: `GET .../kundali/chart-image`
Query: `dob` (YYYY-MM-DD), `tob` (HH:MM), `lat`, `lon`, `tz`, `div` (`D1` default, `D9`, `D10` …),
`style` (`north` default or `south`). Returns an **image**, not JSON.

### 8.3 Matching: `aggregate`, `ashtakoot`, `dashakoot`, `papasamaya`, `rajju-vedha`
```json
{ "boy": { PersonInput }, "girl": { PersonInput }, "match_type": "", "lang": "en" }
```

### 8.4 Nakshatra match
`{ "boy_star": 1-27, "girl_star": 1-27, "lang": "en" }`

### 8.5 Western match
`{ "boy_sign": 1-12, "girl_sign": 1-12, "lang": "en" }`

### 8.6 Panchang: `today`, `monthly`, `choghadiya`, `hora`, `festivals`, `sun-moon`
`{ "date": "2026-09-25", "time": "06:00", "latitude": 19.07, "longitude": 72.87, "timezone": 5.5, "lang": "en" }`.
`latitude` and `longitude` are required.

### 8.7 Numerology report
`{ "name": "Ravi", "birth_date": "1990-05-15", "lang": "en" }` (`name` and `birth_date` required)

### 8.8 Numerology day number
`{ "birth_date": "1990-05-15", "lang": "en" }`

### 8.9 Numerology table
`{ "name", "birth_date", "birth_time", "latitude", "longitude", "timezone", "lang" }`. Everything
except `timezone` and `lang` is required.

### 8.10 Radical number
`{ "radical_number": 1-9, "lang": "en" }`

### 8.11 Tarot cards
`GET .../tarot/cards?arcana=&suit=&search=&lang=` and `GET .../tarot/cards/:id`

### 8.12 Tarot shuffle
`GET .../tarot/shuffle?shuffle_type=&lang=`

### 8.13 Single-card readings: `one-card`, `yes-no`, `career`, `love`
`{ "name": "Ravi", "card": "<card from /tarot/cards or /tarot/shuffle>", "direction": "upright", "lang": "en" }` (`card` required).
`love` also takes `style`: `in_depth` (default), `erotic`, `made_for_each_other` or `flirt`.

### 8.14 Three-card (past / present / future)
`{ "name", "lang", "cards": [ { "card", "direction" }, { ... }, { ... } ] }`

### 8.15 Love triangle
`{ "name", "lang", "card_self", "card_lover1", "card_lover2" }` (all three cards required)

### 8.16 Breakup
`{ "name", "lang", "kind": "romantic|business", "card_cause", "card_advise" }` (both cards required)

Matching, panchang and numerology responses use the section 5 envelope:
`{ "status": true, "message": "...", "data": { "charged": 0, "data": { ... } } }`.

---

## 9. Database changes

Run on each environment (idempotent, safe to repeat):

| File | Change |
|---|---|
| `migrations/2026_09_25_astrology_service_usage_platform.sql` | Adds `platform`, `device_type`, `app_version` and index `astrology_usage_platform_index` to `astrology_service_usage` |

`.env`: add `ADMIN_URL=https://<admin-host>` on every server (the sign image URLs are built from it).
