# Change stage

`POST /api/v1/opportunities/{id}/stage`

Moves the opportunity to another stage. Stage gates apply exactly like in the web app: an unmet rule returns `409 gate` with `gate_problems`. Send `reason` for Lost / Cancel. A won opportunity turns the company into a customer and emits `opp_won` to apps.

## Path parameters

| Field | Type | Description |
|---|---|---|
| `id` (required) | integer | Opportunity id. |

## Body

| Field | Type | Description |
|---|---|---|
| `stage` (required) | string | Target stage key (`/me` → `constants.stages`; closing keys are `Win`, `Lost`, `Cancel`). |
| `note` | string | Note for the stage log. |
| `reason` | string | Loss / cancel reason (`/me` → `constants.loss_reasons`). |

## Response

```json 200
{
  "messages": [
    "Aşama güncellendi: Viable"
  ],
  "ok": true,
  "opp": {
    "bant": 4,
    "bant_a": true,
    "bant_b": true,
    "bant_n": true,
    "bant_t": true,
    "base_currency": "EUR",
    "can_edit": true,
    "can_revive": false,
    "close_category": "",
    "close_date": "2026-11-16",
    "close_reason": "",
    "closed_at": null,
    "competitor": "Mevcut tedarikçi",
    "cur_sym": "€",
    "currency": "EUR",
    "customer": "Kuzey Plastik Sanayi",
    "customer_city": "Bursa",
    "customer_id": 31,
    "days_in_stage": 0,
    "demos": [],
    "detail_status": "",
    "fc": "Best Case",
    "gate_ok": false,
    "gate_problems": [
      "En az bir F2F ziyaret kaydı gerekir (Hızlı Giriş → tür F2F)"
    ],
    "guide": "f2f ziyaret + doğru ürün",
    "health": {
      "grade": "success",
      "label": "sağlıklı",
      "score": 80
    },
    "health_color": "g",
    "health_manual": false,
    "health_note": "",
    "health_why": [
      [
        "−15"
      ]
    ],
    "id": 53,
    "initials": "KP",
    "is_account": false,
    "is_open": true,
    "last_update": "2026-10-02",
    "lifetime_left": 180,
    "line": "",
    "logs": [
      {
        "date": "2026-10-02T20:07:00",
        "from": "Qualify",
        "note": "İhtiyaç ve bütçe doğrulandı.",
        "to": "Viable",
        "user": "Deniz Aksoy"
      }
    ],
    "name": "Streç film tedariki",
    "next_stage": "Present Solution",
    "next_step": "F2F ziyaret planla ve gerçekleştir",
    "note": "Numune onayı bekleniyor.",
    "notes": [],
    "offer_price": 2.35,
    "offers": [],
    "orders": [],
    "owner": {
      "full_name": "Deniz Aksoy",
      "id": 1,
      "role": "admin",
      "role_label": "Yönetici",
      "username": "admin"
    },
    "payment_days": 60,
    "potential_kg": 12000.0,
    "prob": 0.25,
    "probability": null,
    "product": "",
    "product_id": null,
    "pu": "€/kg",
    "rid": "006BMHmVNZ9nFLS",
    "sla_days": 60,
    "sla_left": 60,
    "source": "",
    "stage": "Viable",
    "stage_label": "Viable",
    "start_date": "2026-10-02",
    "steps": [
      {
        "assignee": {
          "full_name": "Deniz Aksoy",
          "id": 1,
          "role": "admin",
          "role_label": "Yönetici",
          "username": "admin"
        },
        "auto": true,
        "done": true,
        "due_date": null,
        "id": 467,
        "note": "otomatik: BANT kutusu",
        "stage": "Qualify",
        "state": "done",
        "title": "Karar verici / yetkili kişiyi belirle (Authority)"
      }
    ],
    "tags": [],
    "tasks": [],
    "threads": [],
    "threads_n": 0,
    "trend": "",
    "trend_label": "Otomatik",
    "type": "",
    "unit": "kg",
    "unit_code": "kg",
    "value": 338400.0,
    "value_base": 338400.0,
    "value_short": "338K",
    "visits": [],
    "weighted": 84600.0
  }
}
```

```json 409
{
  "error": "gate",
  "gate_problems": [
    "BANT kriterleri 4/4 sağlanmalı (Budget · Authority · Need · Time)"
  ],
  "message": "Viable'a geçmek için: BANT kriterleri 4/4 sağlanmalı (Budget · Authority · Need · Time)",
  "ok": false
}
```
