# Mission Log

Mission Logs are the **activity events** that drive mission progress. Every time an end user performs a qualifying action — completing a purchase, finishing a lesson, or leaving a review — your backend sends a Mission Log entry. The platform aggregates these entries according to the mission's `aggregationPeriod`, updating the user's `Mission Progress` automatically.

:::info
Mission Logs can only be **created** via the API (`CREATE`, `GET`, `LIST`). They cannot be updated or deleted. Once submitted, a log entry is permanent.
:::

---

## How it works

1. **User performs an action** — a customer completes a purchase, registers, or finishes a mission task.
2. **Your backend sends a log** — call `POST /schema/mission_log/record` with `missionId`, `ownedById`, `activityId`, `activityAt`, `uniqueIdentifier`, and optional `activityValue`.
3. **Progress updated** — the platform aggregates the entry into the user's `Mission Progress`, updating the state and checking milestone thresholds.
4. **Milestone triggered** — if a milestone threshold is crossed, a `Reward Log` is created and returned in `achievedMilestoneRewardLog`.
5. **Mission completed** — when all mission milestones or objectives are reached, `missionProgressStatus` transitions to `completed` and the overall `rewardLog` is issued.

---

## Fields

### Required on create

| Field | Type | Required | Description |
|---|---|---|---|
| `missionId` | UUID | ✅ | ID of the mission this log contributes to |
| `ownedById` | UUID | ✅ *(or use `ownedBy`)* | Gamopanda member ID of the user performing the activity |
| `activityId` | string | ✅ | Activity ID for this event — e.g. `order_completed`, `registration_complete`, `referral_sign_up` |
| `activityAt` | datetime | ✅ | Datetime when the activity occurred |
| `uniqueIdentifier` | string | ✅ | Unique identifier for this event — e.g., `order_completed_123456789`, `registration_complete_987654321` |

### Optional on create

| Field | Type | Description |
|---|---|---|
| `activityValue` | number | The numeric value associated with the activity (e.g. spend amount, count) |
| `ownedBy` | object | Inline member upsert payload. Use instead of `ownedById` to sync the member in the same request |

### Status

| Field | Type | Default | Description |
|---|---|---|---|
| `status` | enum | `live` | `draft` · `live` · `paused`. Only `live` logs are included in aggregation |

---

## Extra fields returned in the response

After a log is created, the platform enriches the response with several computed fields:

| Field | Description |
|---|---|
| `mission` | The full joined `Mission` object this log belongs to |
| `missionProgress` | The user's updated `Mission Progress` record after this log was processed |
| `taskProgress` | The associated task progress data |
| `achievedMilestone` | The `Milestone` record crossed by this log entry, if any |
| `nextMilestone` | The next `Milestone` the user is working toward, if any |
| `achievedMilestoneRewardLog` | The `Reward Log` issued when a milestone was crossed |
| `rewardLog` | The `Reward Log` issued when the overall mission is completed |

---

## Handling `achievedMilestoneRewardLog`

When a milestone threshold is crossed, the platform creates a `Reward Log` record and returns it as `achievedMilestoneRewardLog` in the response.

Coupon generation and fulfillment depend on the `handleCoupon` flag configured on the associated [Reward](/reward) module:

- **Gamopanda-handled coupons (`handleCoupon: true` on Reward)**: Gamopanda automatically assigns an available coupon code (or auto-generates one if `handleCouponAutoGeneration: true`) and sets `rewardIssuedAt` and `rewardExpiryAt` on the `Reward Log`. No client action is required.
- **Client-handled coupons (`handleCoupon: false` on Reward)**: The `Reward Log` is created with a `null` `couponCode`. Your backend is responsible for generating the coupon in your system and updating the `Reward Log` via API.

### Reward fulfilment workflow (Client-handled coupons)

1. **Check the response** — after `POST /schema/mission_log/record`, inspect `achievedMilestoneRewardLog` or `rewardLog`. If it is not `null` and `couponCode` is `null`, a milestone was crossed that requires client fulfillment.
2. **Generate a coupon** — call your coupon or voucher system to issue a reward code for this user.
3. **Update the reward log** — `PATCH` the reward log with the coupon code and timestamps:

```http
PATCH /api/v1.0/schema/reward_log/record/{achievedMilestoneRewardLog.id}
x-api-key: <your-api-key>
x-api-secret: <your-api-secret>

{
  "couponCode": "MISSIONREWARD2026",
  "rewardIssuedAt": "2026-06-24T10:00:00+05:30",
  "rewardExpiryAt": "2026-07-24T23:59:59+05:30"
}
```

### Reward log lifecycle

| Step | Fields set | Who sets it |
|---|---|---|
| Milestone crossed | `milestoneId`, `linkedSchemaRecordId`, `ownedById` | Platform (automatic) |
| Coupon assigned | `couponCode`, `rewardIssuedAt`, `rewardExpiryAt` | Gamopanda (if `handleCoupon: true`) OR Your backend (if `handleCoupon: false`) |

---

## Syncing a member inline

You can pass member details directly in the `ownedBy` field. The platform will **create or update** the member record automatically:

```json
{
  "missionId": "c123e456-e89b-12d3-a456-426614174000",
  "ownedBy": {
    "externalId": "cust_8472910",
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "jane.doe@example.com"
  },
  "activityId": "order_completed",
  "uniqueIdentifier": "order_completed_123456789",
  "activityAt": "2026-06-24T10:00:00+05:30",
  "activityValue": 20.50,
  "status": "live"
}
```

---

## The `uniqueIdentifier` — preventing duplicates

`uniqueIdentifier` is your system's unique identifier for the triggering event. The platform uses it to **idempotently reject duplicate submissions**.

```json
{ "uniqueIdentifier": "order_completed_123456789" }
```

---

## Real-world examples

**🛍️ E-commerce — Purchase Cycle Mission Log**

A user completes an order that contributes to a weekly purchase cycle mission:

```http
POST /api/v1.0/schema/mission_log/record
x-api-key: <your-api-key>
x-api-secret: <your-api-secret>

{
  "missionId": "c123e456-e89b-12d3-a456-426614174000",
  "ownedById": "019ac851-a7c0-75ad-a271-b37946a3e5ed",
  "activityId": "order_completed",
  "uniqueIdentifier": "order_completed_123456789",
  "activityAt": "2026-06-24T10:00:00+05:30",
  "activityValue": 50.00,
  "status": "live"
}
```

**Response:**

```json
{
  "id": "log-uuid-here",
  "missionId": "c123e456-e89b-12d3-a456-426614174000",
  "uniqueIdentifier": "order_completed_123456789",
  "activityId": "order_completed",
  "activityAt": "2026-06-24T10:00:00+05:30",
  "activityValue": 50.00,
  "ownedById": "019ac851-a7c0-75ad-a271-b37946a3e5ed",
  "missionProgress": {
    "missionProgressStatus": "in_progress",
    "missionStartedAt": "2026-06-24T10:00:00+05:30",
    "missionCompletedAt": null,
    "missionFailedAt": null
  },
  "achievedMilestone": {
    "id": "milestone-uuid-1",
    "name": "First Purchase Completed"
  },
  "nextMilestone": {
    "id": "milestone-uuid-2",
    "name": "Leave Product Review"
  },
  "achievedMilestoneRewardLog": {
    "id": "reward-log-uuid-1",
    "couponCode": null,
    "rewardIssuedAt": null,
    "rewardExpiryAt": null
  }
}
```

---

## Access & permissions

| Caller | Allowed operations | Notes |
|---|---|---|
| Admin / Backend | CREATE · GET · LIST | Non-editable, cannot be deleted |
| End user | *(none)* | No direct write access |
| Guest user | *(none)* | Not accessible |

---

## Related resources

| Resource | Description |
|---|---|
| [Mission](/mission) | Parent mission configuration defining the mission rules |
| [Mission Progress](/mission-progress) | Per-user progress state updated after each log |
| [Milestone](/milestone) | Checkpoints attached to the mission |
| [Reward Log](/reward-log) | Reward entries automatically created when a milestone or mission is completed |
| [Member](/member) | End user (`ownedById`) performing the mission activities |

---

## API reference

See the [API Reference](/api/mission-log) for full request/response schemas and interactive examples for:

- `POST /schema/mission_log/record` — create a mission log
- `GET /schema/mission_log/record` — list mission logs
- `GET /schema/mission_log/record/{id}` — get a mission log by ID
