> ## Documentation Index
> Fetch the complete documentation index at: https://internal.mechzie.in/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Admin Panel

> Admin dashboard endpoints — login, payments, invites, and management operations

## Overview

The MechZie admin panel is a separate web application that communicates with the same API using `admin` or `super_admin` JWT tokens.
Admins authenticate via Firebase email/password (not phone OTP) through a dedicated endpoint.

```mermaid theme={null}
graph LR
    A[Admin Panel Web] -->|POST /auth/admin-login| B[MechZie API]
    B -->|JWT pair| A
    A -->|Bearer token| C[/admin/* endpoints]
    A -->|Bearer token| D[/super-admin/* endpoints]
```

## Admin Login

<Steps>
  <Step title="Sign in via Firebase email/password">
    Use the Firebase JS SDK in the admin panel:

    ```javascript theme={null}
    import { signInWithEmailAndPassword, getAuth } from 'firebase/auth';

    const auth = getAuth();
    const credential = await signInWithEmailAndPassword(auth, email, password);
    const firebaseIdToken = await credential.user.getIdToken();
    ```
  </Step>

  <Step title="Exchange Firebase token for MechZie JWT">
    ```bash theme={null}
    curl -X POST https://mechzie-api-production.run.app/api/v1/auth/admin-login \
      -H "Content-Type: application/json" \
      -d '{
        "firebaseIdToken": "eyJhbGciOiJSUzI1NiIs..."
      }'
    ```

    **Response (200):**

    ```json theme={null}
    {
      "success": true,
      "data": {
        "accessToken": "eyJhbGciOiJIUzI1NiIs...",
        "refreshToken": "a1b2c3d4...",
        "userId": "uuid-here",
        "role": "admin",
        "expiresIn": 900
      }
    }
    ```

    <Warning>
      Returns **401** if Firebase email is unverified, or no admin account exists for that email.
      Returns **403** if the account's role is `customer` or `mechanic`.
    </Warning>
  </Step>

  <Step title="Use the access token">
    Store and use `accessToken` as a Bearer token for all admin API calls.
    Refresh using `POST /auth/refresh` like any other role.
  </Step>
</Steps>

***

## Payments

### List Payments

`GET /admin/payments`

Returns a paginated list of all payments with joined customer and mechanic details.
Amounts are in **paisa** (÷ 100 = ₹).

**Query parameters:**

| Parameter   | Type                                                      | Description                   |
| ----------- | --------------------------------------------------------- | ----------------------------- |
| `status`    | `created \| authorized \| captured \| refunded \| failed` | Filter by payment status      |
| `type`      | `service \| cancellation_fee`                             | Filter by payment type        |
| `date_from` | `YYYY-MM-DD`                                              | Inclusive start date          |
| `date_to`   | `YYYY-MM-DD`                                              | Inclusive end date (23:59:59) |
| `page`      | integer (default: 1)                                      | Page number                   |
| `limit`     | integer 1–100 (default: 20)                               | Page size                     |

```bash theme={null}
curl -X GET "https://mechzie-api-production.run.app/api/v1/admin/payments?status=captured&page=1&limit=20" \
  -H "Authorization: Bearer ADMIN_ACCESS_TOKEN"
```

**Response (200):**

```json theme={null}
{
  "data": [
    {
      "id": "pay-uuid",
      "job_id": "job-uuid",
      "type": "service",
      "amount": 50000,
      "status": "captured",
      "method": "upi",
      "refund_amount": null,
      "refund_reason": null,
      "razorpay_order_id": "order_abc123",
      "razorpay_payment_id": "pay_xyz789",
      "paid_at": "2026-07-17T10:30:00.000Z",
      "created_at": "2026-07-17T10:00:00.000Z",
      "customer_name": "Rahul Kumar",
      "customer_phone": "+919876543210",
      "mechanic_name": "Arun Singh",
      "mechanic_phone": "+919123456789"
    }
  ],
  "pagination": {
    "total": 142,
    "page": 1,
    "limit": 20,
    "totalPages": 8
  }
}
```

***

### Payment Stats

`GET /admin/payments/stats`

Returns aggregate stats across **all payments** in a single query.

```bash theme={null}
curl -X GET "https://mechzie-api-production.run.app/api/v1/admin/payments/stats" \
  -H "Authorization: Bearer ADMIN_ACCESS_TOKEN"
```

**Response (200):**

```json theme={null}
{
  "data": {
    "totalGross": 5200000,
    "totalRefunded": 150000,
    "totalTransactions": 142,
    "capturedCount": 130,
    "refundedCount": 8,
    "failedCount": 4
  }
}
```

| Field               | Description                                                               |
| ------------------- | ------------------------------------------------------------------------- |
| `totalGross`        | Sum of captured **service** payments (paisa). Excludes cancellation fees. |
| `totalRefunded`     | Sum of `refund_amount` on refunded payments (paisa)                       |
| `totalTransactions` | All payment rows regardless of status                                     |
| `capturedCount`     | Payments with status `captured`                                           |
| `refundedCount`     | Payments with status `refunded`                                           |
| `failedCount`       | Payments with status `failed`                                             |

***

## Invites (super\_admin only)

<Warning>
  All `/super-admin/*` endpoints require the `super_admin` role. `admin` accounts receive **403**.
</Warning>

### List Invites

`GET /super-admin/invites`

Returns all invites (pending, used, and revoked) ordered newest-first.
The invite token hash is **never** included in the response.

```bash theme={null}
curl -X GET "https://mechzie-api-production.run.app/api/v1/super-admin/invites" \
  -H "Authorization: Bearer SUPER_ADMIN_TOKEN"
```

**Response (200):**

```json theme={null}
{
  "success": true,
  "data": [
    {
      "id": "inv-uuid",
      "email": "newadmin@company.com",
      "role": "admin",
      "used": false,
      "used_at": null,
      "revoked": false,
      "revoked_at": null,
      "expires_at": "2026-07-24T10:00:00.000Z",
      "invited_by": "sa-uuid",
      "invited_by_name": "Thrisan P",
      "created_at": "2026-07-17T10:00:00.000Z"
    }
  ]
}
```

<Note>
  `invited_by_name` is `null` if the inviting super\_admin account has been deleted.
</Note>

***

## Endpoint Summary

| Method  | Path                              | Role         | Description             |
| ------- | --------------------------------- | ------------ | ----------------------- |
| `POST`  | `/auth/admin-login`               | Public       | Firebase email → JWT    |
| `GET`   | `/admin/payments`                 | admin+       | Paginated payment list  |
| `GET`   | `/admin/payments/stats`           | admin+       | Aggregate payment stats |
| `POST`  | `/admin/payments/:id/refund`      | admin+       | Initiate refund         |
| `GET`   | `/admin/dashboard`                | admin+       | Dashboard stats         |
| `GET`   | `/admin/users`                    | admin+       | List users              |
| `GET`   | `/admin/mechanics`                | admin+       | List mechanics          |
| `PATCH` | `/admin/mechanics/:id/verify`     | admin+       | Verify/suspend mechanic |
| `GET`   | `/admin/jobs`                     | admin+       | List jobs               |
| `GET`   | `/admin/jobs/:id`                 | admin+       | Job detail              |
| `GET`   | `/super-admin/invites`            | super\_admin | List all invites        |
| `POST`  | `/super-admin/invites`            | super\_admin | Create invite           |
| `PATCH` | `/super-admin/invites/:id/revoke` | super\_admin | Revoke invite           |
| `PATCH` | `/super-admin/users/:id/role`     | super\_admin | Update user role        |
