{
 "openapi": "3.1.0",
 "info": {
  "title": "Solk CRM API",
  "version": "v22",
  "description": "REST API of Solk CRM. Every installation has its own host: https://<company>.solk.app. Turkish texts are in x-summary-tr / x-description-tr. Human-readable docs: https://docs.solk.app",
  "contact": {
   "name": "Solk",
   "email": "info@solk.app",
   "url": "https://solk.app"
  }
 },
 "servers": [
  {
   "url": "https://{workspace}.solk.app",
   "variables": {
    "workspace": {
     "default": "ornek",
     "description": "Your installation's subdomain"
    }
   }
  }
 ],
 "tags": [
  {
   "name": "Authentication",
   "x-name-tr": "Kimlik doğrulama"
  },
  {
   "name": "Workspace",
   "x-name-tr": "Çalışma alanı"
  },
  {
   "name": "Companies",
   "x-name-tr": "Firmalar"
  },
  {
   "name": "People",
   "x-name-tr": "Kişiler"
  },
  {
   "name": "Opportunities",
   "x-name-tr": "Fırsatlar"
  },
  {
   "name": "Activities",
   "x-name-tr": "Görüşmeler"
  },
  {
   "name": "Actions & tasks",
   "x-name-tr": "Aksiyonlar ve görevler"
  },
  {
   "name": "Calendar",
   "x-name-tr": "Takvim"
  },
  {
   "name": "Trade fairs & leads",
   "x-name-tr": "Fuarlar ve leadler"
  },
  {
   "name": "Email",
   "x-name-tr": "E-posta"
  },
  {
   "name": "Ask",
   "x-name-tr": "Sor"
  },
  {
   "name": "SCIM 2.0",
   "x-name-tr": "SCIM 2.0"
  },
  {
   "name": "OAuth 2.1",
   "x-name-tr": "OAuth 2.1"
  }
 ],
 "paths": {
  "/api/v1/me": {
   "get": {
    "operationId": "auth_me",
    "summary": "Identify",
    "description": "Returns the user behind the token, their enabled modules, the installation's constants (stage keys and labels, task priorities, loss reasons…), the product list and the licence state. Call it first when your integration starts: stage keys differ per installation, so read `constants.stages` and `constants.stage_labels` from here.",
    "tags": [
     "Authentication"
    ],
    "x-summary-tr": "Kimliği doğrula",
    "x-description-tr": "Belirtecin hangi kullanıcıyla çalıştığını, kullanıcının açık modüllerini, kurulumun sabitlerini (aşama anahtarları ve adları, görev öncelikleri, kayıp nedenleri…), ürün listesini ve lisans durumunu döndürür. Entegrasyonunuzu başlatırken ilk çağrı budur; aşama anahtarları kuruluma göre değiştiği için `constants.stages` ve `constants.stage_labels` buradan okunmalıdır.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ai": false,
         "app": {
          "accent": "#0f3a44",
          "accent_dark": "#0b2b33",
          "company": "Örnek Kimya",
          "currencies": [
           "EUR"
          ],
          "currency_base": "EUR",
          "currency_symbol": "€",
          "logo": "",
          "name": "Solk CRM",
          "opp_lifetime_days": 180,
          "site_url": "https://ornek.solk.app",
          "stage_sla": {
           "Expect to Close": 15,
           "Negotiation": 30,
           "Present Solution": 60,
           "Qualify": 30,
           "Viable": 60
          },
          "ticket_sla_hours": {
           "Acil": 4,
           "Düşük": 168,
           "Normal": 72,
           "Yüksek": 24
          },
          "unit_default": "kg",
          "units": [
           "kg"
          ],
          "version": "v22"
         },
         "constants": {
          "action_soon_days": 7,
          "barriers": [
           "Fiyat"
          ],
          "customer_statuses": [
           "AC"
          ],
          "demo_results": [
           "Başarılı"
          ],
          "demo_statuses": [
           "Henüz Deneme Aşamasına Gelmedik"
          ],
          "forecast_cats": [
           "Pipeline"
          ],
          "lead_interest": [
           "Sıcak"
          ],
          "lead_next_actions": [
           "Teklif gönder"
          ],
          "lead_statuses": [
           "Yeni"
          ],
          "lead_timings": [
           "Hemen"
          ],
          "lead_visitor_types": [
           "Potansiyel müşteri"
          ],
          "loss_reasons": [
           "Fiyat"
          ],
          "makro_stages": [
           "Takip"
          ],
          "next_actions": [
           "Numune Gönder"
          ],
          "open_stages": [
           "Qualify"
          ],
          "opp_line_label": "",
          "opp_status_labels": false,
          "opp_types": [
           "Yeni Müşteri"
          ],
          "order_kinds": [
           "İlk Sipariş"
          ],
          "stage_colors": {
           "Cancel": "#62767a",
           "Expect to Close": "#2d9d78",
           "Lost": "#c23934",
           "Negotiation": "#e0a228",
           "Present Solution": "#6b5bd6",
           "Qualify": "#8a9ba0",
           "Viable": "#2a78d6",
           "Win": "#24733f"
          },
          "stage_gate": {
           "Expect to Close": "kapanış bekleniyor",
           "Negotiation": "fiyat / vade pazarlığı",
           "Present Solution": "aktif deneme, sonucu net",
           "Qualify": "BANT 4/4",
           "Viable": "f2f ziyaret + doğru ürün"
          },
          "stage_labels": {
           "Cancel": "Cancel",
           "Expect to Close": "Expect to Close",
           "Lost": "Lost",
           "Negotiation": "Negotiation",
           "Present Solution": "Present Solution",
           "Qualify": "Qualify",
           "Viable": "Viable",
           "Win": "Win"
          },
          "stage_rules": true,
          "stage_sla": {
           "Expect to Close": 15,
           "Negotiation": 30,
           "Present Solution": 60,
           "Qualify": 30,
           "Viable": 60
          },
          "stages": [
           "Qualify"
          ],
          "task_priorities": [
           "Düşük"
          ],
          "task_statuses": [
           "Açık"
          ],
          "visit_period": {
           "AC": 90,
           "Prospect": 180
          },
          "visit_topics": [
           "Yeni Ürünler"
          ],
          "visit_types": [
           "F2F"
          ]
         },
         "license": {
          "blocked": false,
          "customer": "Örnek Kimya",
          "days_left": null,
          "end": null,
          "label": "Deneme modu",
          "modules": [
           "calendar"
          ],
          "no": null,
          "state": "trial"
         },
         "mailbox": {
          "connected": true,
          "email": "deniz@ornekkimya.com.tr",
          "error": "",
          "signature": false,
          "status": "ok"
         },
         "ok": true,
         "products": [
          {
           "code": "HS30",
           "id": 5,
           "list_price": 6.4,
           "name": "HS 30 Isıl Yapışma Laki"
          },
          {
           "code": "SB450",
           "id": 3,
           "list_price": 3.8,
           "name": "PU-SB 450 Solvent Bazlı Yapıştırıcı"
          }
         ],
         "user": {
          "email": "deniz@ornekkimya.com.tr",
          "full_name": "Deniz Aksoy",
          "id": 1,
          "modules": [
           "calendar"
          ],
          "role": "admin",
          "role_label": "Yönetici",
          "username": "admin"
         },
         "users": [
          {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          }
         ],
         "weak_password": true
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/login": {
   "post": {
    "operationId": "auth_login",
    "summary": "Log in with username",
    "description": "The sign-in endpoint used by the mobile app: exchanges username + password (+ two-factor code) for a session token starting with `xk_`. The token lives `API_TOKEN_DAYS` days (default 90). For server-to-server integrations use an **API key** from the Developers page or **OAuth** instead.",
    "tags": [
     "Authentication"
    ],
    "x-summary-tr": "Kullanıcı adıyla oturum aç",
    "x-description-tr": "Mobil uygulamanın kullandığı oturum açma ucu: kullanıcı adı + şifre (+ iki adımlı doğrulama kodu) karşılığında `xk_` ile başlayan bir oturum belirteci verir. Belirteç `API_TOKEN_DAYS` gün (varsayılan 90) geçerlidir. Sunucudan sunucuya entegrasyonlarda bunun yerine Geliştiriciler sayfasından açılan **API anahtarını** ya da **OAuth**'u kullanın.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "username": {
          "type": "string",
          "description": "Username."
         },
         "password": {
          "type": "string",
          "description": "Password."
         },
         "otp": {
          "type": "string",
          "description": "6-digit code when two-factor auth is on (the first request returns `otp_required`)."
         },
         "device": {
          "type": "string",
          "description": "Device name shown in the session list."
         }
        },
        "required": [
         "username",
         "password"
        ]
       },
       "example": {
        "username": "admin",
        "password": "1234",
        "device": "iPhone 15 · Solk"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "app": {
          "accent": "#0f3a44",
          "accent_dark": "#0b2b33",
          "company": "Örnek Kimya",
          "currencies": [
           "EUR"
          ],
          "currency_base": "EUR",
          "currency_symbol": "€",
          "logo": "",
          "name": "Solk CRM",
          "opp_lifetime_days": 180,
          "site_url": "https://ornek.solk.app",
          "stage_sla": {
           "Expect to Close": 15,
           "Negotiation": 30,
           "Present Solution": 60,
           "Qualify": 30,
           "Viable": 60
          },
          "ticket_sla_hours": {
           "Acil": 4,
           "Düşük": 168,
           "Normal": 72,
           "Yüksek": 24
          },
          "unit_default": "kg",
          "units": [
           "kg"
          ],
          "version": "v22"
         },
         "license": {
          "blocked": false,
          "customer": "Örnek Kimya",
          "days_left": null,
          "end": null,
          "label": "Deneme modu",
          "modules": [
           "calendar"
          ],
          "no": null,
          "state": "trial"
         },
         "ok": true,
         "token": "xk_1dcb806508e33cee8d728d9baafc6eee23b6e2cb16da8afd",
         "user": {
          "email": "deniz@ornekkimya.com.tr",
          "full_name": "Deniz Aksoy",
          "id": 1,
          "modules": [
           "calendar"
          ],
          "role": "admin",
          "role_label": "Yönetici",
          "username": "admin"
         },
         "weak_password": true
        }
       }
      }
     },
     "401": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/api/v1/logout": {
   "post": {
    "operationId": "auth_logout",
    "summary": "Log out",
    "description": "Revokes the token used for the request. Meant for mobile session tokens (`xk_`); API keys are revoked on the Developers page.",
    "tags": [
     "Authentication"
    ],
    "x-summary-tr": "Oturumu kapat",
    "x-description-tr": "İstekteki belirteci iptal eder. Mobil oturum belirteçleri (`xk_`) için kullanılır; API anahtarları Geliştiriciler sayfasından iptal edilir.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/today": {
   "get": {
    "operationId": "workspace_today",
    "summary": "Today",
    "description": "The user's day: today's meetings and actions, overdue items, recently opened records (companies, opportunities, people, leads) and this week's visit / task targets. The mobile home screen is drawn from this response.",
    "tags": [
     "Workspace"
    ],
    "x-summary-tr": "Bugün",
    "x-description-tr": "Kullanıcının günü: bugünün toplantıları ve aksiyonları, gecikenler, son açılan kayıtlar (firma, fırsat, kişi, lead) ve bu haftanın ziyaret / görev hedefleri. Mobil uygulamanın ana ekranı bu yanıttan çizilir.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "cards": {
          "contacts": {
           "mine": [
            {
             "customer": "Orkide Medikal Ambalaj Ltd. Şti.",
             "customer_id": 30,
             "department": "Üretim",
             "email": "ugur.ozkan@orkidemedikal.example",
             "id": 57,
             "is_former": false,
             "is_main": true,
             "name": "Uğur Özkan",
             "note": "",
             "phone": "0 (262) 000 91 77",
             "rid": "003LlalbBDATepx",
             "title": "Üretim Müdürü",
             "wa": "902620009177"
            }
           ],
           "n": {
            "mine": 57,
            "recent": 0,
            "team": 57
           },
           "recent": [],
           "team": [
            {
             "customer": "Orkide Medikal Ambalaj Ltd. Şti.",
             "customer_id": 30,
             "department": "Üretim",
             "email": "ugur.ozkan@orkidemedikal.example",
             "id": 57,
             "is_former": false,
             "is_main": true,
             "name": "Uğur Özkan",
             "note": "",
             "phone": "0 (262) 000 91 77",
             "rid": "003LlalbBDATepx",
             "title": "Üretim Müdürü",
             "wa": "902620009177"
            }
           ]
          },
          "customers": {
           "mine": [
            {
             "active": true,
             "at_risk": false,
             "city": "Bursa",
             "currency": "EUR",
             "currency_default": "",
             "id": 25,
             "initials": "AE",
             "last_visit": "2026-07-24",
             "main_contact": {
              "email": "kaan.ozkan@akasyaesnek.example",
              "name": "Kaan Özkan",
              "phone": "0 (224) 000 17 41",
              "wa": "902240001741"
             },
             "name": "Akasya Esnek Ambalaj San. ve Tic. A.Ş.",
             "next_visit_due": "2027-01-20",
             "open_opps": 1,
             "owner": {
              "full_name": "Deniz Aksoy",
              "id": 1,
              "role": "admin",
              "role_label": "Yönetici",
              "username": "admin"
             },
             "pending_state": "soon",
             "period": 180,
             "phone": "0 (224) 000 35 36",
             "potential_kg": 40000.0,
             "rid": "001Yk1AKJ1EIEQw",
             "sector": "Esnek ambalaj",
             "status": "Prospect",
             "status_label": "Prospect",
             "unit": "kg",
             "visit_overdue_days": -110,
             "visit_state": "ok"
            }
           ],
           "n": {
            "mine": 30,
            "recent": 0,
            "team": 30
           },
           "recent": [],
           "team": [
            {
             "active": true,
             "at_risk": false,
             "city": "Bursa",
             "currency": "EUR",
             "currency_default": "",
             "id": 25,
             "initials": "AE",
             "last_visit": "2026-07-24",
             "main_contact": {
              "email": "kaan.ozkan@akasyaesnek.example",
              "name": "Kaan Özkan",
              "phone": "0 (224) 000 17 41",
              "wa": "902240001741"
             },
             "name": "Akasya Esnek Ambalaj San. ve Tic. A.Ş.",
             "next_visit_due": "2027-01-20",
             "open_opps": 1,
             "owner": {
              "full_name": "Deniz Aksoy",
              "id": 1,
              "role": "admin",
              "role_label": "Yönetici",
              "username": "admin"
             },
             "pending_state": "soon",
             "period": 180,
             "phone": "0 (224) 000 35 36",
             "potential_kg": 40000.0,
             "rid": "001Yk1AKJ1EIEQw",
             "sector": "Esnek ambalaj",
             "status": "Prospect",
             "status_label": "Prospect",
             "unit": "kg",
             "visit_overdue_days": -110,
             "visit_state": "ok"
            }
           ]
          },
          "leads": {
           "mine": [
            {
             "can_edit": true,
             "city": "Bursa",
             "company": "Işıltı Ambalaj San. Tic. Ltd. Şti.",
             "contact_name": "Mehmet Arslan",
             "created_at": "2026-08-28T14:10:00",
             "customer_id": null,
             "email": "mehmet@isiltiambalajsanti.example",
             "fair": "Ambalaj Fuarı 2026 (örnek)",
             "fair_id": 1,
             "id": 4,
             "initials": "IA",
             "interest": "Soğuk",
             "line": "",
             "next_action": "Numune gönder",
             "next_date": "2026-10-07",
             "note": "Stantta görüşüldü.",
             "opp_id": null,
             "opp_type": "Mevcut Müşteri — Değişim",
             "owner": {
              "full_name": "Deniz Aksoy",
              "id": 1,
              "role": "admin",
              "role_label": "Yönetici",
              "username": "admin"
             },
             "phone": "0 (224) 000 96 45",
             "potential_kg": 6000.0,
             "products": "4",
             "products_text": "",
             "project_note": "",
             "rid": "00QCwrpUC4bpt3E",
             "sector": "Gıda ambalajı",
             "status": "Teklif verildi",
             "status_eff": "Teklif verildi",
             "supplier": "Mevcut tedarikçi (Asya)",
             "task_id": null,
             "timing": "6 ay içinde",
             "title": "Kalite Kontrol Müdürü",
             "unit": "kg",
             "visitor_type": "Potansiyel müşteri",
             "wa": "902240009645",
             "website": ""
            }
           ],
           "n": {
            "mine": 9,
            "recent": 0,
            "team": 3
           },
           "recent": [],
           "team": [
            {
             "can_edit": true,
             "city": "Konya",
             "company": "Alize Ambalaj A.Ş.",
             "contact_name": "Barış Kaya",
             "created_at": "2026-08-25T15:10:00",
             "customer_id": null,
             "email": "baris@alizeambalajas.example",
             "fair": "Ambalaj Fuarı 2026 (örnek)",
             "fair_id": 1,
             "id": 5,
             "initials": "AA",
             "interest": "Sıcak",
             "line": "",
             "next_action": "Teklif gönder",
             "next_date": "2026-10-03",
             "note": "Stantta görüşüldü.",
             "opp_id": null,
             "opp_type": "Yeni Müşteri",
             "owner": {
              "full_name": "Deniz Aksoy",
              "id": 1,
              "role": "admin",
              "role_label": "Yönetici",
              "username": "admin"
             },
             "phone": "0 (332) 000 44 97",
             "potential_kg": 4000.0,
             "products": "5",
             "products_text": "",
             "project_note": "",
             "rid": "00QiUPO55IJhtmL",
             "sector": "Etiket",
             "status": "Yeni",
             "status_eff": "Yeni",
             "supplier": "Mevcut tedarikçi (Asya)",
             "task_id": null,
             "timing": "3 ay içinde",
             "title": "Genel Müdür",
             "unit": "kg",
             "visitor_type": "Potansiyel müşteri",
             "wa": "903320004497",
             "website": ""
            }
           ]
          },
          "opps": {
           "mine": [
            {
             "bant": 4,
             "base_currency": "EUR",
             "close_date": "2026-11-17",
             "cur_sym": "€",
             "currency": "EUR",
             "customer": "Begonya Esnek Ambalaj A.Ş.",
             "customer_city": "Kocaeli",
             "customer_id": 16,
             "days_in_stage": 21,
             "detail_status": "",
             "fc": "Commit",
             "health": {
              "grade": "success",
              "label": "sağlıklı",
              "score": 100
             },
             "health_color": "g",
             "health_manual": false,
             "health_note": "",
             "id": 16,
             "initials": "BE",
             "is_account": false,
             "is_open": true,
             "last_update": "2026-10-02",
             "lifetime_left": 105,
             "line": "",
             "name": "Mevcut Müşteri — Değişim · 2026",
             "next_step": "Vade ve teslim koşullarını görüş",
             "offer_price": 4.08,
             "owner": {
              "full_name": "Deniz Aksoy",
              "id": 1,
              "role": "admin",
              "role_label": "Yönetici",
              "username": "admin"
             },
             "payment_days": 60,
             "potential_kg": 4000.0,
             "prob": 0.75,
             "probability": null,
             "product": "PU-SL 200 Solventsiz Laminasyon Yapıştırıcısı",
             "product_id": 1,
             "pu": "€/kg",
             "rid": "006aJYGE9HUIaM2",
             "sla_days": 30,
             "sla_left": 9,
             "source": "Bayi / distribütör",
             "stage": "Negotiation",
             "stage_label": "Negotiation",
             "start_date": "2026-07-19",
             "trend": "",
             "trend_label": "Otomatik",
             "type": "Mevcut Müşteri — Değişim",
             "unit": "kg",
             "unit_code": "kg",
             "value": 195840.0,
             "value_base": 195840.0,
             "value_short": "196K"
            }
           ],
           "n": {
            "mine": 28,
            "recent": 0,
            "team": 28
           },
           "recent": [],
           "team": [
            {
             "bant": 4,
             "base_currency": "EUR",
             "close_date": "2026-11-17",
             "cur_sym": "€",
             "currency": "EUR",
             "customer": "Begonya Esnek Ambalaj A.Ş.",
             "customer_city": "Kocaeli",
             "customer_id": 16,
             "days_in_stage": 21,
             "detail_status": "",
             "fc": "Commit",
             "health": {
              "grade": "success",
              "label": "sağlıklı",
              "score": 100
             },
             "health_color": "g",
             "health_manual": false,
             "health_note": "",
             "id": 16,
             "initials": "BE",
             "is_account": false,
             "is_open": true,
             "last_update": "2026-10-02",
             "lifetime_left": 105,
             "line": "",
             "name": "Mevcut Müşteri — Değişim · 2026",
             "next_step": "Vade ve teslim koşullarını görüş",
             "offer_price": 4.08,
             "owner": {
              "full_name": "Deniz Aksoy",
              "id": 1,
              "role": "admin",
              "role_label": "Yönetici",
              "username": "admin"
             },
             "payment_days": 60,
             "potential_kg": 4000.0,
             "prob": 0.75,
             "probability": null,
             "product": "PU-SL 200 Solventsiz Laminasyon Yapıştırıcısı",
             "product_id": 1,
             "pu": "€/kg",
             "rid": "006aJYGE9HUIaM2",
             "sla_days": 30,
             "sla_left": 9,
             "source": "Bayi / distribütör",
             "stage": "Negotiation",
             "stage_label": "Negotiation",
             "start_date": "2026-07-19",
             "trend": "",
             "trend_label": "Otomatik",
             "type": "Mevcut Müşteri — Değişim",
             "unit": "kg",
             "unit_code": "kg",
             "value": 195840.0,
             "value_base": 195840.0,
             "value_short": "196K"
            }
           ]
          }
         },
         "day_label": "Cuma, 2 Ekim 2026",
         "events": [
          {
           "act": {
            "addr": "Kayseri Organize Sanayi Bölgesi, 1. Cadde No: 46, Kayseri, Kayseri",
            "c": 4,
            "mail": "nazli.aydin@ihlamurmatbaacilik.example",
            "n": "Ihlamur Matbaacılık A.Ş.",
            "tel": "0 (352) 000 57 99",
            "url": "/customers/4",
            "wa": "903520005799",
            "who": "Nazlı Aydın"
           },
           "customer_id": 4,
           "date": "2026-10-02",
           "kind": "opp",
           "sub": "Mevcut Müşteri — Ek Satış · 2026 · Qualify",
           "time": null,
           "title": "Ihlamur Matbaacılık A.Ş. · sonraki adım",
           "url": "/opportunities/34"
          },
          {
           "act": {
            "addr": "Sakarya Organize Sanayi Bölgesi, 4. Cadde No: 54, Sakarya, Sakarya",
            "c": 10,
            "mail": "murat.cetin@reyhanpaketleme.example",
            "n": "Reyhan Paketleme Ltd. Şti.",
            "tel": "0 (264) 000 63 67",
            "url": "/customers/10",
            "wa": "902640006367",
            "who": "Murat Çetin"
           },
           "customer_id": 10,
           "date": "2026-10-02",
           "kind": "opp",
           "sub": "Mevcut Müşteri — Ek Satış · 2026 · Expect to Close",
           "time": null,
           "title": "Reyhan Paketleme Ltd. Şti. · sonraki adım",
           "url": "/opportunities/10"
          }
         ],
         "focus": [
          {
           "cls": "bad",
           "text": "9 gecikmiş aksiyon"
          },
          {
           "cls": "warn",
           "text": "3 aksiyon bugün"
          }
         ],
         "greeting": "İyi akşamlar",
         "ok": true,
         "today": "2026-10-02",
         "todos": {
          "all": [
           {
            "customer": "Lotus Medikal Ambalaj San. Tic. Ltd. Şti.",
            "customer_id": 3,
            "date": "2026-09-26",
            "icon": "📋",
            "id": 1,
            "key": "task:1",
            "kind": "task",
            "label": "Numune sonucu için ara",
            "opp": "Yeni Müşteri · 2026",
            "opp_id": 33,
            "src": "Görev",
            "state": "overdue",
            "url": "/action/task/1"
           }
          ],
          "overdue": [
           {
            "customer": "Lotus Medikal Ambalaj San. Tic. Ltd. Şti.",
            "customer_id": 3,
            "date": "2026-09-26",
            "icon": "📋",
            "id": 1,
            "key": "task:1",
            "kind": "task",
            "label": "Numune sonucu için ara",
            "opp": "Yeni Müşteri · 2026",
            "opp_id": 33,
            "src": "Görev",
            "state": "overdue",
            "url": "/action/task/1"
           }
          ],
          "today": [
           {
            "customer": "Işıltı Film A.Ş.",
            "customer_id": 8,
            "date": "2026-10-02",
            "icon": "📋",
            "id": 2,
            "key": "task:2",
            "kind": "task",
            "label": "Teklif revizyonunu gönder",
            "opp": "",
            "opp_id": null,
            "src": "Görev",
            "state": "soon",
            "url": "/action/task/2"
           }
          ]
         },
         "unread": 0,
         "week": {
          "demos": 1,
          "f2f": 3,
          "f2f_target": 6,
          "label": "28 Eyl – 4 Eki",
          "sub_fresh": false,
          "sub_week": null,
          "tasks_done": 2,
          "tasks_target": 12,
          "visit_target": 10,
          "visits": 7
         }
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/dashboard": {
   "get": {
    "operationId": "workspace_dashboard",
    "summary": "Sales dashboard",
    "description": "Opportunity count and value per stage (in base currency), SLA overruns, companies due for a visit, next steps, upcoming items and weekly targets.",
    "tags": [
     "Workspace"
    ],
    "x-summary-tr": "Satış panosu",
    "x-description-tr": "Aşamalara göre fırsat sayısı ve değeri (ana dövizde), SLA aşımları, ziyareti gelen firmalar, sıradaki adımlar, yaklaşan işler ve haftalık hedefler.",
    "parameters": [
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "description": "Empty = default for my role, `team` = whole team (admins).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "k": {
          "ac": 9,
          "at_risk": 0,
          "demo_all": 28,
          "demo_ok": 22,
          "demo_open": 6,
          "ok_visits": 29,
          "open_actions": 13,
          "opp_value": 11243660.0,
          "opp_weighted": 5169831.0,
          "opps": 28,
          "overdue_actions": 9,
          "overdue_visits": 1,
          "pot_kg": 331000.0,
          "prospect": 21,
          "prospect_pot": 21,
          "soon_actions": 30,
          "soon_visits": 0
         },
         "last_demos": [
          {
           "action_date": "2026-10-06",
           "action_done": false,
           "action_state": "soon",
           "customer_id": 19,
           "date": "2026-10-01",
           "id": 19,
           "line": "",
           "next_action": "Takip",
           "opp_id": 19,
           "product": "HS 30 Isıl Yapışma Laki",
           "product_id": 5,
           "result": "Beklemede",
           "rid": "a0DuuEJElBgUsAw",
           "status": "Deneme Gönderildi, Yapılması Bekleniyor",
           "tech_note": "Numune hatta; sonuç bekleniyor.",
           "user": "Deniz Aksoy"
          },
          {
           "action_date": "2026-10-03",
           "action_done": false,
           "action_state": "soon",
           "customer_id": 20,
           "date": "2026-09-23",
           "id": 20,
           "line": "",
           "next_action": "Takip",
           "opp_id": 20,
           "product": "PU-SB 450 Solvent Bazlı Yapıştırıcı",
           "product_id": 3,
           "result": "Beklemede",
           "rid": "a0DLsCXfV1D035V",
           "status": "Deneme Gönderildi, Yapılması Bekleniyor",
           "tech_note": "Numune hatta; sonuç bekleniyor.",
           "user": "Deniz Aksoy"
          }
         ],
         "mine": false,
         "n_actions": 52,
         "never_visited": 0,
         "next_steps": [
          {
           "bant": 4,
           "base_currency": "EUR",
           "close_date": "2027-01-16",
           "cur_sym": "€",
           "currency": "EUR",
           "customer": "Hanımeli Etiket San. Tic. Ltd. Şti.",
           "customer_city": "Adana",
           "customer_id": 23,
           "days_in_stage": 74,
           "detail_status": "",
           "fc": "Best Case",
           "health": {
            "grade": "warning",
            "label": "dikkat",
            "score": 60
           },
           "health_color": "g",
           "health_manual": true,
           "health_note": "",
           "id": 23,
           "initials": "HE",
           "is_account": false,
           "is_open": true,
           "last_update": "2026-09-30",
           "lifetime_left": 69,
           "line": "",
           "name": "Mevcut Müşteri — Yenileme · 2026",
           "next_step": "Deneme tarihini planla",
           "offer_price": null,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "payment_days": null,
           "potential_kg": 12000.0,
           "prob": 0.5,
           "probability": null,
           "product": "PU-SL 350 Yüksek Performans (retort)",
           "product_id": 2,
           "pu": "€/kg",
           "rid": "006LsST7gv514nh",
           "sla_days": 60,
           "sla_left": -14,
           "source": "Web formu",
           "stage": "Present Solution",
           "stage_label": "Present Solution",
           "start_date": "2026-06-13",
           "trend": "up",
           "trend_label": "Yeşil",
           "type": "Mevcut Müşteri — Yenileme",
           "unit": "kg",
           "unit_code": "kg",
           "value": 806000.0,
           "value_base": 806000.0,
           "value_short": "806K"
          },
          {
           "bant": 4,
           "base_currency": "EUR",
           "close_date": "2026-12-20",
           "cur_sym": "€",
           "currency": "EUR",
           "customer": "Akasya Esnek Ambalaj San. ve Tic. A.Ş.",
           "customer_city": "Bursa",
           "customer_id": 25,
           "days_in_stage": 68,
           "detail_status": "",
           "fc": "Pipeline",
           "health": {
            "grade": "warning",
            "label": "dikkat",
            "score": 66
           },
           "health_color": "y",
           "health_manual": true,
           "health_note": "",
           "id": 25,
           "initials": "AE",
           "is_account": false,
           "is_open": true,
           "last_update": "2026-09-22",
           "lifetime_left": 99,
           "line": "",
           "name": "Yeni Müşteri · 2026",
           "next_step": "Numune gönder",
           "offer_price": null,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "payment_days": null,
           "potential_kg": 8000.0,
           "prob": 0.25,
           "probability": null,
           "product": "PU-SB 450 Solvent Bazlı Yapıştırıcı",
           "product_id": 3,
           "pu": "€/kg",
           "rid": "006Hyi3NMdZrXvO",
           "sla_days": 60,
           "sla_left": -8,
           "source": "Mevcut müşteri",
           "stage": "Viable",
           "stage_label": "Viable",
           "start_date": "2026-07-13",
           "trend": "flat",
           "trend_label": "Otomatik",
           "type": "Yeni Müşteri",
           "unit": "kg",
           "unit_code": "kg",
           "value": 365000.0,
           "value_base": 365000.0,
           "value_short": "365K"
          }
         ],
         "ok": true,
         "sla_over": 4,
         "stage_counts": {
          "Expect to Close": 4,
          "Negotiation": 5,
          "Present Solution": 6,
          "Qualify": 7,
          "Viable": 6
         },
         "stage_value": {
          "Expect to Close": 1416240.0,
          "Negotiation": 2424420.0,
          "Present Solution": 2287000.0,
          "Qualify": 2304000.0,
          "Viable": 2812000.0
         },
         "upcoming": [
          {
           "date": "2026-10-02",
           "head": "Reyhan Paketleme Ltd. Şti.",
           "kind": "opp",
           "sub": "Proje #10 · Expect to Close · sonraki adım",
           "url": "/opportunities/10"
          },
          {
           "date": "2026-10-02",
           "head": "Yıldızlı Paketleme San. Tic. Ltd. Şti.",
           "kind": "opp",
           "sub": "Proje #19 · Present Solution · sonraki adım",
           "url": "/opportunities/19"
          }
         ],
         "visit_due": [
          {
           "active": true,
           "at_risk": false,
           "city": "Adana",
           "currency": "EUR",
           "currency_default": "",
           "id": 9,
           "initials": "KP",
           "last_visit": "2026-07-02",
           "main_contact": {
            "email": "ayse.aydin@kumsalplastik.example",
            "name": "Ayşe Aydın",
            "phone": "0 (322) 000 80 24",
            "wa": "903220008024"
           },
           "name": "Kumsal Plastik Ambalaj San. ve Tic. A.Ş.",
           "next_visit_due": "2026-09-30",
           "open_opps": 0,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "pending_state": null,
           "period": 90,
           "phone": "0 (322) 000 53 49",
           "potential_kg": 12000.0,
           "rid": "001t29x5kWbHOxg",
           "sector": "Esnek ambalaj",
           "status": "AC",
           "status_label": "Aktif Müşteri",
           "unit": "kg",
           "visit_overdue_days": 2,
           "visit_state": "overdue"
          }
         ],
         "week": {
          "demos": 1,
          "f2f": 3,
          "f2f_target": 6,
          "label": "28 Eyl – 4 Eki",
          "n_sales": 1,
          "sub_fresh": false,
          "tasks_done": 2,
          "tasks_due": 10,
          "tasks_target": 12,
          "visit_target": 10,
          "visits": 7,
          "we": "2026-10-04",
          "ws": "2026-09-28"
         }
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/search": {
   "get": {
    "operationId": "workspace_search",
    "summary": "Search",
    "description": "Searches companies (name, city), people (name, phone, e-mail), opportunities and fair leads; up to 10–15 results per type. Passing a 15-character record ID (`001…`, `006…`) resolves it in the `record` field.",
    "tags": [
     "Workspace"
    ],
    "x-summary-tr": "Ara",
    "x-description-tr": "Firma (ad, şehir), kişi (ad, telefon, e-posta), fırsat ve fuar leadlerinde arar; her türden en çok 10–15 sonuç. 15 karakterlik bir kayıt kimliği (`001…`, `006…`) verilirse `record` alanında o kayıt döner.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": true,
      "description": "Search text (at least 2 characters).",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "contacts": [
          {
           "customer": "Alize Paketleme San. ve Tic. A.Ş.",
           "customer_id": 1,
           "department": "Satın Alma",
           "email": "selin.dogan@alizepaketleme.example",
           "id": 1,
           "is_former": false,
           "is_main": true,
           "name": "Selin Doğan",
           "note": "",
           "phone": "0 (212) 000 55 24",
           "rid": "003MaZR2tfJCp1h",
           "title": "Satın Alma Müdürü",
           "wa": "902120005524"
          }
         ],
         "customers": [
          {
           "active": true,
           "at_risk": false,
           "city": "İstanbul",
           "currency": "EUR",
           "currency_default": "",
           "id": 1,
           "initials": "AP",
           "last_visit": "2026-09-30",
           "main_contact": {
            "email": "selin.dogan@alizepaketleme.example",
            "name": "Selin Doğan",
            "phone": "0 (212) 000 55 24",
            "wa": "902120005524"
           },
           "name": "Alize Paketleme San. ve Tic. A.Ş.",
           "next_visit_due": "2026-12-29",
           "open_opps": 1,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "pending_state": "overdue",
           "period": 90,
           "phone": "0 (212) 000 15 65",
           "potential_kg": 8000.0,
           "rid": "001RBoHIo80N8nR",
           "sector": "Gıda ambalajı",
           "status": "AC",
           "status_label": "Aktif Müşteri",
           "unit": "kg",
           "visit_overdue_days": -88,
           "visit_state": "ok"
          }
         ],
         "leads": [
          {
           "can_edit": true,
           "city": "Konya",
           "company": "Alize Ambalaj A.Ş.",
           "contact_name": "Barış Kaya",
           "created_at": "2026-08-25T15:10:00",
           "customer_id": null,
           "email": "baris@alizeambalajas.example",
           "fair": "Ambalaj Fuarı 2026 (örnek)",
           "fair_id": 1,
           "id": 5,
           "initials": "AA",
           "interest": "Sıcak",
           "line": "",
           "next_action": "Teklif gönder",
           "next_date": "2026-10-03",
           "note": "Stantta görüşüldü.",
           "opp_id": null,
           "opp_type": "Yeni Müşteri",
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "phone": "0 (332) 000 44 97",
           "potential_kg": 4000.0,
           "products": "5",
           "products_text": "",
           "project_note": "",
           "rid": "00QiUPO55IJhtmL",
           "sector": "Etiket",
           "status": "Yeni",
           "status_eff": "Yeni",
           "supplier": "Mevcut tedarikçi (Asya)",
           "task_id": null,
           "timing": "3 ay içinde",
           "title": "Genel Müdür",
           "unit": "kg",
           "visitor_type": "Potansiyel müşteri",
           "wa": "903320004497",
           "website": ""
          }
         ],
         "ok": true,
         "opps": [
          {
           "bant": 0,
           "base_currency": "EUR",
           "close_date": "2027-03-31",
           "cur_sym": "€",
           "currency": "EUR",
           "customer": "Alize Paketleme San. ve Tic. A.Ş.",
           "customer_city": "İstanbul",
           "customer_id": 1,
           "days_in_stage": 0,
           "detail_status": "",
           "fc": "Omitted",
           "health": null,
           "health_color": null,
           "health_manual": false,
           "health_note": "",
           "id": 44,
           "initials": "AP",
           "is_account": true,
           "is_open": false,
           "last_update": "2026-10-02",
           "lifetime_left": 180,
           "line": "",
           "name": "Müşteri Takibi",
           "next_step": null,
           "offer_price": null,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "payment_days": null,
           "potential_kg": null,
           "prob": 0.0,
           "probability": null,
           "product": "",
           "product_id": null,
           "pu": "€/kg",
           "rid": "006w4ETEfW9soDW",
           "sla_days": null,
           "sla_left": null,
           "source": "",
           "stage": "Account",
           "stage_label": "Müşteri Takibi",
           "start_date": "2026-10-02",
           "trend": "",
           "trend_label": "Otomatik",
           "type": "Müşteri Takibi",
           "unit": "kg",
           "unit_code": "kg",
           "value": 0,
           "value_base": 0,
           "value_short": "0"
          },
          {
           "bant": 4,
           "base_currency": "EUR",
           "close_date": "2026-10-01",
           "cur_sym": "€",
           "currency": "EUR",
           "customer": "Alize Paketleme San. ve Tic. A.Ş.",
           "customer_city": "İstanbul",
           "customer_id": 1,
           "days_in_stage": 1,
           "detail_status": "",
           "fc": "Closed",
           "health": null,
           "health_color": null,
           "health_manual": false,
           "health_note": "",
           "id": 1,
           "initials": "AP",
           "is_account": false,
           "is_open": false,
           "last_update": "2026-10-01",
           "lifetime_left": 115,
           "line": "",
           "name": "Yeni Müşteri · 2026",
           "next_step": null,
           "offer_price": 3.92,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "payment_days": 120,
           "potential_kg": 1500.0,
           "prob": 1.0,
           "probability": null,
           "product": "PU-SL 200 Solventsiz Laminasyon Yapıştırıcısı",
           "product_id": 1,
           "pu": "€/kg",
           "rid": "006kmnffbRT8muo",
           "sla_days": null,
           "sla_left": null,
           "source": "Bayi / distribütör",
           "stage": "Win",
           "stage_label": "Win",
           "start_date": "2026-07-29",
           "trend": "",
           "trend_label": "Otomatik",
           "type": "Yeni Müşteri",
           "unit": "kg",
           "unit_code": "kg",
           "value": 70560.0,
           "value_base": 70560.0,
           "value_short": "71K"
          }
         ],
         "record": null
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/notifications": {
   "get": {
    "operationId": "workspace_notifications",
    "summary": "List notifications",
    "description": "The user's latest 50 notifications and the unread count.",
    "tags": [
     "Workspace"
    ],
    "x-summary-tr": "Bildirimleri listele",
    "x-description-tr": "Kullanıcının son 50 bildirimi ve okunmamış sayısı.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "rows": [],
         "unread": 0
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/notifications/read": {
   "post": {
    "operationId": "workspace_notifications_read",
    "summary": "Mark notifications read",
    "description": "Marks the given notifications (or all, when `ids` is omitted) as read.",
    "tags": [
     "Workspace"
    ],
    "x-summary-tr": "Bildirimleri okundu say",
    "x-description-tr": "Verilen bildirimleri (ya da `ids` yoksa tümünü) okundu yapar.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "ids": {
          "type": "array",
          "items": {
           "type": "integer"
          },
          "description": "Notification ids."
         }
        }
       },
       "example": {}
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "marked": 0,
         "ok": true
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/recent": {
   "post": {
    "operationId": "workspace_recent",
    "summary": "Add to recently viewed",
    "description": "Adds a record to the user's recently viewed list (cards on Today).",
    "tags": [
     "Workspace"
    ],
    "x-summary-tr": "Son açılanlara ekle",
    "x-description-tr": "Bir kaydı kullanıcının ‘son açılanlar’ listesine ekler (Bugün ekranındaki kartlar).",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "kind": {
          "type": "string",
          "enum": [
           "customer",
           "opp",
           "contact",
           "lead"
          ],
          "description": "Record type."
         },
         "id": {
          "type": "integer",
          "description": "Record id."
         }
        },
        "required": [
         "kind",
         "id"
        ]
       },
       "example": {
        "kind": "customer",
        "id": 1
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/customers": {
   "get": {
    "operationId": "companies_list",
    "summary": "List companies",
    "description": "Filters, sorts and pages active companies. `counts` gives customer / prospect totals and overdue visits for the filtered list.",
    "tags": [
     "Companies"
    ],
    "x-summary-tr": "Firmaları listele",
    "x-description-tr": "Aktif firmaları süzer, sıralar ve sayfalar. `counts` süzülmüş listedeki müşteri / aday sayılarını ve ziyareti geciken firmaları verir.",
    "parameters": [
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "description": "`mine` = records I own (default for sales users), `all` = every record I can see (default for admins), or a user id.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "description": "`AC` = active customer, `Prospect` = prospect.",
      "schema": {
       "type": "string",
       "enum": [
        "AC",
        "Prospect"
       ]
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Name, city or sector contains.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "city",
      "in": "query",
      "required": false,
      "description": "City (exact match).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "visit",
      "in": "query",
      "required": false,
      "description": "Visit schedule state.",
      "schema": {
       "type": "string",
       "enum": [
        "overdue",
        "soon",
        "ok",
        "none"
       ]
      }
     },
     {
      "name": "risk",
      "in": "query",
      "required": false,
      "description": "`1` = only customers at risk.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "active",
      "in": "query",
      "required": false,
      "description": "`0` = inactive (archived) companies.",
      "schema": {
       "type": "string",
       "default": "1"
      }
     },
     {
      "name": "sort",
      "in": "query",
      "required": false,
      "description": "Sort order.",
      "schema": {
       "type": "string",
       "enum": [
        "name",
        "visit",
        "priority"
       ],
       "default": "name"
      }
     },
     {
      "name": "page",
      "in": "query",
      "required": false,
      "description": "Page number (starts at 1).",
      "schema": {
       "type": "integer",
       "default": 1
      }
     },
     {
      "name": "per",
      "in": "query",
      "required": false,
      "description": "Rows per page (10–100).",
      "schema": {
       "type": "integer",
       "default": 40
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "counts": {
          "ac": 9,
          "overdue": 1,
          "prospect": 21,
          "soon": 0
         },
         "ok": true,
         "page": 1,
         "pages": 3,
         "rows": [
          {
           "active": true,
           "at_risk": false,
           "city": "Adana",
           "currency": "EUR",
           "currency_default": "",
           "id": 9,
           "initials": "KP",
           "last_visit": "2026-07-02",
           "main_contact": {
            "email": "ayse.aydin@kumsalplastik.example",
            "name": "Ayşe Aydın",
            "phone": "0 (322) 000 80 24",
            "wa": "903220008024"
           },
           "name": "Kumsal Plastik Ambalaj San. ve Tic. A.Ş.",
           "next_visit_due": "2026-09-30",
           "open_opps": 0,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "pending_state": null,
           "period": 90,
           "phone": "0 (322) 000 53 49",
           "potential_kg": 12000.0,
           "rid": "001t29x5kWbHOxg",
           "sector": "Esnek ambalaj",
           "status": "AC",
           "status_label": "Aktif Müşteri",
           "unit": "kg",
           "visit_overdue_days": 2,
           "visit_state": "overdue"
          },
          {
           "active": true,
           "at_risk": false,
           "city": "Konya",
           "currency": "EUR",
           "currency_default": "",
           "id": 8,
           "initials": "IF",
           "last_visit": "2026-08-25",
           "main_contact": {
            "email": "gizem.arslan@isiltifilm.example",
            "name": "Gizem Arslan",
            "phone": "0 (332) 000 94 28",
            "wa": "903320009428"
           },
           "name": "Işıltı Film A.Ş.",
           "next_visit_due": "2026-11-23",
           "open_opps": 0,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "pending_state": null,
           "period": 90,
           "phone": "0 (332) 000 99 70",
           "potential_kg": 40000.0,
           "rid": "001frrIzBuo8ERp",
           "sector": "Film üretimi",
           "status": "AC",
           "status_label": "Aktif Müşteri",
           "unit": "kg",
           "visit_overdue_days": -52,
           "visit_state": "ok"
          }
         ],
         "total": 30
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   },
   "post": {
    "operationId": "companies_create",
    "summary": "Create a company",
    "description": "Creates a company (status `Prospect` unless given, owned by the caller). An existing name returns `409 exists`; similar names return `409 similar` with a `similar` list — send `confirm_new: true` to create anyway. Optionally creates the first contact.",
    "tags": [
     "Companies"
    ],
    "x-summary-tr": "Firma oluştur",
    "x-description-tr": "Yeni firma açar (durum verilmezse `Prospect`, sorumlu isteği yapan kullanıcı). Aynı adda firma varsa `409 exists`, benzer adlar varsa `409 similar` döner ve `similar` listesi gelir — yine de açmak için `confirm_new: true` gönderin. İsteğe bağlı olarak ilk kişi de açılır.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string",
          "description": "Company name (max 200 characters)."
         },
         "status": {
          "type": "string",
          "enum": [
           "AC",
           "Prospect"
          ],
          "description": "Status."
         },
         "city": {
          "type": "string",
          "description": "City."
         },
         "sector": {
          "type": "string",
          "description": "Sector."
         },
         "phone": {
          "type": "string",
          "description": "Phone."
         },
         "website": {
          "type": "string",
          "description": "Website."
         },
         "address": {
          "type": "string",
          "description": "Address."
         },
         "note": {
          "type": "string",
          "description": "Note."
         },
         "owner_id": {
          "type": "integer",
          "description": "Owner user id (admins only)."
         },
         "visit_period_days": {
          "type": "integer",
          "description": "Visit every N days."
         },
         "potential_kg": {
          "type": "number",
          "description": "Monthly potential quantity (installation's base unit)."
         },
         "contact_name": {
          "type": "string",
          "description": "First contact's name (becomes the main contact)."
         },
         "contact_title": {
          "type": "string",
          "description": "First contact's job title."
         },
         "contact_email": {
          "type": "string",
          "description": "First contact's e-mail."
         },
         "contact_phone": {
          "type": "string",
          "description": "First contact's phone."
         },
         "confirm_new": {
          "type": "boolean",
          "description": "Create even if similar names exist."
         }
        },
        "required": [
         "name"
        ]
       },
       "example": {
        "name": "Kuzey Plastik Sanayi",
        "city": "Bursa",
        "sector": "Plastik",
        "phone": "+90 224 555 01 02",
        "website": "kuzeyplastik.com.tr",
        "contact_name": "Selin Kara",
        "contact_title": "Satın Alma Müdürü",
        "contact_email": "selin.kara@kuzeyplastik.com.tr",
        "confirm_new": true
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "customer": {
          "act": {
           "addr": "Bursa",
           "c": 31,
           "mail": "selin.kara@kuzeyplastik.com.tr",
           "n": "Kuzey Plastik Sanayi",
           "tel": "+90 224 555 01 02",
           "url": "/customers/31",
           "wa": "902245550102",
           "who": "Selin Kara"
          },
          "active": true,
          "address": "",
          "at_risk": false,
          "barrier": "",
          "can_edit": true,
          "city": "Bursa",
          "commit_kg": null,
          "competitors": [],
          "contacts": [
           {
            "customer": "Kuzey Plastik Sanayi",
            "customer_id": 31,
            "department": "",
            "email": "selin.kara@kuzeyplastik.com.tr",
            "id": 58,
            "is_former": false,
            "is_main": true,
            "name": "Selin Kara",
            "note": "",
            "phone": "",
            "rid": "003URRQi11tfUY7",
            "title": "Satın Alma Müdürü",
            "wa": ""
           }
          ],
          "created_at": "2026-10-02T20:07:00",
          "currency": "EUR",
          "currency_default": "",
          "demos": [],
          "events": [
           {
            "badge": null,
            "dot": "#94a3b8",
            "icon": "building",
            "kind": "firma",
            "note": "",
            "opp_id": null,
            "planned": false,
            "state": null,
            "sub": "Firma #31 · Deniz Aksoy",
            "title": "Firma kaydı açıldı",
            "url": "",
            "when": "2026-10-02",
            "who": ""
           }
          ],
          "extra_kg": null,
          "id": 31,
          "initials": "KP",
          "last_visit": null,
          "main_contact": {
           "email": "selin.kara@kuzeyplastik.com.tr",
           "name": "Selin Kara",
           "phone": "",
           "wa": ""
          },
          "mgmt_note": "",
          "mgmt_support": false,
          "name": "Kuzey Plastik Sanayi",
          "next_visit_due": null,
          "note": "",
          "offers": [],
          "open_actions": [],
          "open_opps": 0,
          "opps": [],
          "orders": [],
          "our_kg_current": null,
          "our_kg_target": null,
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "pending_state": null,
          "period": 180,
          "phone": "+90 224 555 01 02",
          "potential_kg": null,
          "prices": [],
          "priority_score": 0.0,
          "rid": "001QJi5Zr1Hk2VH",
          "sector": "Plastik",
          "share_current": null,
          "share_start": null,
          "share_target": null,
          "status": "Prospect",
          "status_label": "Prospect",
          "supplier_note": "",
          "threads": [],
          "threads_n": 0,
          "unit": "kg",
          "visit_overdue_days": 0,
          "visit_period_days": null,
          "visit_postponed_until": null,
          "visit_state": "none",
          "visits": [],
          "website": "kuzeyplastik.com.tr"
         },
         "ok": true
        }
       }
      }
     },
     "409": {
      "description": "Error",
      "content": {
       "application/json": {
        "example": {
         "error": "similar",
         "message": "Benzer adlı firma var — mevcut kaydı seçin ya da confirm_new=1 ile yeni açın.",
         "ok": false,
         "similar": [
          {
           "active": true,
           "at_risk": false,
           "city": "Kocaeli",
           "currency": "EUR",
           "currency_default": "",
           "id": 2,
           "initials": "FA",
           "last_visit": "2026-09-24",
           "main_contact": {
            "email": "elif.karaca@filizambalaj.example",
            "name": "Elif Karaca",
            "phone": "0 (262) 000 27 12",
            "wa": "902620002712"
           },
           "name": "Filiz Ambalaj Ltd. Şti.",
           "next_visit_due": "2026-12-23",
           "open_opps": 1,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "pending_state": "soon",
           "period": 90,
           "phone": "0 (262) 000 83 56",
           "potential_kg": 40000.0,
           "rid": "001rutEPiRkEPfD",
           "sector": "Gıda ambalajı",
           "status": "AC",
           "status_label": "Aktif Müşteri",
           "unit": "kg",
           "visit_overdue_days": -82,
           "visit_state": "ok"
          }
         ]
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/customers/{id}": {
   "get": {
    "operationId": "companies_get",
    "summary": "Get a company",
    "description": "The full company card: people, opportunities, recent visits and trials, open actions, offers, orders, timeline, competitors, prices and e-mail threads (`threads`).",
    "tags": [
     "Companies"
    ],
    "x-summary-tr": "Firmayı getir",
    "x-description-tr": "Firma kartının tamamı: kişiler, fırsatlar, son ziyaretler ve denemeler, açık aksiyonlar, teklifler, siparişler, zaman tüneli, rakipler, fiyatlar ve e-posta yazışmaları (`threads`).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Company id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "customer": {
          "act": {
           "addr": "İstanbul Organize Sanayi Bölgesi, 3. Cadde No: 25, İstanbul, İstanbul",
           "c": 1,
           "mail": "selin.dogan@alizepaketleme.example",
           "n": "Alize Paketleme San. ve Tic. A.Ş.",
           "tel": "0 (212) 000 55 24",
           "url": "/customers/1",
           "wa": "902120005524",
           "who": "Selin Doğan"
          },
          "active": true,
          "address": "İstanbul Organize Sanayi Bölgesi, 3. Cadde No: 25, İstanbul",
          "at_risk": false,
          "barrier": "",
          "can_edit": true,
          "city": "İstanbul",
          "commit_kg": 1700.0,
          "competitors": [],
          "contacts": [
           {
            "customer": "Alize Paketleme San. ve Tic. A.Ş.",
            "customer_id": 1,
            "department": "Satın Alma",
            "email": "selin.dogan@alizepaketleme.example",
            "id": 1,
            "is_former": false,
            "is_main": true,
            "name": "Selin Doğan",
            "note": "",
            "phone": "0 (212) 000 55 24",
            "rid": "003MaZR2tfJCp1h",
            "title": "Satın Alma Müdürü",
            "wa": "902120005524"
           }
          ],
          "created_at": "2026-03-25T09:00:00",
          "currency": "EUR",
          "currency_default": "",
          "demos": [
           {
            "action_date": "2026-09-02",
            "action_done": true,
            "action_state": "done",
            "customer_id": 1,
            "date": "2026-08-28",
            "id": 1,
            "line": "",
            "next_action": "Fiyat Teklifi",
            "opp_id": 1,
            "product": "PU-SL 200 Solventsiz Laminasyon Yapıştırıcısı",
            "product_id": 1,
            "result": "Başarılı",
            "rid": "a0DZ6tZKUceyZxW",
            "status": "Deneme Gerçekleştirilmiştir",
            "tech_note": "Mürekkep uyumu iyi; şeffaflık beklentiyi karşıladı.",
            "user": "Deniz Aksoy"
           }
          ],
          "events": [
           {
            "badge": null,
            "dot": "#94a3b8",
            "icon": "geo-alt",
            "kind": "plan",
            "note": "",
            "opp_id": null,
            "planned": true,
            "state": null,
            "sub": "periyot 90 gün · son ziyaret 30.09.2026",
            "title": "Planlanan: ziyaret vadesi",
            "url": "",
            "when": "2026-12-29",
            "who": ""
           }
          ],
          "extra_kg": 800.0,
          "id": 1,
          "initials": "AP",
          "last_visit": "2026-09-30",
          "main_contact": {
           "email": "selin.dogan@alizepaketleme.example",
           "name": "Selin Doğan",
           "phone": "0 (212) 000 55 24",
           "wa": "902120005524"
          },
          "mgmt_note": "",
          "mgmt_support": false,
          "name": "Alize Paketleme San. ve Tic. A.Ş.",
          "next_visit_due": "2026-12-29",
          "note": "",
          "offers": [
           {
            "currency": "EUR",
            "date": "2026-09-09",
            "id": 1,
            "is_primary": true,
            "kg": 1500.0,
            "lines": 1,
            "locked": true,
            "monthly_amount": 5880.0,
            "payment_days": 120,
            "pdf_url": "/offers/1/pdf",
            "price": 3.92,
            "product": "PU-SL 200 Solventsiz Laminasyon Yapıştırıcısı",
            "pu": "€/kg",
            "quote_no": "TKL-2026-0001",
            "state": "presented",
            "status": "Kabul",
            "unit": "kg",
            "valid_until": "2026-10-09"
           }
          ],
          "open_actions": [
           {
            "customer": "",
            "customer_id": null,
            "date": "2026-09-30",
            "icon": "⚡",
            "id": 74,
            "key": "visit:74",
            "kind": "visit",
            "label": "Ziyaret Planla",
            "opp": "Mevcut Müşteri — Yenileme · 2026",
            "opp_id": 31,
            "src": "Ziyaret",
            "state": "overdue",
            "url": "/action/visit/74"
           }
          ],
          "open_opps": 1,
          "opps": [
           {
            "bant": 0,
            "base_currency": "EUR",
            "close_date": "2027-03-31",
            "cur_sym": "€",
            "currency": "EUR",
            "customer": "Alize Paketleme San. ve Tic. A.Ş.",
            "customer_city": "İstanbul",
            "customer_id": 1,
            "days_in_stage": 0,
            "detail_status": "",
            "fc": "Omitted",
            "health": null,
            "health_color": null,
            "health_manual": false,
            "health_note": "",
            "id": 44,
            "initials": "AP",
            "is_account": true,
            "is_open": false,
            "last_update": "2026-10-02",
            "lifetime_left": 180,
            "line": "",
            "name": "Müşteri Takibi",
            "next_step": null,
            "offer_price": null,
            "owner": {
             "full_name": "Deniz Aksoy",
             "id": 1,
             "role": "admin",
             "role_label": "Yönetici",
             "username": "admin"
            },
            "payment_days": null,
            "potential_kg": null,
            "prob": 0.0,
            "probability": null,
            "product": "",
            "product_id": null,
            "pu": "€/kg",
            "rid": "006w4ETEfW9soDW",
            "sla_days": null,
            "sla_left": null,
            "source": "",
            "stage": "Account",
            "stage_label": "Müşteri Takibi",
            "start_date": "2026-10-02",
            "trend": "",
            "trend_label": "Otomatik",
            "type": "Müşteri Takibi",
            "unit": "kg",
            "unit_code": "kg",
            "value": 0,
            "value_base": 0,
            "value_short": "0"
           }
          ],
          "orders": [
           {
            "currency": "EUR",
            "date": "2026-10-02",
            "id": 1,
            "kg": 700.0,
            "kind": "İlk Sipariş",
            "note": "",
            "opp_id": 1,
            "payment_days": 120,
            "price": 3.92,
            "product": "PU-SL 200 Solventsiz Laminasyon Yapıştırıcısı",
            "pu": "€/kg",
            "unit": "kg"
           }
          ],
          "our_kg_current": 1600.0,
          "our_kg_target": 2400.0,
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "pending_state": "overdue",
          "period": 90,
          "phone": "0 (212) 000 15 65",
          "potential_kg": 8000.0,
          "prices": [
           {
            "currency": "EUR",
            "id": 1,
            "payment_days": 120,
            "price": 3.92,
            "product": "PU-SL 200 Solventsiz Laminasyon Yapıştırıcısı",
            "product_id": 1,
            "pu": "€/kg",
            "source": "TKL-2026-0001 (Win)",
            "valid_until": "2027-10-01"
           }
          ],
          "priority_score": 50.0,
          "rid": "001RBoHIo80N8nR",
          "sector": "Gıda ambalajı",
          "share_current": 20.0,
          "share_start": null,
          "share_target": 30.0,
          "status": "AC",
          "status_label": "Aktif Müşteri",
          "supplier_note": "Distribütör ürünü",
          "threads": [
           {
            "customer": "Alize Paketleme San. ve Tic. A.Ş.",
            "customer_id": 1,
            "id": 1,
            "last_at": "2026-10-01T15:06:59",
            "last_dir": "out",
            "n": 2,
            "opp": "Mevcut Müşteri — Yenileme · 2026",
            "opp_how": "single",
            "opp_id": 31,
            "opp_note": "firmanın tek açık projesi",
            "peer": "selin.dogan@alizepaketleme.example",
            "subject": "Numune ve fiyat teklifi",
            "suggested": false,
            "waiting": false
           }
          ],
          "threads_n": 1,
          "unit": "kg",
          "visit_overdue_days": -88,
          "visit_period_days": null,
          "visit_postponed_until": null,
          "visit_state": "ok",
          "visits": [
           {
            "action_date": "2026-09-30",
            "action_done": false,
            "action_state": "overdue",
            "contact": "Selin Doğan",
            "customer": "Alize Paketleme San. ve Tic. A.Ş.",
            "customer_id": 1,
            "date": "2026-09-30",
            "id": 74,
            "line": "",
            "next_action": "Ziyaret Planla",
            "note": "Hat 2'de tünelleşme sorunu konuşuldu; solventsiz sisteme geçiş planlıyorlar.",
            "opp": "Mevcut Müşteri — Yenileme · 2026",
            "opp_id": 31,
            "product": "",
            "result": "Teklif istendi",
            "rid": "00U2wBTaDRg4JXL",
            "topic": "Tanışma",
            "type": "Call",
            "user": "Deniz Aksoy"
           }
          ],
          "website": "www.alizepaketleme.example"
         },
         "ok": true
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   },
   "patch": {
    "operationId": "companies_update",
    "summary": "Update a company",
    "description": "Only the fields you send change; an empty string clears a text field. `PUT` and `POST` are accepted too. Requires edit rights on the company (owner, admin or a user allowed by the visibility rule).",
    "tags": [
     "Companies"
    ],
    "x-summary-tr": "Firmayı güncelle",
    "x-description-tr": "Yalnız gönderilen alanlar değişir; boş metin alanı temizler. `PUT` ve `POST` da kabul edilir. Firmayı düzenleme yetkisi gerekir (sorumlu, yönetici ya da görünürlük kuralının izin verdiği kullanıcı).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Company id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string",
          "description": "Company name."
         },
         "status": {
          "type": "string",
          "enum": [
           "AC",
           "Prospect"
          ],
          "description": "Status."
         },
         "owner_id": {
          "type": "integer",
          "description": "Owner (admins only)."
         },
         "visit_period_days": {
          "type": "integer",
          "description": "Visit frequency (days)."
         },
         "sector": {
          "type": "string",
          "description": "Text fields."
         },
         "city": {
          "type": "string",
          "description": "Text fields."
         },
         "phone": {
          "type": "string",
          "description": "Text fields."
         },
         "website": {
          "type": "string",
          "description": "Text fields."
         },
         "address": {
          "type": "string",
          "description": "Text fields."
         },
         "note": {
          "type": "string",
          "description": "Text fields."
         },
         "supplier_note": {
          "type": "string",
          "description": "Current supplier, barrier and management note."
         },
         "barrier": {
          "type": "string",
          "description": "Current supplier, barrier and management note."
         },
         "mgmt_note": {
          "type": "string",
          "description": "Current supplier, barrier and management note."
         },
         "potential_kg": {
          "type": "number",
          "description": "Quantity fields (monthly)."
         },
         "commit_kg": {
          "type": "number",
          "description": "Quantity fields (monthly)."
         },
         "our_kg_current": {
          "type": "number",
          "description": "Quantity fields (monthly)."
         },
         "our_kg_target": {
          "type": "number",
          "description": "Quantity fields (monthly)."
         },
         "share_start": {
          "type": "number",
          "description": "Share-of-wallet percentages."
         },
         "share_current": {
          "type": "number",
          "description": "Share-of-wallet percentages."
         },
         "share_target": {
          "type": "number",
          "description": "Share-of-wallet percentages."
         },
         "mgmt_support": {
          "type": "boolean",
          "description": "Management support."
         }
        }
       },
       "example": {
        "status": "AC",
        "visit_period_days": 30,
        "note": "Yıllık sözleşme görüşülüyor."
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "customer": {
          "act": {
           "addr": "Bursa",
           "c": 31,
           "mail": "selin.kara@kuzeyplastik.com.tr",
           "n": "Kuzey Plastik Sanayi",
           "tel": "+90 224 555 01 02",
           "url": "/customers/31",
           "wa": "902245550102",
           "who": "Selin Kara"
          },
          "active": true,
          "address": "",
          "at_risk": true,
          "barrier": "",
          "can_edit": true,
          "city": "Bursa",
          "commit_kg": null,
          "competitors": [],
          "contacts": [
           {
            "customer": "Kuzey Plastik Sanayi",
            "customer_id": 31,
            "department": "",
            "email": "selin.kara@kuzeyplastik.com.tr",
            "id": 58,
            "is_former": false,
            "is_main": true,
            "name": "Selin Kara",
            "note": "",
            "phone": "",
            "rid": "003URRQi11tfUY7",
            "title": "Satın Alma Müdürü",
            "wa": ""
           }
          ],
          "created_at": "2026-10-02T20:07:00",
          "currency": "EUR",
          "currency_default": "",
          "demos": [],
          "events": [
           {
            "badge": null,
            "dot": "#94a3b8",
            "icon": "building",
            "kind": "firma",
            "note": "",
            "opp_id": null,
            "planned": false,
            "state": null,
            "sub": "Firma #31 · Deniz Aksoy",
            "title": "Firma kaydı açıldı",
            "url": "",
            "when": "2026-10-02",
            "who": ""
           }
          ],
          "extra_kg": null,
          "id": 31,
          "initials": "KP",
          "last_visit": null,
          "main_contact": {
           "email": "selin.kara@kuzeyplastik.com.tr",
           "name": "Selin Kara",
           "phone": "",
           "wa": ""
          },
          "mgmt_note": "",
          "mgmt_support": false,
          "name": "Kuzey Plastik Sanayi",
          "next_visit_due": null,
          "note": "Yıllık sözleşme görüşülüyor.",
          "offers": [],
          "open_actions": [],
          "open_opps": 0,
          "opps": [],
          "orders": [],
          "our_kg_current": null,
          "our_kg_target": null,
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "pending_state": null,
          "period": 30,
          "phone": "+90 224 555 01 02",
          "potential_kg": null,
          "prices": [],
          "priority_score": 0.0,
          "rid": "001QJi5Zr1Hk2VH",
          "sector": "Plastik",
          "share_current": null,
          "share_start": null,
          "share_target": null,
          "status": "AC",
          "status_label": "Aktif Müşteri",
          "supplier_note": "",
          "threads": [],
          "threads_n": 0,
          "unit": "kg",
          "visit_overdue_days": 0,
          "visit_period_days": 30,
          "visit_postponed_until": null,
          "visit_state": "none",
          "visits": [],
          "website": "kuzeyplastik.com.tr"
         },
         "ok": true
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/customers/{id}/postpone": {
   "post": {
    "operationId": "companies_postpone",
    "summary": "Postpone the visit",
    "description": "Moves the company's visit due date. Uses `date` when given, otherwise `days` from today (default 7).",
    "tags": [
     "Companies"
    ],
    "x-summary-tr": "Ziyareti ertele",
    "x-description-tr": "Firmanın ziyaret terminini ileri alır. `date` verilirse o gün, yoksa `days` gün sonrası (varsayılan 7).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Company id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "date": {
          "type": "string",
          "description": "New date (YYYY-MM-DD)."
         },
         "days": {
          "type": "integer",
          "description": "Number of days."
         },
         "note": {
          "type": "string",
          "description": "Reason."
         }
        }
       },
       "example": {
        "days": 14,
        "note": "Fabrika bakımda"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "customer": {
          "active": true,
          "at_risk": false,
          "city": "Bursa",
          "currency": "EUR",
          "currency_default": "",
          "id": 31,
          "initials": "KP",
          "last_visit": null,
          "main_contact": {
           "email": "selin.kara@kuzeyplastik.com.tr",
           "name": "Selin Kara",
           "phone": "",
           "wa": ""
          },
          "name": "Kuzey Plastik Sanayi",
          "next_visit_due": "2026-10-16",
          "open_opps": 0,
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "pending_state": null,
          "period": 30,
          "phone": "+90 224 555 01 02",
          "potential_kg": null,
          "rid": "001QJi5Zr1Hk2VH",
          "sector": "Plastik",
          "status": "AC",
          "status_label": "Aktif Müşteri",
          "unit": "kg",
          "visit_overdue_days": -14,
          "visit_state": "ok"
         },
         "ok": true,
         "until": "2026-10-16"
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/customers/{id}/lookup": {
   "get": {
    "operationId": "companies_lookup",
    "summary": "Activity form options",
    "description": "What an activity (quick entry) form needs: the company's open projects, the default project, people, open actions and last stage label.",
    "tags": [
     "Companies"
    ],
    "x-summary-tr": "Görüşme formu seçenekleri",
    "x-description-tr": "Görüşme kaydı (hızlı giriş) formunu doldurmak için firmanın açık projeleri, varsayılan proje, kişileri, açık aksiyonları ve son aşama etiketi.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Company id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "city": "İstanbul",
         "competitor": "Distribütör ürünü",
         "contacts": [
          {
           "customer": "Alize Paketleme San. ve Tic. A.Ş.",
           "customer_id": 1,
           "department": "Satın Alma",
           "email": "selin.dogan@alizepaketleme.example",
           "id": 1,
           "is_former": false,
           "is_main": true,
           "name": "Selin Doğan",
           "note": "",
           "phone": "0 (212) 000 55 24",
           "rid": "003MaZR2tfJCp1h",
           "title": "Satın Alma Müdürü",
           "wa": "902120005524"
          }
         ],
         "default_project": 31,
         "id": 1,
         "name": "Alize Paketleme San. ve Tic. A.Ş.",
         "ok": true,
         "open_actions": [
          {
           "customer": "",
           "customer_id": null,
           "date": "2026-09-30",
           "icon": "⚡",
           "id": 74,
           "key": "visit:74",
           "kind": "visit",
           "label": "Ziyaret Planla",
           "opp": "Mevcut Müşteri — Yenileme · 2026",
           "opp_id": 31,
           "src": "Ziyaret",
           "state": "overdue",
           "url": "/action/visit/74"
          }
         ],
         "opp_type": "Mevcut Müşteri — Yenileme",
         "potential_kg": 8000.0,
         "projects": [
          {
           "id": 31,
           "name": "Mevcut Müşteri — Yenileme · 2026",
           "stage": "Qualify"
          },
          {
           "id": 44,
           "name": "Müşteri Takibi",
           "stage": "Müşteri Takibi"
          }
         ],
         "stage": "Qualify",
         "stage_label": "",
         "status": "AC"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/contacts": {
   "get": {
    "operationId": "people_list",
    "summary": "List people",
    "description": "People of active companies (max 300, by name). Former employees are excluded by default.",
    "tags": [
     "People"
    ],
    "x-summary-tr": "Kişileri listele",
    "x-description-tr": "Aktif firmaların kişileri (en çok 300, ada göre). Ayrılmış kişiler varsayılan olarak gelmez.",
    "parameters": [
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "description": "`mine` = records I own (default for sales users), `all` = every record I can see (default for admins), or a user id.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Name, company, phone, e-mail or title contains.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "former",
      "in": "query",
      "required": false,
      "description": "`1` = include former employees.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "rows": [
          {
           "customer": "Ortanca Matbaacılık Ltd. Şti.",
           "customer_id": 22,
           "department": "Satın Alma",
           "email": "ahmet.aydin@ortancamatbaacilik.example",
           "id": 42,
           "is_former": false,
           "is_main": true,
           "name": "Ahmet Aydın",
           "note": "",
           "phone": "0 (332) 000 81 52",
           "rid": "003qMFfAArgzPDF",
           "title": "Satın Alma Müdürü",
           "wa": "903320008152"
          },
          {
           "customer": "Kamelya Lamine Film Ltd. Şti.",
           "customer_id": 6,
           "department": "Teknik",
           "email": "ahmet.ozturk@kamelyalamine.example",
           "id": 11,
           "is_former": false,
           "is_main": true,
           "name": "Ahmet Öztürk",
           "note": "",
           "phone": "0 (232) 000 89 83",
           "rid": "003t3MMhbXHOFjR",
           "title": "Teknik Müdür",
           "wa": "902320008983"
          }
         ],
         "total": 58
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/customers/{id}/contacts": {
   "post": {
    "operationId": "people_create",
    "summary": "Create a person",
    "description": "Adds a person to a company. The company's first person, or one sent with `is_main: true`, becomes the main contact.",
    "tags": [
     "People"
    ],
    "x-summary-tr": "Kişi ekle",
    "x-description-tr": "Firmaya kişi ekler. Firmanın ilk kişisi ya da `is_main: true` ise ana kişi olur.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Company id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string",
          "description": "Full name."
         },
         "title": {
          "type": "string",
          "description": "Job title."
         },
         "department": {
          "type": "string",
          "description": "Department."
         },
         "email": {
          "type": "string",
          "description": "E-mail."
         },
         "phone": {
          "type": "string",
          "description": "Phone."
         },
         "is_main": {
          "type": "boolean",
          "description": "Make main contact."
         },
         "note": {
          "type": "string",
          "description": "Note (250 characters)."
         }
        },
        "required": [
         "name"
        ]
       },
       "example": {
        "name": "Emre Yıldız",
        "title": "Üretim Şefi",
        "department": "Üretim",
        "phone": "+90 532 555 11 22",
        "email": "emre.yildiz@kuzeyplastik.com.tr"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "contact": {
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "department": "Üretim",
          "email": "emre.yildiz@kuzeyplastik.com.tr",
          "id": 59,
          "is_former": false,
          "is_main": false,
          "name": "Emre Yıldız",
          "note": "",
          "phone": "+90 532 555 11 22",
          "rid": "0037CJrFvjDFvYX",
          "title": "Üretim Şefi",
          "wa": "905325551122"
         },
         "ok": true
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/contacts/{id}": {
   "patch": {
    "operationId": "people_update",
    "summary": "Update a person",
    "description": "Only the fields you send change. `is_former: true` marks the person as left (not deleted); `is_main: true` makes them the main contact.",
    "tags": [
     "People"
    ],
    "x-summary-tr": "Kişiyi güncelle",
    "x-description-tr": "Yalnız gönderilen alanlar değişir. `is_former: true` kişiyi ‘ayrıldı’ yapar (silinmez); `is_main: true` ana kişi yapar.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Person id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "name": {
          "type": "string",
          "description": "Text fields."
         },
         "title": {
          "type": "string",
          "description": "Text fields."
         },
         "department": {
          "type": "string",
          "description": "Text fields."
         },
         "phone": {
          "type": "string",
          "description": "Text fields."
         },
         "email": {
          "type": "string",
          "description": "Text fields."
         },
         "note": {
          "type": "string",
          "description": "Text fields."
         },
         "is_main": {
          "type": "boolean",
          "description": "Make main contact."
         },
         "is_former": {
          "type": "boolean",
          "description": "Left the company."
         }
        }
       },
       "example": {
        "title": "Fabrika Müdürü",
        "is_main": true
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "contact": {
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "department": "Üretim",
          "email": "emre.yildiz@kuzeyplastik.com.tr",
          "id": 59,
          "is_former": false,
          "is_main": true,
          "name": "Emre Yıldız",
          "note": "",
          "phone": "+90 532 555 11 22",
          "rid": "0037CJrFvjDFvYX",
          "title": "Fabrika Müdürü",
          "wa": "905325551122"
         },
         "ok": true
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/opportunities": {
   "get": {
    "operationId": "deals_list",
    "summary": "List opportunities",
    "description": "Filters, sorts and pages opportunities (sales projects). The response also carries open-stage counts, the open total in base currency and the number of SLA overruns.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Fırsatları listele",
    "x-description-tr": "Fırsatları (satış projeleri) süzer, sıralar ve sayfalar. Yanıtta açık aşama sayıları, açık fırsatların ana dövizdeki toplamı ve SLA aşımı sayısı da gelir.",
    "parameters": [
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "description": "`mine` = records I own (default for sales users), `all` = every record I can see (default for admins), or a user id.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "stage",
      "in": "query",
      "required": false,
      "description": "`open` (default), `closed`, `account` (customer follow-up containers) or a stage key (`/me` → `constants.stages`).",
      "schema": {
       "type": "string",
       "default": "open"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Opportunity or company name contains.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sort",
      "in": "query",
      "required": false,
      "description": "Sort order.",
      "schema": {
       "type": "string",
       "enum": [
        "update",
        "health",
        "value",
        "sla"
       ],
       "default": "update"
      }
     },
     {
      "name": "page",
      "in": "query",
      "required": false,
      "description": "Page number (starts at 1).",
      "schema": {
       "type": "integer",
       "default": 1
      }
     },
     {
      "name": "per",
      "in": "query",
      "required": false,
      "description": "Rows per page (10–100).",
      "schema": {
       "type": "integer",
       "default": 40
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "base_currency": "EUR",
         "ok": true,
         "page": 1,
         "pages": 3,
         "rows": [
          {
           "bant": 4,
           "base_currency": "EUR",
           "close_date": "2026-11-12",
           "cur_sym": "€",
           "currency": "EUR",
           "customer": "Sardunya Etiket Ltd. Şti.",
           "customer_city": "Eskişehir",
           "customer_id": 14,
           "days_in_stage": 12,
           "detail_status": "",
           "fc": "Best Case",
           "health": {
            "grade": "success",
            "label": "sağlıklı",
            "score": 100
           },
           "health_color": "g",
           "health_manual": true,
           "health_note": "",
           "id": 14,
           "initials": "SE",
           "is_account": false,
           "is_open": true,
           "last_update": "2026-10-01",
           "lifetime_left": 106,
           "line": "",
           "name": "Mevcut Müşteri — Ek Satış · 2026",
           "next_step": "Vade ve teslim koşullarını görüş",
           "offer_price": 6.12,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "payment_days": 120,
           "potential_kg": 12000.0,
           "prob": 0.75,
           "probability": null,
           "product": "HS 30 Isıl Yapışma Laki",
           "product_id": 5,
           "pu": "€/kg",
           "rid": "006riIxDf4YpLLv",
           "sla_days": 30,
           "sla_left": 18,
           "source": "Soğuk arama",
           "stage": "Negotiation",
           "stage_label": "Negotiation",
           "start_date": "2026-07-20",
           "trend": "up",
           "trend_label": "Yeşil",
           "type": "Mevcut Müşteri — Ek Satış",
           "unit": "kg",
           "unit_code": "kg",
           "value": 881280.0,
           "value_base": 881280.0,
           "value_short": "881K"
          },
          {
           "bant": 4,
           "base_currency": "EUR",
           "close_date": "2027-01-16",
           "cur_sym": "€",
           "currency": "EUR",
           "customer": "Hanımeli Etiket San. Tic. Ltd. Şti.",
           "customer_city": "Adana",
           "customer_id": 23,
           "days_in_stage": 74,
           "detail_status": "",
           "fc": "Best Case",
           "health": {
            "grade": "warning",
            "label": "dikkat",
            "score": 60
           },
           "health_color": "g",
           "health_manual": true,
           "health_note": "",
           "id": 23,
           "initials": "HE",
           "is_account": false,
           "is_open": true,
           "last_update": "2026-09-30",
           "lifetime_left": 69,
           "line": "",
           "name": "Mevcut Müşteri — Yenileme · 2026",
           "next_step": "Deneme tarihini planla",
           "offer_price": null,
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "payment_days": null,
           "potential_kg": 12000.0,
           "prob": 0.5,
           "probability": null,
           "product": "PU-SL 350 Yüksek Performans (retort)",
           "product_id": 2,
           "pu": "€/kg",
           "rid": "006LsST7gv514nh",
           "sla_days": 60,
           "sla_left": -14,
           "source": "Web formu",
           "stage": "Present Solution",
           "stage_label": "Present Solution",
           "start_date": "2026-06-13",
           "trend": "up",
           "trend_label": "Yeşil",
           "type": "Mevcut Müşteri — Yenileme",
           "unit": "kg",
           "unit_code": "kg",
           "value": 806000.0,
           "value_base": 806000.0,
           "value_short": "806K"
          }
         ],
         "sla_over": 4,
         "stage_counts": {
          "Expect to Close": 4,
          "Negotiation": 5,
          "Present Solution": 6,
          "Qualify": 7,
          "Viable": 6
         },
         "total": 28,
         "value_open": 11243660.0
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   },
   "post": {
    "operationId": "deals_create",
    "summary": "Create an opportunity",
    "description": "Opens a sales project for a company in the first open stage and sets up its stage steps. The annual value is quantity × unit price; `value` is used when those are missing.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Fırsat oluştur",
    "x-description-tr": "Firma için yeni satış projesi açar; ilk açık aşamadan başlar ve aşama adımları kendiliğinden kurulur. Yıllık değer miktar × birim fiyattan hesaplanır; ikisi yoksa `value` kullanılır.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "customer_id": {
          "type": "integer",
          "description": "Company id."
         },
         "name": {
          "type": "string",
          "description": "Project name."
         },
         "type": {
          "type": "string",
          "description": "Project type (`/me` → `constants.opp_types`)."
         },
         "product_id": {
          "type": "integer",
          "description": "Product (`/me` → `products`)."
         },
         "potential_kg": {
          "type": "number",
          "description": "Monthly quantity (in the product's unit)."
         },
         "offer_price": {
          "type": "number",
          "description": "Unit price."
         },
         "payment_days": {
          "type": "integer",
          "description": "Payment terms (days)."
         },
         "value": {
          "type": "number",
          "description": "Annual value (when there is no quantity × price)."
         },
         "line": {
          "type": "string",
          "description": "Line / application."
         },
         "competitor": {
          "type": "string",
          "description": "Competitor or current supplier."
         },
         "note": {
          "type": "string",
          "description": "Note."
         }
        },
        "required": [
         "customer_id"
        ]
       },
       "example": {
        "customer_id": 31,
        "name": "Streç film tedariki",
        "potential_kg": 12000,
        "offer_price": 2.35,
        "payment_days": 60,
        "competitor": "Mevcut tedarikçi"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "opp": {
          "bant": 0,
          "bant_a": false,
          "bant_b": false,
          "bant_n": false,
          "bant_t": false,
          "base_currency": "EUR",
          "can_edit": true,
          "can_revive": false,
          "close_category": "",
          "close_date": "2027-03-31",
          "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": "Pipeline",
          "gate_ok": false,
          "gate_problems": [
           "BANT kriterleri 4/4 sağlanmalı (Budget · Authority · Need · Time)"
          ],
          "guide": "BANT 4/4",
          "health": {
           "grade": "success",
           "label": "sağlıklı",
           "score": 85
          },
          "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": null,
            "note": "Proje açıldı (mobil)",
            "to": "Qualify",
            "user": "Deniz Aksoy"
           }
          ],
          "name": "Streç film tedariki",
          "next_stage": "Viable",
          "next_step": "Karar verici / yetkili kişiyi belirle (Authority)",
          "note": "",
          "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.1,
          "probability": null,
          "product": "",
          "product_id": null,
          "pu": "€/kg",
          "rid": "006BMHmVNZ9nFLS",
          "sla_days": 30,
          "sla_left": 30,
          "source": "",
          "stage": "Qualify",
          "stage_label": "Qualify",
          "start_date": "2026-10-02",
          "steps": [
           {
            "assignee": {
             "full_name": "Deniz Aksoy",
             "id": 1,
             "role": "admin",
             "role_label": "Yönetici",
             "username": "admin"
            },
            "auto": false,
            "done": false,
            "due_date": null,
            "id": 467,
            "note": "",
            "stage": "Qualify",
            "state": "open",
            "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": 33840.0
         }
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/opportunities/{id}": {
   "get": {
    "operationId": "deals_get",
    "summary": "Get an opportunity",
    "description": "The full opportunity: stage, value, probability, health, checklist steps, BANT, stage-gate problems (`gate_problems`), visits, trials, offers, orders, tasks, stage history, notes and e-mail threads.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Fırsatı getir",
    "x-description-tr": "Fırsatın tamamı: aşama, değer, olasılık, sağlık, kontrol listesi adımları, BANT, aşama kapısı sorunları (`gate_problems`), ziyaretler, denemeler, teklifler, siparişler, görevler, aşama geçmişi, notlar ve e-posta yazışmaları.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Opportunity id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "opp": {
          "bant": 3,
          "bant_a": true,
          "bant_b": true,
          "bant_n": false,
          "bant_t": true,
          "base_currency": "EUR",
          "can_edit": true,
          "can_revive": false,
          "close_category": "",
          "close_date": "2027-02-06",
          "close_reason": "",
          "closed_at": null,
          "competitor": "Distribütör ürünü",
          "cur_sym": "€",
          "currency": "EUR",
          "customer": "Alize Paketleme San. ve Tic. A.Ş.",
          "customer_city": "İstanbul",
          "customer_id": 1,
          "days_in_stage": 2,
          "demos": [],
          "detail_status": "",
          "fc": "Pipeline",
          "gate_ok": false,
          "gate_problems": [
           "BANT kriterleri 4/4 sağlanmalı (Budget · Authority · Need · Time)"
          ],
          "guide": "BANT 4/4",
          "health": {
           "grade": "success",
           "label": "sağlıklı",
           "score": 92
          },
          "health_color": "g",
          "health_manual": true,
          "health_note": "",
          "health_why": [
           [
            "−8"
           ]
          ],
          "id": 31,
          "initials": "AP",
          "is_account": false,
          "is_open": true,
          "last_update": "2026-09-20",
          "lifetime_left": 178,
          "line": "",
          "logs": [
           {
            "date": "2026-09-30T08:00:00",
            "from": null,
            "note": "Proje açıldı",
            "to": "Qualify",
            "user": "Deniz Aksoy"
           }
          ],
          "name": "Mevcut Müşteri — Yenileme · 2026",
          "next_stage": "Viable",
          "next_step": "İhtiyaç, hat ve aylık miktar potansiyelini netleştir (Need)",
          "note": "",
          "notes": [],
          "offer_price": null,
          "offers": [],
          "orders": [],
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "payment_days": null,
          "potential_kg": 8000.0,
          "prob": 0.1,
          "probability": null,
          "product": "",
          "product_id": null,
          "pu": "€/kg",
          "rid": "006YV7xczE9DnY2",
          "sla_days": 30,
          "sla_left": 28,
          "source": "Bayi / distribütör",
          "stage": "Qualify",
          "stage_label": "Qualify",
          "start_date": "2026-09-30",
          "steps": [
           {
            "assignee": {
             "full_name": "Deniz Aksoy",
             "id": 1,
             "role": "admin",
             "role_label": "Yönetici",
             "username": "admin"
            },
            "auto": true,
            "done": true,
            "due_date": null,
            "id": 376,
            "note": "otomatik: BANT kutusu",
            "stage": "Qualify",
            "state": "done",
            "title": "Karar verici / yetkili kişiyi belirle (Authority)"
           }
          ],
          "tags": [],
          "tasks": [],
          "threads": [
           {
            "customer": "Alize Paketleme San. ve Tic. A.Ş.",
            "customer_id": 1,
            "id": 1,
            "last_at": "2026-10-01T15:06:59",
            "last_dir": "out",
            "n": 2,
            "opp": "Mevcut Müşteri — Yenileme · 2026",
            "opp_how": "single",
            "opp_id": 31,
            "opp_note": "firmanın tek açık projesi",
            "peer": "selin.dogan@alizepaketleme.example",
            "subject": "Numune ve fiyat teklifi",
            "suggested": false,
            "waiting": false
           }
          ],
          "threads_n": 1,
          "trend": "up",
          "trend_label": "Yeşil",
          "type": "Mevcut Müşteri — Yenileme",
          "unit": "kg",
          "unit_code": "kg",
          "value": 403000.0,
          "value_base": 403000.0,
          "value_short": "403K",
          "visits": [
           {
            "action_date": "2026-09-30",
            "action_done": false,
            "action_state": "overdue",
            "contact": "Selin Doğan",
            "customer": "Alize Paketleme San. ve Tic. A.Ş.",
            "customer_id": 1,
            "date": "2026-09-30",
            "id": 74,
            "line": "",
            "next_action": "Ziyaret Planla",
            "note": "Hat 2'de tünelleşme sorunu konuşuldu; solventsiz sisteme geçiş planlıyorlar.",
            "opp": "Mevcut Müşteri — Yenileme · 2026",
            "opp_id": 31,
            "product": "",
            "result": "Teklif istendi",
            "rid": "00U2wBTaDRg4JXL",
            "topic": "Tanışma",
            "type": "Call",
            "user": "Deniz Aksoy"
           }
          ],
          "weighted": 40300.0
         }
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/opportunities/{id}/fields": {
   "post": {
    "operationId": "deals_fields",
    "summary": "Update an opportunity",
    "description": "Frequently changed fields: quantity, unit price (recorded in offer history when it changes), payment terms, close date (logged), next step date, note, product, type, line, name, forecast category and stage label. Use the [stage endpoint](/rest-api/deals/stage) to move stages.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Fırsatı güncelle",
    "x-description-tr": "Sık değişen alanlar: miktar, birim fiyat (değişince teklif geçmişine yazılır), vade, kapanış tarihi (değişiklik günlüğe yazılır), sonraki adım tarihi, not, ürün, tür, hat, ad, öngörü kategorisi ve aşama etiketi. Aşama değiştirmek için [aşama ucunu](/rest-api/deals/stage) kullanın.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Opportunity id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "potential_kg": {
          "type": "number",
          "description": "Monthly quantity."
         },
         "offer_price": {
          "type": "number",
          "description": "Unit price."
         },
         "payment_days": {
          "type": "integer",
          "description": "Payment terms (days)."
         },
         "close_date": {
          "type": "string",
          "description": "Close date (YYYY-MM-DD)."
         },
         "next_step_date": {
          "type": "string",
          "description": "Next step date."
         },
         "note": {
          "type": "string",
          "description": "Note."
         },
         "product_id": {
          "type": "integer",
          "description": "Product."
         },
         "type": {
          "type": "string",
          "description": "Type."
         },
         "line": {
          "type": "string",
          "description": "Line."
         },
         "name": {
          "type": "string",
          "description": "Name."
         },
         "forecast_cat": {
          "type": "string",
          "enum": [
           "Pipeline",
           "Best Case",
           "Commit",
           "Closed",
           "Omitted"
          ],
          "description": "Forecast category."
         },
         "detail_status": {
          "type": "string",
          "description": "Detail label matching the stage (Makro pipeline)."
         }
        }
       },
       "example": {
        "close_date": "2026-11-16",
        "forecast_cat": "Best Case",
        "note": "Numune onayı bekleniyor."
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "opp": {
          "bant": 0,
          "bant_a": false,
          "bant_b": false,
          "bant_n": false,
          "bant_t": false,
          "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": [
           "BANT kriterleri 4/4 sağlanmalı (Budget · Authority · Need · Time)"
          ],
          "guide": "BANT 4/4",
          "health": {
           "grade": "success",
           "label": "sağlıklı",
           "score": 85
          },
          "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": null,
            "note": "Proje açıldı (mobil)",
            "to": "Qualify",
            "user": "Deniz Aksoy"
           }
          ],
          "name": "Streç film tedariki",
          "next_stage": "Viable",
          "next_step": "Karar verici / yetkili kişiyi belirle (Authority)",
          "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.1,
          "probability": null,
          "product": "",
          "product_id": null,
          "pu": "€/kg",
          "rid": "006BMHmVNZ9nFLS",
          "sla_days": 30,
          "sla_left": 30,
          "source": "",
          "stage": "Qualify",
          "stage_label": "Qualify",
          "start_date": "2026-10-02",
          "steps": [
           {
            "assignee": {
             "full_name": "Deniz Aksoy",
             "id": 1,
             "role": "admin",
             "role_label": "Yönetici",
             "username": "admin"
            },
            "auto": false,
            "done": false,
            "due_date": null,
            "id": 467,
            "note": "",
            "stage": "Qualify",
            "state": "open",
            "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": 33840.0
         }
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/opportunities/{id}/stage": {
   "post": {
    "operationId": "deals_stage",
    "summary": "Change stage",
    "description": "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.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Aşamayı değiştir",
    "x-description-tr": "Fırsatı başka bir aşamaya taşır. Aşama kapıları web'deki gibi uygulanır: kural sağlanmıyorsa `409 gate` ve `gate_problems` döner. Kaybedildi / İptal için `reason` (kayıp nedeni) gönderin. Kazanılan fırsat firmayı müşteri yapar ve uygulamalara `opp_won` olayı gider.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Opportunity id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "stage": {
          "type": "string",
          "description": "Target stage key (`/me` → `constants.stages`; closing keys are `Win`, `Lost`, `Cancel`)."
         },
         "note": {
          "type": "string",
          "description": "Note for the stage log."
         },
         "reason": {
          "type": "string",
          "description": "Loss / cancel reason (`/me` → `constants.loss_reasons`)."
         }
        },
        "required": [
         "stage"
        ]
       },
       "example": {
        "stage": "Viable",
        "note": "İhtiyaç ve bütçe doğrulandı."
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "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
         }
        }
       }
      }
     },
     "409": {
      "description": "Error",
      "content": {
       "application/json": {
        "example": {
         "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
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/opportunities/{id}/bant": {
   "post": {
    "operationId": "deals_bant",
    "summary": "Update BANT",
    "description": "Sets the Budget, Authority, Need and Timing criteria; the matching checklist steps are updated too.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "BANT güncelle",
    "x-description-tr": "Bütçe, yetki, ihtiyaç ve zamanlama ölçütlerini işaretler; ilgili kontrol listesi adımları da güncellenir.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Opportunity id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "bant_b": {
          "type": "boolean",
          "description": "Budget confirmed."
         },
         "bant_a": {
          "type": "boolean",
          "description": "Authority known."
         },
         "bant_n": {
          "type": "boolean",
          "description": "Need confirmed."
         },
         "bant_t": {
          "type": "boolean",
          "description": "Timing known."
         }
        }
       },
       "example": {
        "bant_b": true,
        "bant_a": true,
        "bant_n": true,
        "bant_t": true
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "message": "BANT güncellendi (4/4).",
         "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": true,
          "gate_problems": [],
          "guide": "BANT 4/4",
          "health": {
           "grade": "success",
           "label": "sağlıklı",
           "score": 90
          },
          "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": null,
            "note": "Proje açıldı (mobil)",
            "to": "Qualify",
            "user": "Deniz Aksoy"
           }
          ],
          "name": "Streç film tedariki",
          "next_stage": "Viable",
          "next_step": "Ön koşullar tamam → Viable aşamasına geçir",
          "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.1,
          "probability": null,
          "product": "",
          "product_id": null,
          "pu": "€/kg",
          "rid": "006BMHmVNZ9nFLS",
          "sla_days": 30,
          "sla_left": 30,
          "source": "",
          "stage": "Qualify",
          "stage_label": "Qualify",
          "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": 33840.0
         }
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/opportunities/{id}/steps": {
   "post": {
    "operationId": "deals_step_add",
    "summary": "Add a step",
    "description": "Adds a checklist step to the opportunity's current stage. Dated steps show up in Actions with kind `step`.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Adım ekle",
    "x-description-tr": "Fırsatın bulunduğu aşamaya kontrol listesi adımı ekler. Tarihli adımlar Aksiyonlar'da `step` türüyle görünür.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Opportunity id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "title": {
          "type": "string",
          "description": "Step title."
         },
         "due_date": {
          "type": "string",
          "description": "Due date (YYYY-MM-DD)."
         },
         "assigned_to": {
          "type": "integer",
          "description": "Assignee user id."
         }
        },
        "required": [
         "title"
        ]
       },
       "example": {
        "title": "Hat denemesi planla",
        "due_date": "2026-10-09"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "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": 95
          },
          "health_color": "g",
          "health_manual": false,
          "health_note": "",
          "health_why": [
           [
            "−10"
           ]
          ],
          "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
         },
         "step": {
          "assignee": null,
          "auto": false,
          "done": false,
          "due_date": "2026-10-09",
          "id": 474,
          "note": "",
          "stage": "Viable",
          "state": "soon",
          "title": "Hat denemesi planla"
         }
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/steps/{id}/toggle": {
   "post": {
    "operationId": "deals_step_toggle",
    "summary": "Toggle a step",
    "description": "Marks a step done / open (flips it when `done` is omitted). BANT steps also update the opportunity's BANT flags.",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Adımı işaretle",
    "x-description-tr": "Adımı tamamlandı / açık yapar (`done` yoksa tersine çevirir). BANT adımları fırsatın BANT işaretlerini de değiştirir.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Step id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "done": {
          "type": "boolean",
          "description": "Done."
         },
         "note": {
          "type": "string",
          "description": "Note (250 characters)."
         }
        }
       },
       "example": {
        "done": true,
        "note": "Perşembe 10:00"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "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
         },
         "step": {
          "assignee": null,
          "auto": false,
          "done": true,
          "due_date": "2026-10-09",
          "id": 474,
          "note": "Perşembe 10:00",
          "stage": "Viable",
          "state": "done",
          "title": "Hat denemesi planla"
         }
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/opportunities/{id}/revive": {
   "post": {
    "operationId": "deals_revive",
    "summary": "Revive an opportunity",
    "description": "Opens a new opportunity from a lost / cancelled one (product, quantity and line are copied and linked to the original).",
    "tags": [
     "Opportunities"
    ],
    "x-summary-tr": "Fırsatı canlandır",
    "x-description-tr": "Kaybedilmiş / iptal edilmiş fırsattan yeni bir fırsat açar (ürün, miktar ve hat kopyalanır, eskisine bağlanır).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Id of the closed opportunity.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "opp": {
          "bant": 0,
          "bant_a": false,
          "bant_b": false,
          "bant_n": false,
          "bant_t": false,
          "base_currency": "EUR",
          "can_edit": true,
          "can_revive": false,
          "close_category": "",
          "close_date": "2027-03-31",
          "close_reason": "",
          "closed_at": null,
          "competitor": "",
          "cur_sym": "€",
          "currency": "EUR",
          "customer": "Işıltı Film A.Ş.",
          "customer_city": "Konya",
          "customer_id": 8,
          "days_in_stage": 0,
          "demos": [],
          "detail_status": "",
          "fc": "Pipeline",
          "gate_ok": false,
          "gate_problems": [
           "BANT kriterleri 4/4 sağlanmalı (Budget · Authority · Need · Time)"
          ],
          "guide": "BANT 4/4",
          "health": {
           "grade": "success",
           "label": "sağlıklı",
           "score": 85
          },
          "health_color": "g",
          "health_manual": false,
          "health_note": "",
          "health_why": [
           [
            "−15"
           ]
          ],
          "id": 54,
          "initials": "IF",
          "is_account": false,
          "is_open": true,
          "last_update": "2026-10-02",
          "lifetime_left": 180,
          "line": "",
          "logs": [
           {
            "date": "2026-10-02T20:07:00",
            "from": null,
            "note": "Yeniden canlandırıldı (mobil) ← #38",
            "to": "Qualify",
            "user": "Deniz Aksoy"
           }
          ],
          "name": "Mevcut Müşteri — Ek Satış · 2026 (canlandırıldı)",
          "next_stage": "Viable",
          "next_step": "Karar verici / yetkili kişiyi belirle (Authority)",
          "note": "",
          "notes": [],
          "offer_price": null,
          "offers": [],
          "orders": [],
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "payment_days": null,
          "potential_kg": 12000.0,
          "prob": 0.1,
          "probability": null,
          "product": "PU-SL 350 Yüksek Performans (retort)",
          "product_id": 2,
          "pu": "€/kg",
          "rid": "006CSwEIJ0YiYkC",
          "sla_days": 30,
          "sla_left": 30,
          "source": "",
          "stage": "Qualify",
          "stage_label": "Qualify",
          "start_date": "2026-10-02",
          "steps": [
           {
            "assignee": {
             "full_name": "Deniz Aksoy",
             "id": 1,
             "role": "admin",
             "role_label": "Yönetici",
             "username": "admin"
            },
            "auto": false,
            "done": false,
            "due_date": null,
            "id": 475,
            "note": "",
            "stage": "Qualify",
            "state": "open",
            "title": "Karar verici / yetkili kişiyi belirle (Authority)"
           }
          ],
          "tags": [],
          "tasks": [],
          "threads": [],
          "threads_n": 0,
          "trend": "",
          "trend_label": "Otomatik",
          "type": "Mevcut Müşteri — Ek Satış",
          "unit": "kg",
          "unit_code": "kg",
          "value": 0,
          "value_base": 0,
          "value_short": "0",
          "visits": [],
          "weighted": 0.0
         }
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/quick": {
   "post": {
    "operationId": "activities_quick",
    "summary": "Log an activity",
    "description": "Quick Entry: logs a phone call or face-to-face visit in one request. The company is matched by name (created as a prospect when missing; similar names return `409 similar`), a missing person is added, matching open actions are closed, the next action is opened and the project advances under the same rules as the web form. `parts` tells what was recorded; `warnings` and `advice` explain what needs attention.",
    "tags": [
     "Activities"
    ],
    "x-summary-tr": "Görüşme kaydet",
    "x-description-tr": "Hızlı Giriş: bir telefon görüşmesini ya da yüz yüze ziyareti tek istekte kaydeder. Firma adla bulunur (yoksa aday olarak açılır; benzer adlar varsa `409 similar`), kişi yoksa eklenir, uygun açık aksiyonlar kapanır, sonraki aksiyon açılır ve proje web formundaki kurallarla ilerler. Yanıttaki `parts` neyin kaydedildiğini, `warnings` ve `advice` dikkat edilecekleri anlatır.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "customer": {
          "type": "string",
          "description": "Company name (exact or close)."
         },
         "visit_type": {
          "type": "string",
          "enum": [
           "F2F",
           "Call",
           "Deneme"
          ],
          "description": "`F2F` face to face, `Call` phone, `Deneme` trial visit."
         },
         "visit_date": {
          "type": "string",
          "description": "Activity date (YYYY-MM-DD, default today)."
         },
         "contact": {
          "type": "string",
          "description": "Person met (added when missing)."
         },
         "contact_title": {
          "type": "string",
          "description": "Details for a new person."
         },
         "contact_phone": {
          "type": "string",
          "description": "Details for a new person."
         },
         "contact_email": {
          "type": "string",
          "description": "Details for a new person."
         },
         "topic": {
          "type": "string",
          "description": "Topic."
         },
         "note": {
          "type": "string",
          "description": "What was discussed."
         },
         "result": {
          "type": "string",
          "description": "Outcome."
         },
         "next_action": {
          "type": "string",
          "description": "Next action."
         },
         "action_date": {
          "type": "string",
          "description": "Next action date."
         },
         "opp_id": {
          "type": "integer",
          "description": "Project to log against."
         },
         "product": {
          "description": "Project details (same as the web form)."
         },
         "competitor": {
          "description": "Project details (same as the web form)."
         },
         "offer_price": {
          "description": "Project details (same as the web form)."
         },
         "payment_days": {
          "description": "Project details (same as the web form)."
         },
         "potential_kg": {
          "description": "Project details (same as the web form)."
         },
         "confirm_new": {
          "type": "boolean",
          "description": "Create a new company even if similar names exist."
         }
        },
        "required": [
         "customer"
        ]
       },
       "example": {
        "customer": "Kuzey Plastik Sanayi",
        "visit_type": "Call",
        "contact": "Emre Yıldız",
        "note": "Deneme sonuçlarını konuştuk; kalınlık 23 mikron uygun.",
        "result": "Olumlu",
        "next_action": "Teklif gönder",
        "action_date": "2026-10-05"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "advice": null,
         "closed": [],
         "created": false,
         "customer": {
          "active": true,
          "at_risk": false,
          "city": "Bursa",
          "currency": "EUR",
          "currency_default": "",
          "id": 31,
          "initials": "KP",
          "last_visit": "2026-10-02",
          "main_contact": {
           "email": "emre.yildiz@kuzeyplastik.com.tr",
           "name": "Emre Yıldız",
           "phone": "+90 532 555 11 22",
           "wa": "905325551122"
          },
          "name": "Kuzey Plastik Sanayi",
          "next_visit_due": "2026-11-01",
          "open_opps": 1,
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "pending_state": "soon",
          "period": 30,
          "phone": "+90 224 555 01 02",
          "potential_kg": null,
          "rid": "001QJi5Zr1Hk2VH",
          "sector": "Plastik",
          "status": "AC",
          "status_label": "Aktif Müşteri",
          "unit": "kg",
          "visit_overdue_days": -30,
          "visit_state": "ok"
         },
         "message": "Kuzey Plastik Sanayi kaydedildi: ziyaret, proje #53 Streç film tedariki.",
         "next_step": "F2F ziyaret planla ve gerçekleştir",
         "ok": true,
         "opp": {
          "bant": 4,
          "base_currency": "EUR",
          "close_date": "2026-11-16",
          "cur_sym": "€",
          "currency": "EUR",
          "customer": "Kuzey Plastik Sanayi",
          "customer_city": "Bursa",
          "customer_id": 31,
          "days_in_stage": 0,
          "detail_status": "",
          "fc": "Best Case",
          "health": {
           "grade": "success",
           "label": "sağlıklı",
           "score": 95
          },
          "health_color": "g",
          "health_manual": false,
          "health_note": "",
          "id": 53,
          "initials": "KP",
          "is_account": false,
          "is_open": true,
          "last_update": "2026-10-02",
          "lifetime_left": 180,
          "line": "",
          "name": "Streç film tedariki",
          "next_step": "F2F ziyaret planla ve gerçekleştir",
          "offer_price": 2.35,
          "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",
          "trend": "",
          "trend_label": "Otomatik",
          "type": "",
          "unit": "kg",
          "unit_code": "kg",
          "value": 338400.0,
          "value_base": 338400.0,
          "value_short": "338K"
         },
         "opp_new": false,
         "parts": [
          "ziyaret",
          "proje #53 Streç film tedariki"
         ],
         "visit": {
          "action_date": "2026-10-05",
          "action_done": false,
          "action_state": "soon",
          "contact": "Emre Yıldız",
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "date": "2026-10-02",
          "id": 106,
          "line": "",
          "next_action": "Teklif gönder",
          "note": "Deneme sonuçlarını konuştuk; kalınlık 23 mikron uygun.",
          "opp": "Streç film tedariki",
          "opp_id": 53,
          "product": "",
          "result": "Olumlu",
          "rid": "00UEIXukSoU4vCq",
          "topic": "Görüşme",
          "type": "Call",
          "user": "Deniz Aksoy"
         },
         "warnings": []
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "409": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/actions": {
   "get": {
    "operationId": "actions_list",
    "summary": "List actions",
    "description": "Open work in one list: tasks, next actions of visits and trials, dated project steps. Use each row's `kind` + `id` with the complete / postpone endpoints.",
    "tags": [
     "Actions & tasks"
    ],
    "x-summary-tr": "Aksiyonları listele",
    "x-description-tr": "Açık işler tek listede: görevler, ziyaret ve denemelerin sonraki aksiyonları, tarihli proje adımları. Her satırdaki `kind` + `id` ile tamamlama / erteleme uçları çağrılır.",
    "parameters": [
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "description": "`mine` = records I own (default for sales users), `all` = every record I can see (default for admins), or a user id.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "state",
      "in": "query",
      "required": false,
      "description": "Due state.",
      "schema": {
       "type": "string",
       "enum": [
        "today",
        "overdue",
        "soon",
        "open",
        "week"
       ]
      }
     },
     {
      "name": "customer_id",
      "in": "query",
      "required": false,
      "description": "Only this company.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "counts": {
          "overdue": 9,
          "soon": 0,
          "today": 0
         },
         "ok": true,
         "rows": [
          {
           "customer": "Lotus Medikal Ambalaj San. Tic. Ltd. Şti.",
           "customer_id": 3,
           "date": "2026-09-26",
           "icon": "📋",
           "id": 1,
           "key": "task:1",
           "kind": "task",
           "label": "Numune sonucu için ara",
           "opp": "Yeni Müşteri · 2026",
           "opp_id": 33,
           "src": "Görev",
           "state": "overdue",
           "url": "/action/task/1"
          },
          {
           "customer": "Hanımeli Etiket San. Tic. Ltd. Şti.",
           "customer_id": 23,
           "date": "2026-09-26",
           "icon": "📋",
           "id": 17,
           "key": "task:17",
           "kind": "task",
           "label": "Fiyat listesini güncelleyip gönder",
           "opp": "Mevcut Müşteri — Yenileme · 2026",
           "opp_id": 23,
           "src": "Görev",
           "state": "overdue",
           "url": "/action/task/17"
          }
         ],
         "total": 9
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/actions/{kind}/{rid}": {
   "get": {
    "operationId": "actions_get",
    "summary": "Get an action",
    "description": "The action with its context: company, project, the chain before / after it (`chain_before`, `chain_after`), the company's other open work and e-mail threads.",
    "tags": [
     "Actions & tasks"
    ],
    "x-summary-tr": "Aksiyonu getir",
    "x-description-tr": "Aksiyonun ayrıntısı ve bağlamı: firma, proje, önceki / sonraki zincir (`chain_before`, `chain_after`), firmanın diğer açık işleri ve e-posta yazışmaları.",
    "parameters": [
     {
      "name": "kind",
      "in": "path",
      "required": true,
      "description": "Action kind: `task`, `visit` (next action of a visit), `demo` (next action of a trial), `step` (opportunity step).",
      "schema": {
       "type": "string",
       "enum": [
        "task",
        "visit",
        "demo",
        "step"
       ]
      }
     },
     {
      "name": "rid",
      "in": "path",
      "required": true,
      "description": "Action id (`id` in the list).",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "action": {
          "act": {
           "addr": "Bursa",
           "c": 31,
           "mail": "emre.yildiz@kuzeyplastik.com.tr",
           "n": "Kuzey Plastik Sanayi",
           "tel": "+90 532 555 11 22",
           "url": "/customers/31",
           "wa": "905325551122",
           "who": "Emre Yıldız"
          },
          "chain_after": [],
          "chain_before": [],
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "date": "2026-10-04",
          "detail": "2027 listesi, €/kg",
          "done": false,
          "done_at": null,
          "editable": true,
          "icon": "📋",
          "id": 23,
          "key": "task:23",
          "kind": "task",
          "label": "Fiyat listesini gönder",
          "opp": "",
          "opp_id": null,
          "others": [
           {
            "customer": "",
            "customer_id": null,
            "date": "2026-10-05",
            "icon": "⚡",
            "id": 106,
            "key": "visit:106",
            "kind": "visit",
            "label": "Teklif gönder",
            "opp": "Streç film tedariki",
            "opp_id": 53,
            "src": "Ziyaret",
            "state": "soon",
            "url": "/action/visit/106"
           }
          ],
          "result": "",
          "rid": "00TxuMVTniYx44l",
          "src": "Görev",
          "state": "soon",
          "threads": [],
          "threads_n": 0,
          "user": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          }
         },
         "ok": true
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/actions/{kind}/{rid}/done": {
   "post": {
    "operationId": "actions_done",
    "summary": "Complete an action",
    "description": "Marks the action done (or open again with `done: false`). `done_on` sets the completion day (default now).",
    "tags": [
     "Actions & tasks"
    ],
    "x-summary-tr": "Aksiyonu tamamla",
    "x-description-tr": "Aksiyonu tamamlandı (ya da `done: false` ile açık) yapar. `done_on` tamamlanma gününü belirler (varsayılan şimdi).",
    "parameters": [
     {
      "name": "kind",
      "in": "path",
      "required": true,
      "description": "Action kind: `task`, `visit` (next action of a visit), `demo` (next action of a trial), `step` (opportunity step).",
      "schema": {
       "type": "string",
       "enum": [
        "task",
        "visit",
        "demo",
        "step"
       ]
      }
     },
     {
      "name": "rid",
      "in": "path",
      "required": true,
      "description": "Action id (`id` in the list).",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "done": {
          "type": "boolean",
          "description": "Done; flips the state when omitted."
         },
         "done_on": {
          "type": "string",
          "description": "Completion day (YYYY-MM-DD)."
         },
         "result": {
          "type": "string",
          "description": "Result note."
         }
        }
       },
       "example": {
        "done": true,
        "done_on": "2026-10-02",
        "result": "Liste e-postayla gönderildi"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "action": {
          "act": {
           "addr": "Bursa",
           "c": 31,
           "mail": "emre.yildiz@kuzeyplastik.com.tr",
           "n": "Kuzey Plastik Sanayi",
           "tel": "+90 532 555 11 22",
           "url": "/customers/31",
           "wa": "905325551122",
           "who": "Emre Yıldız"
          },
          "chain_after": [],
          "chain_before": [],
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "date": "2026-10-05",
          "detail": "2027 listesi, €/kg\n[Ertelendi 04.10.2026 → 05.10.2026] Liste onayı bekleniyor",
          "done": true,
          "done_at": "2026-10-02T20:07:01",
          "editable": true,
          "icon": "📋",
          "id": 23,
          "key": "task:23",
          "kind": "task",
          "label": "Fiyat listesini gönder",
          "opp": "",
          "opp_id": null,
          "others": [
           {
            "customer": "",
            "customer_id": null,
            "date": "2026-10-05",
            "icon": "⚡",
            "id": 106,
            "key": "visit:106",
            "kind": "visit",
            "label": "Teklif gönder",
            "opp": "Streç film tedariki",
            "opp_id": 53,
            "src": "Ziyaret",
            "state": "soon",
            "url": "/action/visit/106"
           }
          ],
          "result": "Liste e-postayla gönderildi",
          "rid": "00TxuMVTniYx44l",
          "src": "Görev",
          "state": "done",
          "threads": [],
          "threads_n": 0,
          "user": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          }
         },
         "ok": true
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/actions/{kind}/{rid}/postpone": {
   "post": {
    "operationId": "actions_postpone",
    "summary": "Postpone an action",
    "description": "Moves the due date; the note is appended to the record with dates.",
    "tags": [
     "Actions & tasks"
    ],
    "x-summary-tr": "Aksiyonu ertele",
    "x-description-tr": "Termini ileri alır; not, kaydın açıklamasına tarihli satır olarak eklenir.",
    "parameters": [
     {
      "name": "kind",
      "in": "path",
      "required": true,
      "description": "Action kind: `task`, `visit` (next action of a visit), `demo` (next action of a trial), `step` (opportunity step).",
      "schema": {
       "type": "string",
       "enum": [
        "task",
        "visit",
        "demo",
        "step"
       ]
      }
     },
     {
      "name": "rid",
      "in": "path",
      "required": true,
      "description": "Action id (`id` in the list).",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "date": {
          "type": "string",
          "description": "New date (YYYY-MM-DD)."
         },
         "days": {
          "type": "integer",
          "description": "Days (when no date)."
         },
         "note": {
          "type": "string",
          "description": "Reason."
         }
        }
       },
       "example": {
        "days": 3,
        "note": "Liste onayı bekleniyor"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "action": {
          "act": {
           "addr": "Bursa",
           "c": 31,
           "mail": "emre.yildiz@kuzeyplastik.com.tr",
           "n": "Kuzey Plastik Sanayi",
           "tel": "+90 532 555 11 22",
           "url": "/customers/31",
           "wa": "905325551122",
           "who": "Emre Yıldız"
          },
          "chain_after": [],
          "chain_before": [],
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "date": "2026-10-05",
          "detail": "2027 listesi, €/kg\n[Ertelendi 04.10.2026 → 05.10.2026] Liste onayı bekleniyor",
          "done": false,
          "done_at": null,
          "editable": true,
          "icon": "📋",
          "id": 23,
          "key": "task:23",
          "kind": "task",
          "label": "Fiyat listesini gönder",
          "opp": "",
          "opp_id": null,
          "others": [
           {
            "customer": "",
            "customer_id": null,
            "date": "2026-10-05",
            "icon": "⚡",
            "id": 106,
            "key": "visit:106",
            "kind": "visit",
            "label": "Teklif gönder",
            "opp": "Streç film tedariki",
            "opp_id": 53,
            "src": "Ziyaret",
            "state": "soon",
            "url": "/action/visit/106"
           }
          ],
          "result": "",
          "rid": "00TxuMVTniYx44l",
          "src": "Görev",
          "state": "soon",
          "threads": [],
          "threads_n": 0,
          "user": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          }
         },
         "ok": true,
         "until": "2026-10-05"
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/actions/{kind}/{rid}/close": {
   "post": {
    "operationId": "actions_close",
    "summary": "Close and open the next",
    "description": "Closes the action with its result and optionally opens the next task in the chain (same company and project). `mode: keep` leaves the action open and only adds the next task.",
    "tags": [
     "Actions & tasks"
    ],
    "x-summary-tr": "Kapat ve sonrakini aç",
    "x-description-tr": "Aksiyonu sonucuyla kapatır ve isteğe bağlı olarak zincirdeki sonraki görevi açar (aynı firma ve projeye bağlı). `mode: keep` aksiyonu açık bırakıp yalnız sonraki görevi ekler.",
    "parameters": [
     {
      "name": "kind",
      "in": "path",
      "required": true,
      "description": "Action kind: `task`, `visit` (next action of a visit), `demo` (next action of a trial), `step` (opportunity step).",
      "schema": {
       "type": "string",
       "enum": [
        "task",
        "visit",
        "demo",
        "step"
       ]
      }
     },
     {
      "name": "rid",
      "in": "path",
      "required": true,
      "description": "Action id (`id` in the list).",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "result": {
          "type": "string",
          "description": "Result."
         },
         "next_title": {
          "type": "string",
          "description": "Next task's title."
         },
         "next_date": {
          "type": "string",
          "description": "Next task's due date."
         },
         "next_assigned": {
          "type": "integer",
          "description": "Next task's assignee."
         },
         "next_priority": {
          "type": "string",
          "enum": [
           "Düşük",
           "Normal",
           "Yüksek",
           "Acil"
          ],
          "description": "Priority."
         },
         "mode": {
          "type": "string",
          "enum": [
           "close",
           "keep"
          ],
          "description": "`close` closes, `keep` leaves it open."
         }
        }
       },
       "example": {
        "result": "Müşteri aradı, teklif istendi",
        "next_title": "Teklif hazırla",
        "next_date": "2026-10-04"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "action": {
          "act": {
           "addr": "Ankara Organize Sanayi Bölgesi, 8. Cadde No: 35, Ankara, Ankara",
           "c": 3,
           "mail": "cem.polat@lotusmedikal.example",
           "n": "Lotus Medikal Ambalaj San. Tic. Ltd. Şti.",
           "tel": "0 (312) 000 46 49",
           "url": "/customers/3",
           "wa": "903120004649",
           "who": "Cem Polat"
          },
          "chain_after": [
           [
            {
             "date": "2026-10-04",
             "done": false,
             "id": 24,
             "key": "task:24",
             "kind": "task",
             "label": "Teklif hazırla",
             "src": "Görev",
             "state": "soon"
            }
           ]
          ],
          "chain_before": [],
          "customer": "Lotus Medikal Ambalaj San. Tic. Ltd. Şti.",
          "customer_id": 3,
          "date": "2026-09-26",
          "detail": "",
          "done": true,
          "done_at": "2026-10-02T20:07:01",
          "editable": true,
          "icon": "📋",
          "id": 1,
          "key": "task:1",
          "kind": "task",
          "label": "Numune sonucu için ara",
          "opp": "Yeni Müşteri · 2026",
          "opp_id": 33,
          "others": [
           {
            "customer": "",
            "customer_id": null,
            "date": "2026-10-03",
            "icon": "📋",
            "id": 19,
            "key": "task:19",
            "kind": "task",
            "label": "Kargo takip numarasını ilet",
            "opp": "Yeni Müşteri · 2026",
            "opp_id": 33,
            "src": "Görev",
            "state": "soon",
            "url": "/action/task/19"
           }
          ],
          "result": "Müşteri aradı, teklif istendi",
          "rid": "00Tc4zPI4VpXeWp",
          "src": "Görev",
          "state": "done",
          "threads": [],
          "threads_n": 0,
          "user": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          }
         },
         "next_task": {
          "assignee": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "completed_at": null,
          "customer": "Lotus Medikal Ambalaj San. Tic. Ltd. Şti.",
          "customer_id": 3,
          "detail": "↳ Görev #1 (Numune sonucu için ara) sonrası: Müşteri aradı, teklif istendi",
          "due_date": "2026-10-04",
          "due_time": "",
          "id": 24,
          "opp": "Yeni Müşteri · 2026",
          "opp_id": 33,
          "priority": "Normal",
          "result": "",
          "rid": "00TfYtMol2EnOoG",
          "source_key": "task:1",
          "state": "soon",
          "status": "Açık",
          "title": "Teklif hazırla"
         },
         "ok": true
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/tasks": {
   "post": {
    "operationId": "tasks_create",
    "summary": "Create a task",
    "description": "Creates a task, assigned to the caller unless `assigned_to` is given. Linking a company is optional (by id or name); no project is opened automatically — use `opp_id` for an existing project or `opp_name` for a new one.",
    "tags": [
     "Actions & tasks"
    ],
    "x-summary-tr": "Görev oluştur",
    "x-description-tr": "Görev açar; `assigned_to` yoksa isteği yapana atanır. Firma bağlamak isteğe bağlıdır (kimlik ya da adla); kendiliğinden proje açılmaz — `opp_id` ile mevcut projeye, `opp_name` ile yeni projeye bağlanır.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "title": {
          "type": "string",
          "description": "Task title."
         },
         "due_date": {
          "type": "string",
          "description": "Due date (YYYY-MM-DD)."
         },
         "due_time": {
          "type": "string",
          "description": "Time (HH:MM)."
         },
         "priority": {
          "type": "string",
          "enum": [
           "Düşük",
           "Normal",
           "Yüksek",
           "Acil"
          ],
          "description": "Priority."
         },
         "detail": {
          "type": "string",
          "description": "Details."
         },
         "assigned_to": {
          "type": "integer",
          "description": "Assignee user id."
         },
         "customer_id": {
          "type": "integer",
          "description": "Company id."
         },
         "customer": {
          "type": "string",
          "description": "Company name (if the id is unknown)."
         },
         "opp_id": {
          "type": "string",
          "description": "Project id or `__none__` (no project)."
         },
         "opp_name": {
          "type": "string",
          "description": "New project name."
         }
        },
        "required": [
         "title"
        ]
       },
       "example": {
        "title": "Fiyat listesini gönder",
        "customer_id": 31,
        "due_date": "2026-10-04",
        "due_time": "10:30",
        "priority": "Yüksek",
        "detail": "2027 listesi, €/kg"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "action": {
          "act": {
           "addr": "Bursa",
           "c": 31,
           "mail": "emre.yildiz@kuzeyplastik.com.tr",
           "n": "Kuzey Plastik Sanayi",
           "tel": "+90 532 555 11 22",
           "url": "/customers/31",
           "wa": "905325551122",
           "who": "Emre Yıldız"
          },
          "chain_after": [],
          "chain_before": [],
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "date": "2026-10-04",
          "detail": "2027 listesi, €/kg",
          "done": false,
          "done_at": null,
          "editable": true,
          "icon": "📋",
          "id": 23,
          "key": "task:23",
          "kind": "task",
          "label": "Fiyat listesini gönder",
          "opp": "",
          "opp_id": null,
          "others": [
           {
            "customer": "",
            "customer_id": null,
            "date": "2026-10-05",
            "icon": "⚡",
            "id": 106,
            "key": "visit:106",
            "kind": "visit",
            "label": "Teklif gönder",
            "opp": "Streç film tedariki",
            "opp_id": 53,
            "src": "Ziyaret",
            "state": "soon",
            "url": "/action/visit/106"
           }
          ],
          "result": "",
          "rid": "00TxuMVTniYx44l",
          "src": "Görev",
          "state": "soon",
          "threads": [],
          "threads_n": 0,
          "user": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          }
         },
         "ok": true,
         "task": {
          "assignee": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "completed_at": null,
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "detail": "2027 listesi, €/kg",
          "due_date": "2026-10-04",
          "due_time": "10:30",
          "id": 23,
          "opp": "",
          "opp_id": null,
          "priority": "Yüksek",
          "result": "",
          "rid": "00TxuMVTniYx44l",
          "source_key": "",
          "state": "soon",
          "status": "Açık",
          "title": "Fiyat listesini gönder"
         }
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/tasks/{id}": {
   "patch": {
    "operationId": "tasks_update",
    "summary": "Update a task",
    "description": "Only the fields you send change. `status: Tamamlandı` completes the task (`done_on` picks the day). `PUT` and `POST` are accepted too.",
    "tags": [
     "Actions & tasks"
    ],
    "x-summary-tr": "Görevi güncelle",
    "x-description-tr": "Yalnız gönderilen alanlar değişir. `status: Tamamlandı` görevi kapatır (`done_on` ile gün seçilir). `PUT` ve `POST` da kabul edilir.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Task id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "title": {
          "type": "string",
          "description": "Title."
         },
         "detail": {
          "type": "string",
          "description": "Details."
         },
         "due_date": {
          "type": "string",
          "description": "Due date."
         },
         "due_time": {
          "type": "string",
          "description": "Time (HH:MM)."
         },
         "priority": {
          "type": "string",
          "enum": [
           "Düşük",
           "Normal",
           "Yüksek",
           "Acil"
          ],
          "description": "Priority."
         },
         "status": {
          "type": "string",
          "enum": [
           "Açık",
           "Devam Ediyor",
           "Tamamlandı"
          ],
          "description": "Status."
         },
         "done_on": {
          "type": "string",
          "description": "Completion day."
         },
         "assigned_to": {
          "type": "integer",
          "description": "Assignee."
         }
        }
       },
       "example": {
        "priority": "Acil",
        "due_time": "09:00"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "task": {
          "assignee": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "completed_at": null,
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "detail": "2027 listesi, €/kg",
          "due_date": "2026-10-04",
          "due_time": "09:00",
          "id": 23,
          "opp": "",
          "opp_id": null,
          "priority": "Acil",
          "result": "",
          "rid": "00TxuMVTniYx44l",
          "source_key": "",
          "state": "soon",
          "status": "Açık",
          "title": "Fiyat listesini gönder"
         }
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/events": {
   "get": {
    "operationId": "calendar_list",
    "summary": "List calendar",
    "description": "Meetings (`events`) and entries derived from actions (`derived`: due actions, visit dates) in a date range. Internal meetings are visible to their owner only. `mode` tells whether a meeting is online or in person; `join_url` is the meeting link.",
    "tags": [
     "Calendar"
    ],
    "x-summary-tr": "Takvimi listele",
    "x-description-tr": "Tarih aralığındaki toplantılar (`events`) ve aksiyonlardan türeyen girişler (`derived`: termini gelen aksiyonlar, ziyaret günleri). İç toplantılar yalnız sahibine görünür. `mode` toplantının çevrim içi mi yüz yüze mi olduğunu, `join_url` katılım bağlantısını verir.",
    "parameters": [
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "Start (YYYY-MM-DD, default today).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "description": "End (default +30 days).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "done",
      "in": "query",
      "required": false,
      "description": "`1` = include completed actions.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "derived": [
          {
           "date": "2026-10-05",
           "done": false,
           "firm": "Kuzey Plastik Sanayi",
           "icon": "⚡",
           "kind": "visit",
           "location": "",
           "note": "Deneme sonuçlarını konuştuk; kalınlık 23 mikron uygun.",
           "state": "soon",
           "title": "⚡ Kuzey Plastik Sanayi · Teklif gönder",
           "uid": "visit-106@ornek",
           "url": "/action/visit/106",
           "what": "Teklif gönder"
          }
         ],
         "events": [],
         "from": "2026-10-02",
         "ok": true,
         "to": "2026-10-16"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   },
   "post": {
    "operationId": "calendar_create",
    "summary": "Create an event",
    "description": "Adds a meeting to the calendar; it syncs to phone calendars when CalDAV is on.",
    "tags": [
     "Calendar"
    ],
    "x-summary-tr": "Etkinlik oluştur",
    "x-description-tr": "Takvime toplantı ekler; CalDAV açıksa telefon takvimine de gider.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "title": {
          "type": "string",
          "description": "Title."
         },
         "start": {
          "type": "string",
          "description": "Start (YYYY-MM-DDTHH:MM)."
         },
         "end": {
          "type": "string",
          "description": "End."
         },
         "all_day": {
          "type": "boolean",
          "description": "All day."
         },
         "customer_id": {
          "type": "integer",
          "description": "Company."
         },
         "customer": {
          "type": "string",
          "description": "Company name."
         },
         "location": {
          "type": "string",
          "description": "Location."
         },
         "note": {
          "type": "string",
          "description": "Note."
         }
        },
        "required": [
         "title",
         "start"
        ]
       },
       "example": {
        "title": "Kuzey Plastik · hat denemesi",
        "start": "2026-10-07T10:00",
        "end": "2026-10-07T11:30",
        "customer_id": 31,
        "location": "Bursa OSB"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "event": {
          "all_day": false,
          "customer": "Kuzey Plastik Sanayi",
          "customer_id": 31,
          "editable": true,
          "end": "2026-10-07T11:30:00",
          "id": 1,
          "join_url": "",
          "location": "Bursa OSB",
          "mode": "onsite",
          "note": "",
          "source": "manual",
          "start": "2026-10-07T10:00:00",
          "title": "Kuzey Plastik · hat denemesi"
         },
         "ok": true
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/events/{id}": {
   "delete": {
    "operationId": "calendar_delete",
    "summary": "Delete an event",
    "description": "Deletes an event added in the app (events from e-mail or CalDAV can't be deleted). `POST` is accepted too.",
    "tags": [
     "Calendar"
    ],
    "x-summary-tr": "Etkinliği sil",
    "x-description-tr": "Uygulamada eklenmiş bir etkinliği siler (e-postadan ya da CalDAV'dan gelenler silinmez). `POST` da kabul edilir.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Event id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/fairs": {
   "get": {
    "operationId": "fairs_list",
    "summary": "List fairs",
    "description": "Trade fairs (active first) with lead counts.",
    "tags": [
     "Trade fairs & leads"
    ],
    "x-summary-tr": "Fuarları listele",
    "x-description-tr": "Fuarlar (aktif olanlar önce) ve lead sayıları.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ok": true,
         "rows": [
          {
           "active": true,
           "city": "İstanbul",
           "date_label": "25.08.2026 – 28.08.2026",
           "end_date": "2026-08-28",
           "id": 1,
           "is_current": false,
           "lead_count": 10,
           "name": "Ambalaj Fuarı 2026 (örnek)",
           "start_date": "2026-08-25",
           "venue": "Fuar merkezi · Salon 4, Stand B12"
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/fairs/{id}/leads": {
   "get": {
    "operationId": "fairs_leads",
    "summary": "List fair leads",
    "description": "Leads collected at a fair (max 300, newest first).",
    "tags": [
     "Trade fairs & leads"
    ],
    "x-summary-tr": "Fuar leadlerini listele",
    "x-description-tr": "Fuarda toplanan leadler (en çok 300, yeniden eskiye).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Fair id.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "owner",
      "in": "query",
      "required": false,
      "description": "`me` (default for sales users), empty = everyone, or a user id.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "interest",
      "in": "query",
      "required": false,
      "description": "Interest level.",
      "schema": {
       "type": "string",
       "enum": [
        "Sıcak",
        "Ilık",
        "Soğuk"
       ]
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Company, person or phone contains.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "fair": {
          "id": 1,
          "name": "Ambalaj Fuarı 2026 (örnek)"
         },
         "ok": true,
         "rows": [
          {
           "can_edit": true,
           "city": "Bursa",
           "company": "Işıltı Ambalaj San. Tic. Ltd. Şti.",
           "contact_name": "Mehmet Arslan",
           "created_at": "2026-08-28T14:10:00",
           "customer_id": null,
           "email": "mehmet@isiltiambalajsanti.example",
           "fair": "Ambalaj Fuarı 2026 (örnek)",
           "fair_id": 1,
           "id": 4,
           "initials": "IA",
           "interest": "Soğuk",
           "line": "",
           "next_action": "Numune gönder",
           "next_date": "2026-10-07",
           "note": "Stantta görüşüldü.",
           "opp_id": null,
           "opp_type": "Mevcut Müşteri — Değişim",
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "phone": "0 (224) 000 96 45",
           "potential_kg": 6000.0,
           "products": "4",
           "products_text": "",
           "project_note": "",
           "rid": "00QCwrpUC4bpt3E",
           "sector": "Gıda ambalajı",
           "status": "Teklif verildi",
           "status_eff": "Teklif verildi",
           "supplier": "Mevcut tedarikçi (Asya)",
           "task_id": null,
           "timing": "6 ay içinde",
           "title": "Kalite Kontrol Müdürü",
           "unit": "kg",
           "visitor_type": "Potansiyel müşteri",
           "wa": "902240009645",
           "website": ""
          },
          {
           "can_edit": true,
           "city": "Tekirdağ",
           "company": "Nehirli Ambalaj San. Tic. Ltd. Şti.",
           "contact_name": "İpek Karaca",
           "created_at": "2026-08-28T12:10:00",
           "customer_id": null,
           "email": "ipek@nehirliambalajsant.example",
           "fair": "Ambalaj Fuarı 2026 (örnek)",
           "fair_id": 1,
           "id": 8,
           "initials": "NA",
           "interest": "Soğuk",
           "line": "",
           "next_action": "Teklif gönder",
           "next_date": "2026-10-13",
           "note": "Stantta görüşüldü.",
           "opp_id": null,
           "opp_type": "Mevcut Müşteri — Değişim",
           "owner": {
            "full_name": "Deniz Aksoy",
            "id": 1,
            "role": "admin",
            "role_label": "Yönetici",
            "username": "admin"
           },
           "phone": "0 (282) 000 76 98",
           "potential_kg": 2000.0,
           "products": "3",
           "products_text": "",
           "project_note": "",
           "rid": "00QBIhQqejYyYc3",
           "sector": "Film üretimi",
           "status": "Teklif verildi",
           "status_eff": "Teklif verildi",
           "supplier": "Mevcut tedarikçi (Asya)",
           "task_id": null,
           "timing": "Hemen",
           "title": "Satın Alma Müdürü",
           "unit": "kg",
           "visitor_type": "Potansiyel müşteri",
           "wa": "902820007698",
           "website": ""
          }
         ],
         "total": 10
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   },
   "post": {
    "operationId": "fairs_lead_create",
    "summary": "Create a lead",
    "description": "Records a lead at the fair stand; a next action opens a task for the owner.",
    "tags": [
     "Trade fairs & leads"
    ],
    "x-summary-tr": "Lead ekle",
    "x-description-tr": "Fuar standında lead kaydeder; sonraki aksiyon verilirse sorumluya görev açılır.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Fair id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "company": {
          "type": "string",
          "description": "Company name."
         },
         "contact_name": {
          "type": "string",
          "description": "Contact details."
         },
         "title": {
          "type": "string",
          "description": "Contact details."
         },
         "phone": {
          "type": "string",
          "description": "Contact details."
         },
         "email": {
          "type": "string",
          "description": "Contact details."
         },
         "city": {
          "type": "string",
          "description": "Company details."
         },
         "sector": {
          "type": "string",
          "description": "Company details."
         },
         "website": {
          "type": "string",
          "description": "Company details."
         },
         "visitor_type": {
          "type": "string",
          "enum": [
           "Potansiyel müşteri",
           "Mevcut müşteri",
           "Tedarikçi",
           "Rakip",
           "Diğer"
          ],
          "description": "Visitor type."
         },
         "interest": {
          "type": "string",
          "enum": [
           "Sıcak",
           "Ilık",
           "Soğuk"
          ],
          "description": "Interest."
         },
         "products": {
          "type": "array",
          "items": {
           "type": "integer"
          },
          "description": "Products of interest."
         },
         "products_text": {
          "type": "string",
          "description": "Products (free text)."
         },
         "potential_kg": {
          "type": "number",
          "description": "Monthly potential."
         },
         "timing": {
          "type": "string",
          "enum": [
           "Hemen",
           "3 ay içinde",
           "6 ay içinde",
           "1 yıl+",
           "Belirsiz"
          ],
          "description": "Timing."
         },
         "next_action": {
          "type": "string",
          "enum": [
           "Teklif gönder",
           "Ziyaret planla",
           "Numune gönder",
           "Deneme planla",
           "Bilgi gönder",
           "Ara",
           "Aksiyon yok"
          ],
          "description": "Next action."
         },
         "next_date": {
          "type": "string",
          "description": "Action date."
         },
         "owner_id": {
          "type": "integer",
          "description": "Owner."
         },
         "note": {
          "type": "string",
          "description": "Other fields."
         },
         "project_note": {
          "type": "string",
          "description": "Other fields."
         },
         "supplier": {
          "type": "string",
          "description": "Other fields."
         },
         "line": {
          "type": "string",
          "description": "Other fields."
         },
         "opp_type": {
          "type": "string",
          "description": "Other fields."
         }
        },
        "required": [
         "company"
        ]
       },
       "example": {
        "company": "Anadolu Gıda Ambalaj",
        "contact_name": "Murat Er",
        "title": "Genel Müdür",
        "phone": "+90 533 555 33 44",
        "interest": "Sıcak",
        "city": "Konya",
        "next_action": "Numune gönder",
        "next_date": "2026-10-07"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "lead": {
          "can_edit": true,
          "city": "Konya",
          "company": "Anadolu Gıda Ambalaj",
          "contact_name": "Murat Er",
          "created_at": "2026-10-02T20:07:01",
          "customer_id": null,
          "email": "",
          "fair": "Ambalaj Fuarı 2026 (örnek)",
          "fair_id": 1,
          "id": 11,
          "initials": "AG",
          "interest": "Sıcak",
          "line": "",
          "next_action": "Numune gönder",
          "next_date": "2026-10-07",
          "note": "",
          "opp_id": null,
          "opp_type": "",
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "phone": "+90 533 555 33 44",
          "potential_kg": null,
          "products": "",
          "products_text": "",
          "project_note": "",
          "rid": "00QpWFogpnPsXu7",
          "sector": "",
          "status": "Yeni",
          "status_eff": "Yeni",
          "supplier": "",
          "task_id": 25,
          "timing": "",
          "title": "Genel Müdür",
          "unit": "kg",
          "visitor_type": "Potansiyel müşteri",
          "wa": "905335553344",
          "website": ""
         },
         "ok": true
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/leads/{id}": {
   "get": {
    "operationId": "fairs_lead_get",
    "summary": "Get a lead",
    "description": "The lead and the product list (for form options).",
    "tags": [
     "Trade fairs & leads"
    ],
    "x-summary-tr": "Leadi getir",
    "x-description-tr": "Lead ve ürün listesi (form seçenekleri için).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Lead id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "lead": {
          "can_edit": true,
          "city": "Konya",
          "company": "Anadolu Gıda Ambalaj",
          "contact_name": "Murat Er",
          "created_at": "2026-10-02T20:07:01",
          "customer_id": null,
          "email": "",
          "fair": "Ambalaj Fuarı 2026 (örnek)",
          "fair_id": 1,
          "id": 11,
          "initials": "AG",
          "interest": "Sıcak",
          "line": "",
          "next_action": "Numune gönder",
          "next_date": "2026-10-07",
          "note": "",
          "opp_id": null,
          "opp_type": "",
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "phone": "+90 533 555 33 44",
          "potential_kg": null,
          "products": "",
          "products_text": "",
          "project_note": "",
          "rid": "00QpWFogpnPsXu7",
          "sector": "",
          "status": "Yeni",
          "status_eff": "Yeni",
          "supplier": "",
          "task_id": 25,
          "timing": "",
          "title": "Genel Müdür",
          "unit": "kg",
          "visitor_type": "Potansiyel müşteri",
          "wa": "905335553344",
          "website": ""
         },
         "ok": true,
         "products": [
          {
           "id": 5,
           "name": "HS 30 Isıl Yapışma Laki"
          },
          {
           "id": 3,
           "name": "PU-SB 450 Solvent Bazlı Yapıştırıcı"
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   },
   "patch": {
    "operationId": "fairs_lead_update",
    "summary": "Update a lead",
    "description": "Changes the status; sending `company` rewrites all form fields (fields you omit are cleared).",
    "tags": [
     "Trade fairs & leads"
    ],
    "x-summary-tr": "Leadi güncelle",
    "x-description-tr": "Durumu değiştirir; `company` gönderilirse tüm form alanları yeniden yazılır (gönderilmeyenler boşalır).",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Lead id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "status": {
          "type": "string",
          "enum": [
           "Yeni",
           "İletişime geçildi",
           "Teklif verildi",
           "Aktarıldı",
           "Vazgeçildi"
          ],
          "description": "Status."
         },
         "company": {
          "type": "string",
          "description": "Fields of the create endpoint."
         }
        }
       },
       "example": {
        "status": "İletişime geçildi"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "lead": {
          "can_edit": true,
          "city": "Konya",
          "company": "Anadolu Gıda Ambalaj",
          "contact_name": "Murat Er",
          "created_at": "2026-10-02T20:07:01",
          "customer_id": null,
          "email": "",
          "fair": "Ambalaj Fuarı 2026 (örnek)",
          "fair_id": 1,
          "id": 11,
          "initials": "AG",
          "interest": "Sıcak",
          "line": "",
          "next_action": "Numune gönder",
          "next_date": "2026-10-07",
          "note": "",
          "opp_id": null,
          "opp_type": "",
          "owner": {
           "full_name": "Deniz Aksoy",
           "id": 1,
           "role": "admin",
           "role_label": "Yönetici",
           "username": "admin"
          },
          "phone": "+90 533 555 33 44",
          "potential_kg": null,
          "products": "",
          "products_text": "",
          "project_note": "",
          "rid": "00QpWFogpnPsXu7",
          "sector": "",
          "status": "İletişime geçildi",
          "status_eff": "İletişime geçildi",
          "supplier": "",
          "task_id": 25,
          "timing": "",
          "title": "Genel Müdür",
          "unit": "kg",
          "visitor_type": "Potansiyel müşteri",
          "wa": "905335553344",
          "website": ""
         },
         "ok": true
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/threads": {
   "get": {
    "operationId": "email_threads",
    "summary": "List threads",
    "description": "E-mail threads either for one record (`kind` + `id`) or the inbox (`filter`, `q`). Content follows the user's permission to see it.",
    "tags": [
     "Email"
    ],
    "x-summary-tr": "Yazışmaları listele",
    "x-description-tr": "E-posta yazışmaları: bir kaydınkiler (`kind` + `id`) ya da gelen kutusu (`filter`, `q`). İçerik kullanıcının görme iznine göre gelir.",
    "parameters": [
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "description": "Record type.",
      "schema": {
       "type": "string",
       "enum": [
        "customer",
        "opp",
        "visit",
        "demo",
        "task",
        "offer",
        "ticket",
        "contract"
       ]
      }
     },
     {
      "name": "id",
      "in": "query",
      "required": false,
      "description": "Record id.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "filter",
      "in": "query",
      "required": false,
      "description": "`waiting` awaiting reply, `replied`, `mine`.",
      "schema": {
       "type": "string",
       "enum": [
        "all",
        "waiting",
        "replied",
        "mine"
       ]
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Subject or address contains.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "items": [
          {
           "customer": "Alize Paketleme San. ve Tic. A.Ş.",
           "customer_id": 1,
           "id": 1,
           "last_at": "2026-10-01T15:06:59",
           "last_dir": "out",
           "n": 2,
           "opp": "Mevcut Müşteri — Yenileme · 2026",
           "opp_how": "single",
           "opp_id": 31,
           "opp_note": "firmanın tek açık projesi",
           "peer": "selin.dogan@alizepaketleme.example",
           "subject": "Numune ve fiyat teklifi",
           "suggested": false,
           "waiting": false
          }
         ],
         "mailbox": {
          "connected": true,
          "email": "deniz@ornekkimya.com.tr",
          "error": "",
          "signature": false,
          "status": "ok"
         },
         "ok": true,
         "total": 1
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/threads/{id}": {
   "get": {
    "operationId": "email_thread",
    "summary": "Get a thread",
    "description": "Messages (`body: null`, `hidden: true` when the user may not see them), linked records, companies and people, a reply draft (`reply`) and link suggestions.",
    "tags": [
     "Email"
    ],
    "x-summary-tr": "Yazışmayı getir",
    "x-description-tr": "İletiler (görme izni yoksa `body: null`, `hidden: true`), bağlı kayıtlar, firmalar ve kişiler, yanıt taslağı (`reply`) ve bağlama önerileri.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Thread id.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "mailbox": {
          "connected": true,
          "email": "deniz@ornekkimya.com.tr",
          "error": "",
          "signature": false,
          "status": "ok"
         },
         "ok": true,
         "thread": {
          "companies": [
           {
            "contacts": [
             {
              "email": "selin.dogan@alizepaketleme.example",
              "id": 1,
              "name": "Selin Doğan"
             }
            ],
            "id": 1,
            "name": "Alize Paketleme San. ve Tic. A.Ş.",
            "role": "main"
           }
          ],
          "customer": "Alize Paketleme San. ve Tic. A.Ş.",
          "customer_id": 1,
          "id": 1,
          "last_at": "2026-10-01T15:06:59",
          "last_dir": "out",
          "linkables": [
           {
            "items": [
             {
              "id": 74,
              "label": "30.09.2026 · Call · Tanışma"
             }
            ],
            "kind": "visit",
            "klabel": "Ziyaret / görüşme"
           }
          ],
          "links": [],
          "may_edit": true,
          "messages": [
           {
            "at": "2026-09-30T17:06:59",
            "body": "Merhaba Deniz Bey,\n\nNumuneler bize ulaştı, hat denemesini perşembe yapacağız. Aylık 12 ton için güncel fiyatınızı paylaşabilir misiniz?\n\nİyi çalışmalar",
            "cc": "",
            "dir": "in",
            "from_addr": "selin.dogan@alizepaketleme.example",
            "from_name": "Selin Doğan",
            "hidden": false,
            "id": 1,
            "subject": "Numune ve fiyat teklifi",
            "to": "deniz@ornekkimya.com.tr"
           }
          ],
          "n": 2,
          "opp": "Mevcut Müşteri — Yenileme · 2026",
          "opp_how": "single",
          "opp_id": 31,
          "opp_note": "firmanın tek açık projesi",
          "opps": [
           {
            "id": 44,
            "name": "Müşteri Takibi",
            "open": true,
            "stage_label": "Müşteri Takibi"
           }
          ],
          "peer": "selin.dogan@alizepaketleme.example",
          "reply": {
           "contact_id": 1,
           "customer_id": 1,
           "in_reply_to": "<a2@mail.ornek>",
           "opp_id": 31,
           "subject": "Re: Numune ve fiyat teklifi",
           "to": "selin.dogan@alizepaketleme.example"
          },
          "subject": "Numune ve fiyat teklifi",
          "suggested": false,
          "suggestions": [
           {
            "date": "2026-09-30",
            "how": "",
            "id": 74,
            "kind": "visit",
            "klabel": "Ziyaret / görüşme",
            "label": "Call 30.09.2026",
            "nav": {
             "id": 74,
             "kind": "visit",
             "screen": "action"
            },
            "url": "/action/visit/74",
            "why": "yazışmayla aynı günlerde görüşme"
           }
          ],
          "waiting": false
         }
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/threads/{id}/{action}": {
   "post": {
    "operationId": "email_thread_act",
    "summary": "Link a thread",
    "description": "`opp` changes the project (`opp_id`), `link` links a record (`kind`, `obj_id`), `unlink` removes a link, `dismiss` ignores a suggestion. Only the thread's owner, the company owner or an admin may change it.",
    "tags": [
     "Email"
    ],
    "x-summary-tr": "Yazışmayı kayda bağla",
    "x-description-tr": "`opp` projeyi değiştirir (`opp_id`), `link` bir kayda bağlar (`kind`, `obj_id`), `unlink` bağı kaldırır, `dismiss` öneriyi yok sayar. Yalnız yazışmanın sahibi, firmanın sorumlusu ya da yönetici değiştirebilir.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Thread id.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "action",
      "in": "path",
      "required": true,
      "description": "Action.",
      "schema": {
       "type": "string",
       "enum": [
        "opp",
        "link",
        "unlink",
        "dismiss"
       ]
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "opp_id": {
          "type": "integer",
          "description": "Project (`opp`)."
         },
         "kind": {
          "type": "string",
          "description": "Record type (`link`/`unlink`)."
         },
         "obj_id": {
          "type": "integer",
          "description": "Record id."
         }
        }
       },
       "example": {
        "opp_id": 31
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "msg": "Yazışma projesi: Mevcut Müşteri — Yenileme · 2026.",
         "ok": true,
         "thread": {
          "companies": [
           {
            "contacts": [
             {
              "email": "selin.dogan@alizepaketleme.example",
              "id": 1,
              "name": "Selin Doğan"
             }
            ],
            "id": 1,
            "name": "Alize Paketleme San. ve Tic. A.Ş.",
            "role": "main"
           }
          ],
          "customer": "Alize Paketleme San. ve Tic. A.Ş.",
          "customer_id": 1,
          "id": 1,
          "last_at": "2026-10-01T15:06:59",
          "last_dir": "out",
          "linkables": [
           {
            "items": [
             {
              "id": 74,
              "label": "30.09.2026 · Call · Tanışma"
             }
            ],
            "kind": "visit",
            "klabel": "Ziyaret / görüşme"
           }
          ],
          "links": [],
          "may_edit": true,
          "messages": [
           {
            "at": "2026-09-30T17:06:59",
            "body": "Merhaba Deniz Bey,\n\nNumuneler bize ulaştı, hat denemesini perşembe yapacağız. Aylık 12 ton için güncel fiyatınızı paylaşabilir misiniz?\n\nİyi çalışmalar",
            "cc": "",
            "dir": "in",
            "from_addr": "selin.dogan@alizepaketleme.example",
            "from_name": "Selin Doğan",
            "hidden": false,
            "id": 1,
            "subject": "Numune ve fiyat teklifi",
            "to": "deniz@ornekkimya.com.tr"
           }
          ],
          "n": 2,
          "opp": "Mevcut Müşteri — Yenileme · 2026",
          "opp_how": "manual",
          "opp_id": 31,
          "opp_note": "elle seçildi",
          "opps": [
           {
            "id": 44,
            "name": "Müşteri Takibi",
            "open": true,
            "stage_label": "Müşteri Takibi"
           }
          ],
          "peer": "selin.dogan@alizepaketleme.example",
          "reply": {
           "contact_id": 1,
           "customer_id": 1,
           "in_reply_to": "<a2@mail.ornek>",
           "opp_id": 31,
           "subject": "Re: Numune ve fiyat teklifi",
           "to": "selin.dogan@alizepaketleme.example"
          },
          "subject": "Numune ve fiyat teklifi",
          "suggested": false,
          "suggestions": [
           {
            "date": "2026-09-30",
            "how": "",
            "id": 74,
            "kind": "visit",
            "klabel": "Ziyaret / görüşme",
            "label": "Call 30.09.2026",
            "nav": {
             "id": 74,
             "kind": "visit",
             "screen": "action"
            },
            "url": "/action/visit/74",
            "why": "yazışmayla aynı günlerde görüşme"
           }
          ],
          "waiting": false
         }
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "403": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "404": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/emails/compose": {
   "get": {
    "operationId": "email_compose",
    "summary": "Compose options",
    "description": "For a new e-mail: whether the mailbox is connected, the company's people with e-mail and its open projects.",
    "tags": [
     "Email"
    ],
    "x-summary-tr": "E-posta hazırlığı",
    "x-description-tr": "Yeni e-posta için: hesabın bağlı olup olmadığı, firmanın e-postalı kişileri ve açık projeleri.",
    "parameters": [
     {
      "name": "customer_id",
      "in": "query",
      "required": false,
      "description": "Company.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "opp_id",
      "in": "query",
      "required": false,
      "description": "Project.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "contacts": [
          {
           "email": "selin.dogan@alizepaketleme.example",
           "id": 1,
           "main": true,
           "name": "Selin Doğan",
           "title": "Satın Alma Müdürü"
          }
         ],
         "customer": {
          "id": 1,
          "name": "Alize Paketleme San. ve Tic. A.Ş."
         },
         "mailbox": {
          "connected": true,
          "email": "deniz@ornekkimya.com.tr",
          "error": "",
          "signature": false,
          "status": "ok"
         },
         "ok": true,
         "opp": null,
         "opps": [
          {
           "id": 44,
           "name": "Müşteri Takibi",
           "stage_label": "Müşteri Takibi"
          },
          {
           "id": 31,
           "name": "Mevcut Müşteri — Yenileme · 2026",
           "stage_label": "Qualify"
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/emails/send": {
   "post": {
    "operationId": "email_send",
    "summary": "Send an e-mail",
    "description": "Sends one e-mail (including replies) from the user's connected mailbox; it joins the thread and project under the web rules. Returns `400 send` when no mailbox is connected. JSON body only.",
    "tags": [
     "Email"
    ],
    "x-summary-tr": "E-posta gönder",
    "x-description-tr": "Kullanıcının bağlı e-posta hesabından tek e-posta (yanıt dahil) gönderir; ileti yazışmaya ve projeye web'deki kurallarla bağlanır. Hesap bağlı değilse `400 send` döner. Yalnız JSON gövde kabul edilir.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "to": {
          "type": "string",
          "description": "Recipient(s), comma separated."
         },
         "subject": {
          "type": "string",
          "description": "Subject."
         },
         "body": {
          "type": "string",
          "description": "Body (plain text)."
         },
         "cc": {
          "type": "string",
          "description": "Cc."
         },
         "customer_id": {
          "type": "integer",
          "description": "Records to link."
         },
         "contact_id": {
          "type": "integer",
          "description": "Records to link."
         },
         "opp_id": {
          "type": "integer",
          "description": "Records to link."
         },
         "in_reply_to": {
          "type": "string",
          "description": "Message-ID being replied to (`reply.in_reply_to`)."
         }
        },
        "required": [
         "to",
         "subject",
         "body"
        ]
       },
       "example": {
        "to": "x@ornek.com",
        "subject": "Deneme",
        "body": ""
       }
      }
     }
    },
    "responses": {
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "example": {
         "error": "invalid",
         "message": "E-posta metni boş.",
         "ok": false
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.write"
      ]
     }
    ]
   }
  },
  "/api/v1/ask": {
   "post": {
    "operationId": "ask_ask",
    "summary": "Ask a question",
    "description": "A natural-language question about CRM data: with the AI module on, the model answers (`mode: ai`); otherwise a rule-based answer (`mode: kural`). `blocks` is a renderable structure, `refs` the records mentioned. JSON body only.",
    "tags": [
     "Ask"
    ],
    "x-summary-tr": "Soru sor",
    "x-description-tr": "CRM verisine doğal dilde soru: Yapay Zekâ modülü açıksa model yanıtlar (`mode: ai`), değilse kural tabanlı yanıt gelir (`mode: kural`). `blocks` ekrana çizilecek yapıdır, `refs` yanıtta geçen kayıtlar. Yalnız JSON gövde.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "q": {
          "type": "string",
          "description": "Question."
         },
         "history": {
          "type": "array",
          "items": {},
          "description": "Previous turns (chat context)."
         }
        },
        "required": [
         "q"
        ]
       },
       "example": {
        "q": "Bu hafta geciken aksiyonlarım neler?"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ai": false,
         "blocks": [
          {
           "muted": false,
           "spans": [
            {
             "b": true,
             "text": "Gecikmiş 2 görev"
            }
           ],
           "t": "p"
          },
          {
           "muted": false,
           "spans": [
            {
             "b": false,
             "nav": {
              "id": 17,
              "kind": "task",
              "screen": "action"
             },
             "text": "Fiyat listesini güncelleyip gönder",
             "url": "/action/task/17"
            }
           ],
           "t": "li"
          }
         ],
         "mode": "kural",
         "ok": true,
         "q": "Bu hafta geciken aksiyonlarım neler?",
         "refs": [
          {
           "kind": "task",
           "label": "Fiyat listesini güncelleyip gönder",
           "nav": {
            "id": 17,
            "kind": "task",
            "screen": "action"
           },
           "url": "/action/task/17"
          },
          {
           "kind": "task",
           "label": "Yeni hat devreye alma toplantısı",
           "nav": {
            "id": 8,
            "kind": "task",
            "screen": "action"
           },
           "url": "/action/task/8"
          }
         ],
         "text": "**Gecikmiş 2 görev** (sizin)\n- [Fiyat listesini güncelleyip gönder](/action/task/17) · 26.09.2026 · Hanımeli Etiket San. Tic. Ltd. Şti.\n- [Yeni hat devreye alma toplantısı](/action/task/8) · 30.09.2026 · Işıltı Film A.Ş."
        }
       }
      }
     },
     "400": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/v1/ask/history": {
   "get": {
    "operationId": "ask_history",
    "summary": "Question history",
    "description": "The user's last 12 questions and suggested questions.",
    "tags": [
     "Ask"
    ],
    "x-summary-tr": "Son sorular",
    "x-description-tr": "Kullanıcının son 12 sorusu ve önerilen sorular.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "ai": false,
         "items": [
          {
           "at": "2026-10-02T20:07:01",
           "mode": "kural",
           "q": "Bu hafta geciken aksiyonlarım neler?"
          }
         ],
         "ok": true,
         "suggest": [
          "Bu ay kapanması beklenen fırsatlar",
          "Gecikmiş görevlerim"
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "bearerAuth": []
     },
     {
      "oauth2": [
       "crm.read"
      ]
     }
    ]
   }
  },
  "/api/scim/v2/ServiceProviderConfig": {
   "get": {
    "operationId": "scim_spc",
    "summary": "Service provider config",
    "description": "Supported SCIM features (PATCH yes; bulk, sort, ETag no).",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Sağlayıcı yapılandırması",
    "x-description-tr": "Desteklenen SCIM özellikleri (PATCH var; toplu işlem, sıralama, ETag yok).",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"
         ],
         "patch": {
          "supported": true
         },
         "bulk": {
          "supported": false
         },
         "filter": {
          "supported": true,
          "maxResults": 200
         },
         "changePassword": {
          "supported": false
         },
         "sort": {
          "supported": false
         },
         "etag": {
          "supported": false
         },
         "authenticationSchemes": [
          {
           "type": "oauthbearertoken",
           "name": "Bearer",
           "description": "Ayarlar → Uygulamalar → SCIM anahtarı"
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   }
  },
  "/api/scim/v2/ResourceTypes": {
   "get": {
    "operationId": "scim_resource_types",
    "summary": "Resource types",
    "description": "Only the `User` resource.",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Kaynak türleri",
    "x-description-tr": "Yalnız `User` kaynağı.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:api:messages:2.0:ListResponse"
         ],
         "totalResults": 1,
         "Resources": [
          {
           "schemas": [
            "urn:ietf:params:scim:schemas:core:2.0:ResourceType"
           ],
           "id": "User",
           "name": "User",
           "endpoint": "/Users",
           "schema": "urn:ietf:params:scim:schemas:core:2.0:User",
           "schemaExtensions": [
            {
             "schema": "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
             "required": false
            }
           ]
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   }
  },
  "/api/scim/v2/Schemas": {
   "get": {
    "operationId": "scim_schemas",
    "summary": "Schemas",
    "description": "User and enterprise extension schemas.",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Şemalar",
    "x-description-tr": "Kullanıcı ve kurumsal uzantı şemaları.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:api:messages:2.0:ListResponse"
         ],
         "totalResults": 1,
         "Resources": [
          {
           "id": "urn:ietf:params:scim:schemas:core:2.0:User",
           "name": "User",
           "attributes": [
            {
             "name": "userName",
             "type": "string",
             "required": true,
             "uniqueness": "server"
            }
           ]
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   }
  },
  "/api/scim/v2/Users": {
   "get": {
    "operationId": "scim_users_list",
    "summary": "List users",
    "description": "Users; only the `userName eq \"…\"` (or `id eq`) filter is supported. Paging via `startIndex` + `count` (max 200).",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Kullanıcıları listele",
    "x-description-tr": "Kullanıcılar; yalnız `userName eq \"…\"` (ya da `id eq`) süzgeci desteklenir. Sayfalama `startIndex` + `count` (en çok 200).",
    "parameters": [
     {
      "name": "filter",
      "in": "query",
      "required": false,
      "description": "`userName eq \"name@company.com\"`",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "startIndex",
      "in": "query",
      "required": false,
      "description": "Starts at 1.",
      "schema": {
       "type": "integer",
       "default": 1
      }
     },
     {
      "name": "count",
      "in": "query",
      "required": false,
      "description": "Page size.",
      "schema": {
       "type": "integer",
       "default": 100
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:api:messages:2.0:ListResponse"
         ],
         "totalResults": 1,
         "startIndex": 1,
         "itemsPerPage": 1,
         "Resources": [
          {
           "schemas": [
            "urn:ietf:params:scim:schemas:core:2.0:User",
            "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
           ],
           "id": "2",
           "userName": "ayse.demir@ornekkimya.com.tr",
           "displayName": "Ayşe Demir",
           "name": {
            "formatted": "Ayşe Demir",
            "givenName": "Ayşe",
            "familyName": "Demir"
           },
           "active": true,
           "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
            "department": "Satış"
           },
           "meta": {
            "resourceType": "User",
            "location": "https://ornek.solk.app/api/scim/v2/Users/2"
           },
           "emails": [
            {
             "value": "ayse.demir@ornekkimya.com.tr",
             "type": "work",
             "primary": true
            }
           ]
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   },
   "post": {
    "operationId": "scim_users_create",
    "summary": "Create a user",
    "description": "Creates a user and sends a set-password invitation (role: sales). An existing e-mail returns `409 uniqueness`.",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Kullanıcı aç",
    "x-description-tr": "Kullanıcı açar ve şifre belirleme daveti gönderir (rol: satışçı). Aynı e-posta varsa `409 uniqueness`.",
    "responses": {
     "201": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:schemas:core:2.0:User",
          "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
         ],
         "id": "2",
         "userName": "ayse.demir@ornekkimya.com.tr",
         "displayName": "Ayşe Demir",
         "name": {
          "formatted": "Ayşe Demir",
          "givenName": "Ayşe",
          "familyName": "Demir"
         },
         "active": true,
         "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
          "department": "Satış"
         },
         "meta": {
          "resourceType": "User",
          "location": "https://ornek.solk.app/api/scim/v2/Users/2"
         },
         "emails": [
          {
           "value": "ayse.demir@ornekkimya.com.tr",
           "type": "work",
           "primary": true
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   }
  },
  "/api/scim/v2/Users/{id}": {
   "get": {
    "operationId": "scim_user_get",
    "summary": "Get a user",
    "description": "One user.",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Kullanıcıyı getir",
    "x-description-tr": "Tek kullanıcı.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "User id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:schemas:core:2.0:User",
          "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
         ],
         "id": "2",
         "userName": "ayse.demir@ornekkimya.com.tr",
         "displayName": "Ayşe Demir",
         "name": {
          "formatted": "Ayşe Demir",
          "givenName": "Ayşe",
          "familyName": "Demir"
         },
         "active": true,
         "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
          "department": "Satış"
         },
         "meta": {
          "resourceType": "User",
          "location": "https://ornek.solk.app/api/scim/v2/Users/2"
         },
         "emails": [
          {
           "value": "ayse.demir@ornekkimya.com.tr",
           "type": "work",
           "primary": true
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   },
   "put": {
    "operationId": "scim_user_put",
    "summary": "Replace a user",
    "description": "Rewrites name, e-mail, department, phone and `active`.",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Kullanıcıyı değiştir",
    "x-description-tr": "Ad, e-posta, departman, telefon ve `active` alanlarını yeniden yazar.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "User id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:schemas:core:2.0:User",
          "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
         ],
         "id": "2",
         "userName": "ayse.demir@ornekkimya.com.tr",
         "displayName": "Ayşe Demir Kaya",
         "name": {
          "formatted": "Ayşe Demir Kaya",
          "givenName": "Ayşe Demir",
          "familyName": "Kaya"
         },
         "active": true,
         "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
          "department": ""
         },
         "meta": {
          "resourceType": "User",
          "location": "https://ornek.solk.app/api/scim/v2/Users/2"
         },
         "emails": [
          {
           "value": "ayse.demir@ornekkimya.com.tr",
           "type": "work",
           "primary": true
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   },
   "patch": {
    "operationId": "scim_user_patch",
    "summary": "Update a user",
    "description": "`replace`, `add`, `remove` operations; `active: false` deactivates the user (mobile sessions and API keys are revoked, records stay; the last active admin can't be deactivated). `active: true` needs a free seat.",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Kullanıcıyı güncelle",
    "x-description-tr": "`replace`, `add`, `remove` işlemleri; `active: false` kullanıcıyı kapatır (mobil oturumları ve API anahtarları düşer, kayıtları kalır; son etkin yönetici kapatılamaz). `active: true` boş koltuk ister.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "User id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:schemas:core:2.0:User",
          "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
         ],
         "id": "2",
         "userName": "ayse.demir@ornekkimya.com.tr",
         "displayName": "Ayşe Demir",
         "name": {
          "formatted": "Ayşe Demir",
          "givenName": "Ayşe",
          "familyName": "Demir"
         },
         "active": false,
         "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
          "department": "Satış"
         },
         "meta": {
          "resourceType": "User",
          "location": "https://ornek.solk.app/api/scim/v2/Users/2"
         },
         "emails": [
          {
           "value": "ayse.demir@ornekkimya.com.tr",
           "type": "work",
           "primary": true
          }
         ]
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   },
   "delete": {
    "operationId": "scim_user_delete",
    "summary": "Deactivate a user",
    "description": "Deactivates the user instead of deleting; records and history are kept. Returns `204`.",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Kullanıcıyı kapat",
    "x-description-tr": "Kullanıcıyı siler gibi kapatır; kayıtlar ve geçmiş korunur. `204` döner.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "User id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "OK"
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   }
  },
  "/api/scim/v2/Groups": {
   "get": {
    "operationId": "scim_groups",
    "summary": "Groups",
    "description": "No group sync; returns an empty list (roles are set in the CRM).",
    "tags": [
     "SCIM 2.0"
    ],
    "x-summary-tr": "Gruplar",
    "x-description-tr": "Grup eşitleme yok; boş liste döner (roller CRM'de atanır).",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "schemas": [
          "urn:ietf:params:scim:api:messages:2.0:ListResponse"
         ],
         "totalResults": 0,
         "startIndex": 1,
         "itemsPerPage": 0,
         "Resources": []
        }
       }
      }
     }
    },
    "security": [
     {
      "scimToken": []
     }
    ]
   }
  },
  "/.well-known/oauth-protected-resource/mcp": {
   "get": {
    "operationId": "oauth_prm",
    "summary": "Protected resource metadata",
    "description": "RFC 9728 document: the MCP resource, its authorization server and scopes. Clients arrive here from `resource_metadata` in a `401`.",
    "tags": [
     "OAuth 2.1"
    ],
    "x-summary-tr": "Korunan kaynak bilgisi",
    "x-description-tr": "RFC 9728 belgesi: MCP kaynağının adresi, yetkilendirme sunucusu ve kapsamlar. İstemciler `401` yanıtındaki `resource_metadata`'dan buraya gelir.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "authorization_servers": [
          "https://ornek.solk.app"
         ],
         "bearer_methods_supported": [
          "header"
         ],
         "resource": "https://ornek.solk.app/mcp",
         "resource_documentation": "https://docs.solk.app/mcp/overview",
         "resource_name": "Solk CRM (Örnek Kimya)",
         "scopes_supported": [
          "crm.read",
          "crm.write"
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/.well-known/oauth-authorization-server": {
   "get": {
    "operationId": "oauth_asm",
    "summary": "Authorization server metadata",
    "description": "RFC 8414 document: endpoint URLs, supported flows (`authorization_code` with PKCE S256 and `refresh_token` only), client auth methods.",
    "tags": [
     "OAuth 2.1"
    ],
    "x-summary-tr": "Yetkilendirme sunucusu bilgisi",
    "x-description-tr": "RFC 8414 belgesi: uç adresleri, desteklenen akışlar (yalnız `authorization_code` + PKCE S256 ve `refresh_token`), istemci kimlik doğrulama yöntemleri.",
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "authorization_endpoint": "https://ornek.solk.app/oauth/authorize",
         "client_id_metadata_document_supported": true,
         "code_challenge_methods_supported": [
          "S256"
         ],
         "grant_types_supported": [
          "authorization_code",
          "refresh_token"
         ],
         "issuer": "https://ornek.solk.app",
         "registration_endpoint": "https://ornek.solk.app/oauth/register",
         "response_modes_supported": [
          "query"
         ],
         "response_types_supported": [
          "code"
         ],
         "revocation_endpoint": "https://ornek.solk.app/oauth/revoke",
         "revocation_endpoint_auth_methods_supported": [
          "none",
          "client_secret_post",
          "client_secret_basic"
         ],
         "scopes_supported": [
          "crm.read",
          "crm.write",
          "offline_access"
         ],
         "service_documentation": "https://ornek.solk.app/settings/connections",
         "token_endpoint": "https://ornek.solk.app/oauth/token",
         "token_endpoint_auth_methods_supported": [
          "none",
          "client_secret_post",
          "client_secret_basic"
         ]
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/oauth/register": {
   "post": {
    "operationId": "oauth_register",
    "summary": "Register a client",
    "description": "Dynamic client registration (RFC 7591). `redirect_uris` must be https or loopback (`http://localhost`, `127.0.0.1`, `[::1]`); max 10. `token_endpoint_auth_method: none` registers a public client; `client_secret_post` / `client_secret_basic` a confidential one.",
    "tags": [
     "OAuth 2.1"
    ],
    "x-summary-tr": "İstemci kaydı",
    "x-description-tr": "Dinamik istemci kaydı (RFC 7591). `redirect_uris` https ya da yerel geri döngü (`http://localhost`, `127.0.0.1`, `[::1]`) olmalı; en çok 10. `token_endpoint_auth_method: none` genel (public) istemci, `client_secret_post` / `client_secret_basic` gizli anahtarlı istemci açar.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "redirect_uris": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "description": "Redirect URIs."
         },
         "client_name": {
          "type": "string",
          "description": "Name shown on the consent screen."
         },
         "client_uri": {
          "type": "string",
          "description": "App website (https)."
         },
         "token_endpoint_auth_method": {
          "type": "string",
          "enum": [
           "none",
           "client_secret_post",
           "client_secret_basic"
          ],
          "description": "Client authentication."
         },
         "grant_types": {
          "type": "array",
          "items": {
           "type": "string"
          },
          "description": "`authorization_code`, `refresh_token`."
         }
        },
        "required": [
         "redirect_uris"
        ]
       },
       "example": {
        "client_name": "Örnek Entegrasyon",
        "redirect_uris": [
         "https://uygulamaniz.com/oauth/callback"
        ],
        "token_endpoint_auth_method": "none"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "client_id": "crm_sN-deD6QaASdSwwlE2np8BWe",
         "client_id_issued_at": 1790960821,
         "client_name": "Örnek Entegrasyon",
         "grant_types": [
          "authorization_code",
          "refresh_token"
         ],
         "redirect_uris": [
          "https://uygulamaniz.com/oauth/callback"
         ],
         "response_types": [
          "code"
         ],
         "token_endpoint_auth_method": "none"
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/oauth/authorize": {
   "get": {
    "operationId": "oauth_authorize",
    "summary": "Authorize",
    "description": "Sends the user to the consent screen (signing in first if needed). On approval it redirects to `redirect_uri?code=…&state=…`; on denial `error=access_denied`. PKCE (S256) is mandatory.",
    "tags": [
     "OAuth 2.1"
    ],
    "x-summary-tr": "Yetkilendir",
    "x-description-tr": "Kullanıcıyı onay ekranına götürür (oturum yoksa önce giriş). Onaylanınca `redirect_uri?code=…&state=…` adresine döner; reddedilirse `error=access_denied`. PKCE (S256) zorunludur.",
    "parameters": [
     {
      "name": "response_type",
      "in": "query",
      "required": true,
      "description": "Only `code`.",
      "schema": {
       "type": "string",
       "enum": [
        "code"
       ]
      }
     },
     {
      "name": "client_id",
      "in": "query",
      "required": true,
      "description": "Client id from registration or a CIMD URL.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "redirect_uri",
      "in": "query",
      "required": true,
      "description": "A registered redirect URI.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "scope",
      "in": "query",
      "required": false,
      "description": "`crm.read crm.write` (and optional `offline_access`). Both when empty.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "state",
      "in": "query",
      "required": false,
      "description": "Client CSRF value (echoed back).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "code_challenge",
      "in": "query",
      "required": true,
      "description": "BASE64URL(SHA256(code_verifier)).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "code_challenge_method",
      "in": "query",
      "required": true,
      "description": "Only `S256`.",
      "schema": {
       "type": "string",
       "enum": [
        "S256"
       ]
      }
     },
     {
      "name": "resource",
      "in": "query",
      "required": false,
      "description": "The MCP resource (`https://<install>/mcp`) — leave empty for REST.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "302": {
      "description": "Error"
     }
    },
    "security": []
   }
  },
  "/oauth/token": {
   "post": {
    "operationId": "oauth_token",
    "summary": "Get a token",
    "description": "Form body (`application/x-www-form-urlencoded`). `authorization_code`: code + `code_verifier` → a 1-hour access token (`mcp_…`) + a 60-day refresh token (`mcpr_…`). `refresh_token`: every refresh returns a new pair and revokes the old one. A code works once; reusing it revokes the tokens issued from that grant.",
    "tags": [
     "OAuth 2.1"
    ],
    "x-summary-tr": "Belirteç al",
    "x-description-tr": "Form gövdesi (`application/x-www-form-urlencoded`). `authorization_code`: kod + `code_verifier` → 1 saatlik erişim belirteci (`mcp_…`) + 60 günlük yenileme belirteci (`mcpr_…`). `refresh_token`: her yenilemede yeni çift verilir, eskisi düşer. Kod yalnız bir kez kullanılır; ikinci kullanım o izinden verilmiş belirteçleri iptal eder.",
    "requestBody": {
     "required": true,
     "content": {
      "application/x-www-form-urlencoded": {
       "schema": {
        "type": "object",
        "properties": {
         "grant_type": {
          "type": "string",
          "enum": [
           "authorization_code",
           "refresh_token"
          ],
          "description": "Grant type."
         },
         "code": {
          "type": "string",
          "description": "Authorization code."
         },
         "redirect_uri": {
          "type": "string",
          "description": "Same as in authorize."
         },
         "code_verifier": {
          "type": "string",
          "description": "PKCE verifier."
         },
         "refresh_token": {
          "type": "string",
          "description": "Refresh token."
         },
         "client_id": {
          "type": "string",
          "description": "Client id."
         },
         "client_secret": {
          "type": "string",
          "description": "For confidential clients."
         }
        },
        "required": [
         "grant_type",
         "client_id"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "example": {
         "access_token": "mcp_uBprY6…",
         "expires_in": 3600,
         "refresh_token": "mcpr_AXksm…",
         "scope": "crm.read crm.write",
         "token_type": "Bearer"
        }
       }
      }
     }
    },
    "security": []
   }
  },
  "/oauth/revoke": {
   "post": {
    "operationId": "oauth_revoke",
    "summary": "Revoke a token",
    "description": "Revokes an access or refresh token (RFC 7009); always returns `200`. Users remove the whole grant in Settings → App connections.",
    "tags": [
     "OAuth 2.1"
    ],
    "x-summary-tr": "Belirteci iptal et",
    "x-description-tr": "Erişim ya da yenileme belirtecini iptal eder (RFC 7009); her zaman `200` döner. Kullanıcı izni tümden Ayarlar → Uygulama bağlantıları'ndan kaldırır.",
    "requestBody": {
     "required": true,
     "content": {
      "application/x-www-form-urlencoded": {
       "schema": {
        "type": "object",
        "properties": {
         "token": {
          "type": "string",
          "description": "Token."
         }
        },
        "required": [
         "token"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "OK"
     }
    },
    "security": []
   }
  }
 },
 "components": {
  "securitySchemes": {
   "bearerAuth": {
    "type": "http",
    "scheme": "bearer",
    "description": "API key (sk_…) from Settings → Developers, OAuth access token (mcp_…) or mobile session token (xk_…)."
   },
   "oauth2": {
    "type": "oauth2",
    "description": "Authorization code with PKCE (S256). Discovery: /.well-known/oauth-authorization-server",
    "flows": {
     "authorizationCode": {
      "authorizationUrl": "https://ornek.solk.app/oauth/authorize",
      "tokenUrl": "https://ornek.solk.app/oauth/token",
      "refreshUrl": "https://ornek.solk.app/oauth/token",
      "scopes": {
       "crm.read": "Read records",
       "crm.write": "Create and update records"
      }
     }
    }
   },
   "scimToken": {
    "type": "http",
    "scheme": "bearer",
    "description": "SCIM key from Settings → Apps → SCIM"
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "required": [
     "ok",
     "error"
    ],
    "properties": {
     "ok": {
      "type": "boolean",
      "const": false
     },
     "error": {
      "type": "string",
      "enum": [
       "unauthorized",
       "credentials",
       "otp_required",
       "otp_invalid",
       "forbidden",
       "insufficient_scope",
       "module",
       "license",
       "ip",
       "not_found",
       "invalid",
       "send",
       "exists",
       "similar",
       "gate",
       "locked",
       "rate_limited",
       "limit"
      ]
     },
     "message": {
      "type": "string",
      "description": "Turkish, human-readable"
     }
    }
   }
  }
 }
}