
# Midas API (IColoring Backend)

This document describes the **Midas** endpoints exposed by **api-icoloring**.

## Base URL

- **Dev (Swagger)**: `https://api-icoloring.dev.aperogroup.ai`
- All endpoints below are under: `/api/v1`

## Standard request headers (mobile client)

The mobile client typically calls this backend with headers like:

```bash
curl --compressed -X GET "https://api-icoloring.dev.aperogroup.ai/api/v1/midas/subscriptions" \
  -H "accept: application/json" \
  -H "accept-charset: UTF-8" \
  -H "accept-encoding: gzip" \
  -H "app-name: AI_AIP111_Supermind_Android" \
  -H "app-version: 1.1.0" \
  -H "connection: Keep-Alive" \
  -H "content-type: application/json" \
  -H "country-code: VN" \
  -H "host: api-icoloring.dev.aperogroup.ai" \
  -H "user-agent: ktor-client" \
  -H "x-api-bundleid: icoloring.ai.draw.art.coloringbook" \
  -H "x-api-deviceid: e71016a045482474" \
  -H "x-api-platform: android"
```

Notes:
- `--compressed` is recommended because the server may return `content-encoding: gzip`.
- You typically do **not** need to set `host` manually (your HTTP client will do it); it’s included here only to match the “standard request” shape used in some client logs.
- `x-api-deviceid` is lower-cased by the backend before use.

## Recommended call order (client flow)

1. Call **`POST /api/v1/midas/intent`** to link the user email (required before subscription lookups if your client depends on email linkage).
2. Call **`GET /api/v1/midas/subscriptions`** to fetch the subscription state.

## Deployment state (as of 2026-05-06)

| Environment | Base URL | Midas routes |
|---|---|---|
| **Dev** | `https://api-icoloring.dev.aperogroup.ai` | Live and working ✓ |
| **Production** | `https://api-icoloring.aperogroup.ai` | Not deployed yet (returns 404) |

## Response format

- **Success** responses are wrapped by a global interceptor: `statusCode`, `message`, `data`, `timestamp`, `path`, `traceId`.
- **Error** responses are wrapped by a global exception filter: `correlationId`, `statusCode`, `timestamp`, `path`, `message`, `errorCode` (and `stack` in dev).

### Real example — success envelope

Captured from a live call on **2026-05-06**:

`GET https://api-icoloring.aperogroup.ai/api/timestamp`

```json
{
  "statusCode": 200,
  "message": "Success",
  "data": {
    "timestamp": 1778041326409,
    "timestring": "2026-05-06T04:22:06.409Z"
  },
  "timestamp": "06/05/2026 04:22:06",
  "path": "/api/timestamp",
  "traceId": "1b8fd54b-33d1-48dc-9aea-866867d4a035"
}
```

### Real example — error envelope (400)

Captured from `POST /api/v1/midas/intent` on dev on **2026-05-06** (`ERR303` — email not in Midas):

```json
{
  "correlationId": "3ede5656-c7c7-442d-b94f-966fb4562f1f",
  "statusCode": 400,
  "timestamp": "2026-05-06T05:00:07.542Z",
  "path": "/api/v1/midas/intent",
  "message": "Invalid email",
  "errorCode": "ERR303",
  "stack": "ApiException: Invalid email\n    at MidasService.intentStripe (/usr/src/app/dist/modules/midas/midas.service.js:51:23)"
}
```

> `stack` is only present in `NODE_ENV=development`. Production omits it.

> **Note:** `errorCode: "ERR19"` is the generic catch-all used for unexpected upstream errors, 404 route-not-found, and 502 — use `statusCode` + `message` to distinguish them.

## Endpoints

### POST `/api/v1/midas/intent`

Link an email to Stripe via Midas. This endpoint:

- Validates email format
- Rejects emails already used by another user (`ERR302`)
- Calls Midas to validate the email against purchase history
- Upserts the local `User` record (by `deviceId`) and stores `email`

**Body**

```json
{
  "email": "user@gmail.com"
}
```

**Example (cURL)**

```bash
curl --compressed -X POST "https://api-icoloring.dev.aperogroup.ai/api/v1/midas/intent" \
  -H "accept: application/json" \
  -H "accept-charset: UTF-8" \
  -H "accept-encoding: gzip" \
  -H "app-name: AI_AIP111_Supermind_Android" \
  -H "app-version: 1.1.0" \
  -H "connection: Keep-Alive" \
  -H "content-type: application/json" \
  -H "country-code: VN" \
  -H "host: api-icoloring.dev.aperogroup.ai" \
  -H "user-agent: ktor-client" \
  -H "x-api-bundleid: icoloring.ai.draw.art.coloringbook" \
  -H "x-api-deviceid: e71016a045482474" \
  -H "x-api-platform: android" \
  -d '{ "email": "user@gmail.com" }'
```

**Common errors**

| HTTP | errorCode | When |
|---:|---|---|
| 400 | `ERR302` | Email already exists for another user |
| 400 | `ERR300` | Midas says user already has a transaction not eligible for linking |
| 400 | `ERR301` | Midas says email is owned by another user / requires changing to a “usage email” |
| 400 | `ERR303` | Email has no transaction history in Midas (message: `"Invalid email"`) |
| 502 | `ERR19` | Unexpected Midas upstream error code |

**Real response — `ERR303` (email not in Midas)**

Captured from a live call on **2026-05-06**:

```json
{
  "correlationId": "3ede5656-c7c7-442d-b94f-966fb4562f1f",
  "statusCode": 400,
  "timestamp": "2026-05-06T05:00:07.542Z",
  "path": "/api/v1/midas/intent",
  "message": "Invalid email",
  "errorCode": "ERR303"
}
```

---

### GET `/api/v1/midas/subscriptions`

Returns subscriptions grouped by provider for the given device.

**Example (cURL)**

```bash
curl --compressed -X GET "https://api-icoloring.dev.aperogroup.ai/api/v1/midas/subscriptions" \
  -H "accept: application/json" \
  -H "accept-charset: UTF-8" \
  -H "accept-encoding: gzip" \
  -H "app-name: AI_AIP111_Supermind_Android" \
  -H "app-version: 1.1.0" \
  -H "connection: Keep-Alive" \
  -H "content-type: application/json" \
  -H "country-code: VN" \
  -H "host: api-icoloring.dev.aperogroup.ai" \
  -H "user-agent: ktor-client" \
  -H "x-api-bundleid: icoloring.ai.draw.art.coloringbook" \
  -H "x-api-deviceid: e71016a045482474" \
  -H "x-api-platform: android"
```

**Real response — 200 (no active subscription)**

Captured from a live call on **2026-05-06**:

```json
{
  "statusCode": 200,
  "message": "Success",
  "data": {
    "customer": null,
    "allSubscriptions": [],
    "byProvider": [],
    "currentSubscriptions": [],
    "hasMultipleActiveWarning": false
  },
  "timestamp": "06/05/2026 05:00:09",
  "path": "/api/v1/midas/subscriptions",
  "traceId": "1938d4fc-82da-472f-9fc2-ad6e755da009"
}
```

> `customer: null` and empty arrays mean no Midas record exists for this device yet. `hasMultipleActiveWarning: true` would indicate the user has active subscriptions on multiple providers simultaneously.