{
  "openapi": "3.1.0",
  "info": {
    "title": "Klik Flow API",
    "version": "2.0.0",
    "description": "API Klik Flow untuk mengirim WhatsApp dan membaca data bisnis dari sistem Anda. Panduan lengkap: /docs/api."
  },
  "servers": [
    {
      "url": "https://klikflow.id"
    }
  ],
  "tags": [
    {
      "name": "API v2",
      "description": "Satu API untuk WhatsApp (scan QR) dan WhatsApp Official: kirim teks, file, template, dan OTP, balas percakapan, kelola kontak, baca saluran dan template. Kunci tes hanya ke nomor uji."
    },
    {
      "name": "Webhook v2",
      "description": "Event yang dikirim Klik Flow ke URL webhook Anda."
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Kunci API (kf_live_… atau kf_test_…), dari Pengaturan › API & Webhook › Buat kunci."
      }
    }
  },
  "paths": {
    "/api/v2/messages": {
      "post": {
        "operationId": "v2-messages-send",
        "summary": "Kirim pesan",
        "description": "Satu endpoint untuk WhatsApp (scan QR) dan WhatsApp Official: teks, file, template, atau kode OTP.\n\nPilih saluran dengan `channel`. Klik Flow memakai nomor pertama yang boleh dipakai kunci, atau nomor di `from`. WhatsApp Official di luar 24 jam sejak pelanggan terakhir menulis hanya bisa `template` atau `otp`. Kirim header `Idempotency-Key` agar kirim ulang tidak menghasilkan pesan kedua. Kunci tes hanya mengirim ke nomor uji.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "description": "Saluran pengirim.",
                    "enum": [
                      "whatsapp_qr",
                      "whatsapp_official"
                    ],
                    "examples": [
                      "whatsapp_official"
                    ]
                  },
                  "to": {
                    "type": "string",
                    "description": "Nomor tujuan dengan kode negara; 08… diubah menjadi 628….",
                    "examples": [
                      "6281234567890"
                    ]
                  },
                  "type": {
                    "type": "string",
                    "description": "Jenis pesan. `template` dan `otp` hanya untuk whatsapp_official.",
                    "enum": [
                      "text",
                      "image",
                      "video",
                      "audio",
                      "document",
                      "template",
                      "otp"
                    ],
                    "examples": [
                      "template"
                    ]
                  },
                  "from": {
                    "type": "string",
                    "description": "Nomor pengirim tertentu: id perangkat (whatsapp_qr) atau id nomor (whatsapp_official), dari `GET /api/v2/channels`."
                  },
                  "text": {
                    "type": "object",
                    "description": "`{ \"body\": \"…\" }`, maksimal 4.000 karakter. Untuk type text.",
                    "additionalProperties": true
                  },
                  "media": {
                    "type": "object",
                    "description": "`url` (https) atau `base64` + `mime`, dengan `filename` dan `caption`. Untuk type file.",
                    "additionalProperties": true
                  },
                  "template": {
                    "type": "object",
                    "description": "`name`, `language`, `variables` (objek atau array), `header_variables`, `media_url`, `button_url`, `coupon_code`.",
                    "additionalProperties": true
                  },
                  "otp": {
                    "type": "object",
                    "description": "`template` (template Autentikasi) dan `code` (1–15 huruf, angka, atau `-`). Kode tidak disimpan.",
                    "additionalProperties": true
                  }
                },
                "required": [
                  "channel",
                  "to",
                  "type"
                ]
              },
              "example": {
                "channel": "whatsapp_official",
                "to": "6281234567890",
                "type": "template",
                "template": {
                  "name": "konfirmasi_pesanan",
                  "language": "id",
                  "variables": {
                    "nama": "Rina",
                    "orderid": "INV-2207"
                  },
                  "button_url": "INV-2207"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 99140,
                    "object": "message",
                    "conversation_id": 812,
                    "channel": "whatsapp_official",
                    "to": "6281234567890",
                    "type": "template",
                    "status": "sent",
                    "test": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_json, idempotency_key_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_json": {
                    "summary": "Body bukan JSON yang sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_json",
                        "message": "Body bukan JSON yang sah",
                        "doc_url": "/docs/api/error#invalid_json",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "idempotency_key_invalid": {
                    "summary": "Idempotency-Key tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "idempotency_key_invalid",
                        "message": "Idempotency-Key tidak sah",
                        "doc_url": "/docs/api/error#idempotency_key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, test_number_required, channel_not_allowed, channel_paused",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "test_number_required": {
                    "summary": "Kunci tes hanya ke nomor uji",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "test_number_required",
                        "message": "Kunci tes hanya ke nomor uji",
                        "doc_url": "/docs/api/error#test_number_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_not_allowed": {
                    "summary": "Saluran tidak boleh dipakai kunci ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "channel_not_allowed",
                        "message": "Saluran tidak boleh dipakai kunci ini",
                        "doc_url": "/docs/api/error#channel_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_paused": {
                    "summary": "Saluran sedang dijeda",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "channel_paused",
                        "message": "Saluran sedang dijeda",
                        "doc_url": "/docs/api/error#channel_paused",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found, template_not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "template_not_found": {
                    "summary": "Template tidak ditemukan atau belum disetujui",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "template_not_found",
                        "message": "Template tidak ditemukan atau belum disetujui",
                        "doc_url": "/docs/api/error#template_not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "idempotency_conflict, request_in_progress, channel_unavailable, window_closed",
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency-Key dipakai untuk isi lain",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "idempotency_conflict",
                        "message": "Idempotency-Key dipakai untuk isi lain",
                        "doc_url": "/docs/api/error#idempotency_conflict",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "request_in_progress": {
                    "summary": "Permintaan yang sama masih diproses",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "request_in_progress",
                        "message": "Permintaan yang sama masih diproses",
                        "doc_url": "/docs/api/error#request_in_progress",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_unavailable": {
                    "summary": "Tidak ada nomor WhatsApp yang bisa dipakai",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "channel_unavailable",
                        "message": "Tidak ada nomor WhatsApp yang bisa dipakai",
                        "doc_url": "/docs/api/error#channel_unavailable",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "window_closed": {
                    "summary": "Di luar jendela 24 jam",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "window_closed",
                        "message": "Di luar jendela 24 jam",
                        "doc_url": "/docs/api/error#window_closed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "media_too_large",
            "content": {
              "application/json": {
                "examples": {
                  "media_too_large": {
                    "summary": "File terlalu besar",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "media_too_large",
                        "message": "File terlalu besar",
                        "doc_url": "/docs/api/error#media_too_large",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request, invalid_phone, message_too_long, contact_blocked, template_values, template_not_supported, otp_code_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "invalid_phone": {
                    "summary": "Nomor tujuan tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_phone",
                        "message": "Nomor tujuan tidak sah",
                        "doc_url": "/docs/api/error#invalid_phone",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "message_too_long": {
                    "summary": "Pesan terlalu panjang",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "message_too_long",
                        "message": "Pesan terlalu panjang",
                        "doc_url": "/docs/api/error#message_too_long",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "contact_blocked": {
                    "summary": "Kontak diblokir atau berhenti berlangganan",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "contact_blocked",
                        "message": "Kontak diblokir atau berhenti berlangganan",
                        "doc_url": "/docs/api/error#contact_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "template_values": {
                    "summary": "Variabel template belum lengkap",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "template_values",
                        "message": "Variabel template belum lengkap",
                        "doc_url": "/docs/api/error#template_values",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "template_not_supported": {
                    "summary": "Jenis template belum didukung",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "template_not_supported",
                        "message": "Jenis template belum didukung",
                        "doc_url": "/docs/api/error#template_not_supported",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "otp_code_invalid": {
                    "summary": "Kode OTP tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "otp_code_invalid",
                        "message": "Kode OTP tidak sah",
                        "doc_url": "/docs/api/error#otp_code_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited, daily_limit, new_chat_limit",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "daily_limit": {
                    "summary": "Batas pesan harian tercapai",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "daily_limit",
                        "message": "Batas pesan harian tercapai",
                        "doc_url": "/docs/api/error#daily_limit",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "new_chat_limit": {
                    "summary": "Batas chat ke nomor baru tercapai",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "new_chat_limit",
                        "message": "Batas chat ke nomor baru tercapai",
                        "doc_url": "/docs/api/error#new_chat_limit",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "send_failed, channel_refused",
            "content": {
              "application/json": {
                "examples": {
                  "send_failed": {
                    "summary": "Pesan gagal terkirim",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "send_failed",
                        "message": "Pesan gagal terkirim",
                        "doc_url": "/docs/api/error#send_failed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_refused": {
                    "summary": "WhatsApp menolak pesan",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "channel_refused",
                        "message": "WhatsApp menolak pesan",
                        "doc_url": "/docs/api/error#channel_refused",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "messages:send"
      }
    },
    "/api/v2/messages/{id}": {
      "get": {
        "operationId": "v2-messages-get",
        "summary": "Status pesan",
        "description": "Status dan error pesan yang dikirim kunci ini.\n\nHanya pesan yang dikirim kunci yang sama. Isi pesan template Autentikasi tidak pernah ditampilkan.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "`id` dari jawaban Kirim pesan.",
            "schema": {
              "type": "integer"
            },
            "example": 99140
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 99140,
                    "object": "message",
                    "conversation_id": 812,
                    "direction": "out",
                    "type": "text",
                    "body": "[Template] konfirmasi_pesanan: Halo Rina…",
                    "media_url": null,
                    "status": "read",
                    "error": null,
                    "created_at": "2026-11-01T02:12:03.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "messages:send"
      }
    },
    "/api/v2/conversations": {
      "get": {
        "operationId": "v2-conversations-list",
        "summary": "Daftar percakapan",
        "description": "Percakapan dalam cakupan pembuat kunci, terbaru dulu.\n\nHalaman berikutnya dengan `cursor` = `next_cursor` dari jawaban sebelumnya. Nomor dan nama mengikuti masking role pembuat kunci. Kunci yang dibatasi ke nomor tertentu hanya melihat percakapan nomor itu.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Saring status.",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "pending",
                "resolved"
              ]
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "Saring saluran, misalnya `whatsapp_qr` atau `whatsapp_official`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Cari nama atau isi pesan terakhir.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–50, bawaan 25.",
            "schema": {
              "type": "integer"
            },
            "example": 25
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` dari halaman sebelumnya.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": 812,
                      "object": "conversation",
                      "channel": "whatsapp_official",
                      "contact_id": 301,
                      "name": "Rina",
                      "status": "open",
                      "unread_count": 1,
                      "handled_by": null,
                      "last_message_at": "2026-11-01T02:10:00.000Z",
                      "last_customer_at": "2026-11-01T02:10:00.000Z"
                    }
                  ],
                  "next_cursor": "eyJhIjo4MTJ9"
                }
              }
            }
          },
          "400": {
            "description": "cursor_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "cursor_invalid": {
                    "summary": "Cursor tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "cursor_invalid",
                        "message": "Cursor tidak sah",
                        "doc_url": "/docs/api/error#cursor_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "conversations:read"
      }
    },
    "/api/v2/conversations/{id}": {
      "get": {
        "operationId": "v2-conversation-get",
        "summary": "Detail percakapan",
        "description": "Satu percakapan dalam cakupan pembuat kunci.\n\n`last_customer_at` menunjukkan kapan jendela 24 jam WhatsApp Official dimulai.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id percakapan.",
            "schema": {
              "type": "integer"
            },
            "example": 812
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 812,
                    "object": "conversation",
                    "channel": "whatsapp_official",
                    "contact_id": 301,
                    "name": "Rina",
                    "status": "open",
                    "unread_count": 0,
                    "handled_by": 5,
                    "last_message_at": "2026-11-01T02:10:00.000Z",
                    "last_customer_at": "2026-11-01T02:10:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "conversations:read"
      }
    },
    "/api/v2/conversations/{id}/messages": {
      "get": {
        "operationId": "v2-conversation-messages",
        "summary": "Pesan dalam percakapan",
        "description": "Pesan satu percakapan, terbaru dulu.\n\n`next_cursor` membuka pesan yang lebih lama.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id percakapan.",
            "schema": {
              "type": "integer"
            },
            "example": 812
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–100, bawaan 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` dari halaman sebelumnya.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": 99141,
                      "object": "message",
                      "conversation_id": 812,
                      "direction": "in",
                      "type": "text",
                      "body": "Kak, ongkir ke Bandung berapa?",
                      "media_url": null,
                      "status": null,
                      "error": null,
                      "created_at": "2026-11-01T02:10:00.000Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "cursor_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "cursor_invalid": {
                    "summary": "Cursor tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "cursor_invalid",
                        "message": "Cursor tidak sah",
                        "doc_url": "/docs/api/error#cursor_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "conversations:read"
      },
      "post": {
        "operationId": "v2-conversation-reply",
        "summary": "Balas percakapan",
        "description": "Balas teks atau file di percakapan yang bisa dilihat pembuat kunci, di saluran mana pun yang dibalas Inbox.\n\nWhatsApp Official butuh jendela 24 jam; di luarnya kirim template lewat Kirim pesan. Kunci tes hanya membalas percakapan dengan nomor uji. Pakai `Idempotency-Key`.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id percakapan.",
            "schema": {
              "type": "integer"
            },
            "example": 812
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "Bawaan `text`.",
                    "enum": [
                      "text",
                      "image",
                      "video",
                      "audio",
                      "document"
                    ]
                  },
                  "text": {
                    "type": "object",
                    "description": "`{ \"body\": \"…\" }`.",
                    "additionalProperties": true
                  },
                  "media": {
                    "type": "object",
                    "description": "Sama dengan Kirim pesan.",
                    "additionalProperties": true
                  }
                },
                "required": []
              },
              "example": {
                "type": "text",
                "text": {
                  "body": "Ongkir ke Bandung Rp18.000, Kak."
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 99142,
                    "object": "message",
                    "conversation_id": 812,
                    "channel": "whatsapp_official",
                    "to": "6281234567890",
                    "type": "text",
                    "status": "sent",
                    "test": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_json, idempotency_key_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_json": {
                    "summary": "Body bukan JSON yang sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_json",
                        "message": "Body bukan JSON yang sah",
                        "doc_url": "/docs/api/error#invalid_json",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "idempotency_key_invalid": {
                    "summary": "Idempotency-Key tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "idempotency_key_invalid",
                        "message": "Idempotency-Key tidak sah",
                        "doc_url": "/docs/api/error#idempotency_key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, test_number_required, channel_not_allowed, channel_paused",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "test_number_required": {
                    "summary": "Kunci tes hanya ke nomor uji",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "test_number_required",
                        "message": "Kunci tes hanya ke nomor uji",
                        "doc_url": "/docs/api/error#test_number_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_not_allowed": {
                    "summary": "Saluran tidak boleh dipakai kunci ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "channel_not_allowed",
                        "message": "Saluran tidak boleh dipakai kunci ini",
                        "doc_url": "/docs/api/error#channel_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_paused": {
                    "summary": "Saluran sedang dijeda",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "channel_paused",
                        "message": "Saluran sedang dijeda",
                        "doc_url": "/docs/api/error#channel_paused",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "idempotency_conflict, request_in_progress, channel_unavailable, window_closed",
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency-Key dipakai untuk isi lain",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "idempotency_conflict",
                        "message": "Idempotency-Key dipakai untuk isi lain",
                        "doc_url": "/docs/api/error#idempotency_conflict",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "request_in_progress": {
                    "summary": "Permintaan yang sama masih diproses",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "request_in_progress",
                        "message": "Permintaan yang sama masih diproses",
                        "doc_url": "/docs/api/error#request_in_progress",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_unavailable": {
                    "summary": "Tidak ada nomor WhatsApp yang bisa dipakai",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "channel_unavailable",
                        "message": "Tidak ada nomor WhatsApp yang bisa dipakai",
                        "doc_url": "/docs/api/error#channel_unavailable",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "window_closed": {
                    "summary": "Di luar jendela 24 jam",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "window_closed",
                        "message": "Di luar jendela 24 jam",
                        "doc_url": "/docs/api/error#window_closed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "media_too_large",
            "content": {
              "application/json": {
                "examples": {
                  "media_too_large": {
                    "summary": "File terlalu besar",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "media_too_large",
                        "message": "File terlalu besar",
                        "doc_url": "/docs/api/error#media_too_large",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request, invalid_phone, message_too_long, contact_blocked",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "invalid_phone": {
                    "summary": "Nomor tujuan tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_phone",
                        "message": "Nomor tujuan tidak sah",
                        "doc_url": "/docs/api/error#invalid_phone",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "message_too_long": {
                    "summary": "Pesan terlalu panjang",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "message_too_long",
                        "message": "Pesan terlalu panjang",
                        "doc_url": "/docs/api/error#message_too_long",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "contact_blocked": {
                    "summary": "Kontak diblokir atau berhenti berlangganan",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "contact_blocked",
                        "message": "Kontak diblokir atau berhenti berlangganan",
                        "doc_url": "/docs/api/error#contact_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited, daily_limit",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "daily_limit": {
                    "summary": "Batas pesan harian tercapai",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "daily_limit",
                        "message": "Batas pesan harian tercapai",
                        "doc_url": "/docs/api/error#daily_limit",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "send_failed",
            "content": {
              "application/json": {
                "examples": {
                  "send_failed": {
                    "summary": "Pesan gagal terkirim",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "send_failed",
                        "message": "Pesan gagal terkirim",
                        "doc_url": "/docs/api/error#send_failed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "messages:send"
      }
    },
    "/api/v2/contacts": {
      "get": {
        "operationId": "v2-contacts-list",
        "summary": "Cari kontak",
        "description": "Kontak dalam cakupan pembuat kunci, diperbarui terakhir dulu.\n\nNomor disamarkan bila role pembuat kunci menyamarkannya.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Cari nama, nomor, email, perusahaan, atau kota.",
            "schema": {
              "type": "string"
            },
            "example": "rina"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–100, bawaan 25.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` dari halaman sebelumnya.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": 301,
                      "object": "contact",
                      "name": "Rina",
                      "phone": "6281234567890",
                      "email": "rina@contoh.com",
                      "company": null,
                      "city": "Bandung",
                      "source_channel": "whatsapp",
                      "custom_fields": {
                        "member": "Gold"
                      },
                      "created_at": "2026-10-01T03:00:00.000Z",
                      "updated_at": "2026-11-01T02:10:00.000Z"
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "cursor_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "cursor_invalid": {
                    "summary": "Cursor tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "cursor_invalid",
                        "message": "Cursor tidak sah",
                        "doc_url": "/docs/api/error#cursor_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "contacts:read"
      },
      "post": {
        "operationId": "v2-contacts-create",
        "summary": "Buat kontak",
        "description": "Tambah kontak baru dengan nomor atau email.\n\nKontak dengan nomor atau email yang sama ditolak (409) dengan id yang sudah ada. Batas kontak paket berlaku. Field kustom memakai kunci field dari Pengaturan › Kontak.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nama kontak.",
                    "examples": [
                      "Rina"
                    ]
                  },
                  "phone": {
                    "type": "string",
                    "description": "Nomor dengan kode negara. Wajib bila tanpa email.",
                    "examples": [
                      "6281234567890"
                    ]
                  },
                  "email": {
                    "type": "string",
                    "description": "Email. Wajib bila tanpa nomor."
                  },
                  "company": {
                    "type": "string",
                    "description": "Perusahaan."
                  },
                  "city": {
                    "type": "string",
                    "description": "Kota.",
                    "examples": [
                      "Bandung"
                    ]
                  },
                  "custom_fields": {
                    "type": "object",
                    "description": "Nilai field kustom per kunci field.",
                    "examples": [
                      {
                        "member": "Gold"
                      }
                    ],
                    "additionalProperties": true
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Rina",
                "phone": "6281234567890",
                "city": "Bandung",
                "custom_fields": {
                  "member": "Gold"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 301,
                    "object": "contact",
                    "name": "Rina",
                    "phone": "6281234567890",
                    "email": null,
                    "company": null,
                    "city": "Bandung",
                    "source_channel": null,
                    "custom_fields": {
                      "member": "Gold"
                    },
                    "created_at": "2026-11-01T02:12:03.000Z",
                    "updated_at": "2026-11-01T02:12:03.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_json, idempotency_key_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_json": {
                    "summary": "Body bukan JSON yang sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_json",
                        "message": "Body bukan JSON yang sah",
                        "doc_url": "/docs/api/error#invalid_json",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "idempotency_key_invalid": {
                    "summary": "Idempotency-Key tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "idempotency_key_invalid",
                        "message": "Idempotency-Key tidak sah",
                        "doc_url": "/docs/api/error#idempotency_key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "idempotency_conflict, request_in_progress",
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency-Key dipakai untuk isi lain",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "idempotency_conflict",
                        "message": "Idempotency-Key dipakai untuk isi lain",
                        "doc_url": "/docs/api/error#idempotency_conflict",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "request_in_progress": {
                    "summary": "Permintaan yang sama masih diproses",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "request_in_progress",
                        "message": "Permintaan yang sama masih diproses",
                        "doc_url": "/docs/api/error#request_in_progress",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "contacts:write"
      }
    },
    "/api/v2/contacts/{id}": {
      "get": {
        "operationId": "v2-contact-get",
        "summary": "Detail kontak",
        "description": "Satu kontak dalam cakupan pembuat kunci.\n\nNomor mengikuti masking role pembuat kunci.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id kontak.",
            "schema": {
              "type": "integer"
            },
            "example": 301
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 301,
                    "object": "contact",
                    "name": "Rina",
                    "phone": "6281234567890",
                    "email": "rina@contoh.com",
                    "company": null,
                    "city": "Bandung",
                    "source_channel": "whatsapp",
                    "custom_fields": {},
                    "created_at": "2026-10-01T03:00:00.000Z",
                    "updated_at": "2026-11-01T02:10:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "contacts:read"
      },
      "patch": {
        "operationId": "v2-contact-update",
        "summary": "Ubah kontak",
        "description": "Ubah field kontak; hanya field yang dikirim yang berubah.\n\nAturan sama dengan mengubah kontak di aplikasi, termasuk pemeriksaan nomor dan field kustom.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id kontak.",
            "schema": {
              "type": "integer"
            },
            "example": 301
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nama."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Nomor."
                  },
                  "email": {
                    "type": "string",
                    "description": "Email."
                  },
                  "city": {
                    "type": "string",
                    "description": "Kota.",
                    "examples": [
                      "Jakarta"
                    ]
                  },
                  "custom_fields": {
                    "type": "object",
                    "description": "Field kustom yang diubah.",
                    "additionalProperties": true
                  }
                },
                "required": []
              },
              "example": {
                "city": "Jakarta",
                "custom_fields": {
                  "member": "Platinum"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 301,
                    "object": "contact",
                    "name": "Rina",
                    "phone": "6281234567890",
                    "email": "rina@contoh.com",
                    "company": null,
                    "city": "Jakarta",
                    "source_channel": "whatsapp",
                    "custom_fields": {
                      "member": "Platinum"
                    },
                    "created_at": "2026-10-01T03:00:00.000Z",
                    "updated_at": "2026-11-01T02:14:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_json",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_json": {
                    "summary": "Body bukan JSON yang sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_json",
                        "message": "Body bukan JSON yang sah",
                        "doc_url": "/docs/api/error#invalid_json",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "contacts:write"
      }
    },
    "/api/v2/channels": {
      "get": {
        "operationId": "v2-channels",
        "summary": "Daftar saluran",
        "description": "Nomor WhatsApp yang boleh dipakai kunci ini, dengan statusnya.\n\n`from` di jawaban dipakai sebagai `from` di Kirim pesan.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "wa:12",
                      "object": "channel",
                      "channel": "whatsapp_qr",
                      "name": "CS Toko",
                      "connected": true,
                      "from": 12
                    },
                    {
                      "id": "waba:3",
                      "object": "channel",
                      "channel": "whatsapp_official",
                      "name": "Toko Rina Official",
                      "connected": true,
                      "from": 3
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "business:read"
      }
    },
    "/api/v2/templates": {
      "get": {
        "operationId": "v2-templates-list",
        "summary": "Daftar template",
        "description": "Template WhatsApp Official beserta variabel yang harus diisi.\n\n`variables` menyebut field Kirim pesan untuk tiap isian: `variables`, `header_variables`, `media_url`, `button_url`, atau `coupon_code`.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Saring status, misalnya `APPROVED`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": 41,
                      "object": "template",
                      "name": "konfirmasi_pesanan",
                      "language": "id",
                      "category": "UTILITY",
                      "status": "APPROVED",
                      "channel_id": "waba:3",
                      "body": "Halo {{nama}}, pesanan {{orderid}} sudah kami terima.",
                      "sendable": true,
                      "reason": null,
                      "variables": [
                        {
                          "field": "variables",
                          "name": "nama",
                          "example": "Rina"
                        },
                        {
                          "field": "variables",
                          "name": "orderid",
                          "example": "INV-2207"
                        }
                      ]
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "templates:read"
      },
      "post": {
        "operationId": "v2-templates-create",
        "summary": "Ajukan template",
        "description": "Ajukan template WhatsApp Official baru untuk disetujui.\n\n`template` memakai bentuk yang sama dengan pembuat template di aplikasi dan diperiksa dengan aturan yang sama sebelum diajukan.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel_id": {
                    "type": "string",
                    "description": "Akun WhatsApp Official, `waba:<id>` dari Daftar saluran.",
                    "examples": [
                      "waba:3"
                    ]
                  },
                  "template": {
                    "type": "object",
                    "description": "Draf template: `name`, `language`, `category`, `kind`, `parameterFormat`, `body`, `bodyExamples`, dan lainnya.",
                    "additionalProperties": true
                  }
                },
                "required": [
                  "channel_id",
                  "template"
                ]
              },
              "example": {
                "channel_id": "waba:3",
                "template": {
                  "name": "pengingat_bayar",
                  "language": "id",
                  "category": "UTILITY",
                  "kind": "standard",
                  "parameterFormat": "NAMED",
                  "header": {
                    "format": "NONE"
                  },
                  "body": "Halo {{nama}}, tagihan {{orderid}} jatuh tempo besok.",
                  "bodyExamples": {
                    "nama": "Rina",
                    "orderid": "INV-2207"
                  },
                  "footer": "",
                  "buttons": []
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "object": "template",
                    "name": "pengingat_bayar",
                    "language": "id",
                    "status": "PENDING",
                    "category_changed_to": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_json, idempotency_key_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_json": {
                    "summary": "Body bukan JSON yang sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_json",
                        "message": "Body bukan JSON yang sah",
                        "doc_url": "/docs/api/error#invalid_json",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "idempotency_key_invalid": {
                    "summary": "Idempotency-Key tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "idempotency_key_invalid",
                        "message": "Idempotency-Key tidak sah",
                        "doc_url": "/docs/api/error#idempotency_key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, channel_not_allowed",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "channel_not_allowed": {
                    "summary": "Saluran tidak boleh dipakai kunci ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "channel_not_allowed",
                        "message": "Saluran tidak boleh dipakai kunci ini",
                        "doc_url": "/docs/api/error#channel_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "idempotency_conflict, request_in_progress",
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency-Key dipakai untuk isi lain",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "idempotency_conflict",
                        "message": "Idempotency-Key dipakai untuk isi lain",
                        "doc_url": "/docs/api/error#idempotency_conflict",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "request_in_progress": {
                    "summary": "Permintaan yang sama masih diproses",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "request_in_progress",
                        "message": "Permintaan yang sama masih diproses",
                        "doc_url": "/docs/api/error#request_in_progress",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "channel_refused",
            "content": {
              "application/json": {
                "examples": {
                  "channel_refused": {
                    "summary": "WhatsApp menolak pesan",
                    "value": {
                      "error": {
                        "type": "channel_error",
                        "code": "channel_refused",
                        "message": "WhatsApp menolak pesan",
                        "doc_url": "/docs/api/error#channel_refused",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "templates:write"
      }
    },
    "/api/v2/webhooks": {
      "get": {
        "operationId": "v2-webhooks-list",
        "summary": "Daftar webhook",
        "description": "Webhook bisnis ini, dengan event, kesehatan 7 hari, dan jumlah kiriman gagal.\n\nSama dengan Pengaturan › API & Webhook › Webhook. Hanya kunci live: webhook menerima event sungguhan. Secret tidak pernah ada di jawaban ini.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": 6,
                      "object": "webhook",
                      "url": "https://toko-anda.id/klikflow/webhook",
                      "description": "Server toko",
                      "events": [
                        "message.received",
                        "message.status",
                        "order.paid"
                      ],
                      "status": "active",
                      "paused_reason": null,
                      "health": "Sehat · 99,8% sukses 7 hari",
                      "failed_count": 0,
                      "created_at": "2026-11-01T02:00:00.000Z",
                      "last_success_at": "2026-11-01T02:12:04.000Z",
                      "last_failure_at": null
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, live_key_required",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "live_key_required": {
                    "summary": "Butuh kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "live_key_required",
                        "message": "Butuh kunci live",
                        "doc_url": "/docs/api/error#live_key_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "webhooks:manage"
      },
      "post": {
        "operationId": "v2-webhooks-create",
        "summary": "Tambah webhook",
        "description": "Daftarkan URL HTTPS sistem Anda dan event yang ingin diterima.\n\nMaksimal 5 webhook per bisnis. Jawaban memuat `secret` sekali saja (bisa dilihat lagi di Pengaturan › API & Webhook). Pakai secret itu untuk memeriksa header `Klikflow-Signature`.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "URL HTTPS publik, maksimal 500 karakter.",
                    "examples": [
                      "https://toko-anda.id/klikflow/webhook"
                    ]
                  },
                  "events": {
                    "type": "array",
                    "description": "Event yang dikirim, lihat panduan Event webhook.",
                    "enum": [
                      "message.received",
                      "message.status",
                      "contact.created",
                      "lead.created",
                      "order.paid",
                      "ticket.created",
                      "ticket.status",
                      "template.status",
                      "channel.status"
                    ],
                    "examples": [
                      [
                        "message.received",
                        "message.status",
                        "order.paid"
                      ]
                    ],
                    "items": {}
                  },
                  "description": {
                    "type": "string",
                    "description": "Keterangan, maksimal 120 karakter.",
                    "examples": [
                      "Server toko"
                    ]
                  }
                },
                "required": [
                  "url",
                  "events"
                ]
              },
              "example": {
                "url": "https://toko-anda.id/klikflow/webhook",
                "events": [
                  "message.received",
                  "message.status",
                  "order.paid"
                ],
                "description": "Server toko"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 6,
                    "object": "webhook",
                    "url": "https://toko-anda.id/klikflow/webhook",
                    "description": "Server toko",
                    "events": [
                      "message.received",
                      "message.status",
                      "order.paid"
                    ],
                    "status": "active",
                    "paused_reason": null,
                    "health": "Belum ada kiriman 7 hari",
                    "failed_count": 0,
                    "created_at": "2026-11-01T02:00:00.000Z",
                    "last_success_at": null,
                    "last_failure_at": null,
                    "secret": "whsec_4Hf2Kp9Lq7Rt1Zs8Vb3Nm6Xc0Ya5Wd2E"
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_json, idempotency_key_invalid",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_json": {
                    "summary": "Body bukan JSON yang sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_json",
                        "message": "Body bukan JSON yang sah",
                        "doc_url": "/docs/api/error#invalid_json",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "idempotency_key_invalid": {
                    "summary": "Idempotency-Key tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "idempotency_key_invalid",
                        "message": "Idempotency-Key tidak sah",
                        "doc_url": "/docs/api/error#idempotency_key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, live_key_required",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "live_key_required": {
                    "summary": "Butuh kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "live_key_required",
                        "message": "Butuh kunci live",
                        "doc_url": "/docs/api/error#live_key_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "idempotency_conflict, request_in_progress",
            "content": {
              "application/json": {
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency-Key dipakai untuk isi lain",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "idempotency_conflict",
                        "message": "Idempotency-Key dipakai untuk isi lain",
                        "doc_url": "/docs/api/error#idempotency_conflict",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "request_in_progress": {
                    "summary": "Permintaan yang sama masih diproses",
                    "value": {
                      "error": {
                        "type": "conflict_error",
                        "code": "request_in_progress",
                        "message": "Permintaan yang sama masih diproses",
                        "doc_url": "/docs/api/error#request_in_progress",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request, webhook_limit",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "webhook_limit": {
                    "summary": "Batas jumlah webhook tercapai",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "webhook_limit",
                        "message": "Batas jumlah webhook tercapai",
                        "doc_url": "/docs/api/error#webhook_limit",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "webhooks:manage"
      }
    },
    "/api/v2/webhooks/{id}": {
      "get": {
        "operationId": "v2-webhook-get",
        "summary": "Detail webhook",
        "description": "Satu webhook dengan event dan kesehatannya.\n\nHanya kunci live.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id webhook.",
            "schema": {
              "type": "integer"
            },
            "example": 6
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 6,
                    "object": "webhook",
                    "url": "https://toko-anda.id/klikflow/webhook",
                    "description": "Server toko",
                    "events": [
                      "message.received",
                      "message.status",
                      "order.paid"
                    ],
                    "status": "active",
                    "paused_reason": null,
                    "health": "Sehat · 99,8% sukses 7 hari",
                    "failed_count": 0,
                    "created_at": "2026-11-01T02:00:00.000Z",
                    "last_success_at": "2026-11-01T02:12:04.000Z",
                    "last_failure_at": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, live_key_required",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "live_key_required": {
                    "summary": "Butuh kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "live_key_required",
                        "message": "Butuh kunci live",
                        "doc_url": "/docs/api/error#live_key_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "webhooks:manage"
      },
      "patch": {
        "operationId": "v2-webhook-update",
        "summary": "Ubah webhook",
        "description": "Ubah URL, event, keterangan, atau jeda dan aktifkan lagi.\n\nHanya field yang dikirim yang berubah. `status: active` setelah dijeda mengirim lagi kiriman yang menunggu, mulai sekarang.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id webhook.",
            "schema": {
              "type": "integer"
            },
            "example": 6
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "URL HTTPS publik baru."
                  },
                  "events": {
                    "type": "array",
                    "description": "Daftar event pengganti.",
                    "enum": [
                      "message.received",
                      "message.status",
                      "contact.created",
                      "lead.created",
                      "order.paid",
                      "ticket.created",
                      "ticket.status",
                      "template.status",
                      "channel.status"
                    ],
                    "items": {}
                  },
                  "description": {
                    "type": "string",
                    "description": "Keterangan."
                  },
                  "status": {
                    "type": "string",
                    "description": "Jeda atau aktifkan.",
                    "enum": [
                      "active",
                      "paused"
                    ],
                    "examples": [
                      "paused"
                    ]
                  }
                },
                "required": []
              },
              "example": {
                "status": "paused"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 6,
                    "object": "webhook",
                    "url": "https://toko-anda.id/klikflow/webhook",
                    "description": "Server toko",
                    "events": [
                      "message.received",
                      "message.status",
                      "order.paid"
                    ],
                    "status": "paused",
                    "paused_reason": "Dijeda oleh tim.",
                    "health": "Dijeda",
                    "failed_count": 0,
                    "created_at": "2026-11-01T02:00:00.000Z",
                    "last_success_at": "2026-11-01T02:12:04.000Z",
                    "last_failure_at": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_json",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_json": {
                    "summary": "Body bukan JSON yang sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_json",
                        "message": "Body bukan JSON yang sah",
                        "doc_url": "/docs/api/error#invalid_json",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, live_key_required",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "live_key_required": {
                    "summary": "Butuh kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "live_key_required",
                        "message": "Butuh kunci live",
                        "doc_url": "/docs/api/error#live_key_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "webhooks:manage"
      },
      "delete": {
        "operationId": "v2-webhook-delete",
        "summary": "Hapus webhook",
        "description": "Hapus webhook beserta log kirimannya.\n\nEvent berikutnya tidak dikirim lagi ke URL ini. Tidak bisa dibatalkan.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id webhook.",
            "schema": {
              "type": "integer"
            },
            "example": 6
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 6,
                    "object": "webhook",
                    "deleted": true
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, live_key_required",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "live_key_required": {
                    "summary": "Butuh kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "live_key_required",
                        "message": "Butuh kunci live",
                        "doc_url": "/docs/api/error#live_key_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "webhooks:manage"
      }
    },
    "/api/v2/webhooks/{id}/test": {
      "post": {
        "operationId": "v2-webhook-test",
        "summary": "Kirim event uji",
        "description": "Kirim contoh satu event (ditandai `test: true`) sekarang, lalu lihat jawaban sistem Anda.\n\nContohnya sama dengan di panduan Event webhook. Event uji tidak diulang bila gagal dan tidak dihitung dalam kesehatan webhook.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Id webhook.",
            "schema": {
              "type": "integer"
            },
            "example": 6
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Kunci unik per permintaan (misalnya UUID), disimpan 24 jam: kirim ulang dengan kunci yang sama tidak mengirim dua kali.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "description": "Event yang dicontohkan, bawaan `message.received`.",
                    "enum": [
                      "message.received",
                      "message.status",
                      "contact.created",
                      "lead.created",
                      "order.paid",
                      "ticket.created",
                      "ticket.status",
                      "template.status",
                      "channel.status"
                    ],
                    "examples": [
                      "order.paid"
                    ]
                  }
                },
                "required": []
              },
              "example": {
                "event": "order.paid"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "object": "webhook_delivery",
                    "event_id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                    "event": "order.paid",
                    "test": true,
                    "succeeded": true,
                    "status_code": 200,
                    "error": null,
                    "duration_ms": 182
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, scope_missing, permission_missing, live_key_required",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "scope_missing": {
                    "summary": "Kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "scope_missing",
                        "message": "Kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#scope_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "permission_missing": {
                    "summary": "Role pembuat kunci tidak punya izin ini",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "permission_missing",
                        "message": "Role pembuat kunci tidak punya izin ini",
                        "doc_url": "/docs/api/error#permission_missing",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "live_key_required": {
                    "summary": "Butuh kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "live_key_required",
                        "message": "Butuh kunci live",
                        "doc_url": "/docs/api/error#live_key_required",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "not_found",
            "content": {
              "application/json": {
                "examples": {
                  "not_found": {
                    "summary": "Tidak ditemukan",
                    "value": {
                      "error": {
                        "type": "not_found_error",
                        "code": "not_found",
                        "message": "Tidak ditemukan",
                        "doc_url": "/docs/api/error#not_found",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "invalid_request",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_request": {
                    "summary": "Field tidak sah",
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_request",
                        "message": "Field tidak sah",
                        "doc_url": "/docs/api/error#invalid_request",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": [
          "API kirim WhatsApp"
        ],
        "x-klikflow-scope": "webhooks:manage"
      }
    },
    "/api/v2/me": {
      "get": {
        "operationId": "v2-me",
        "summary": "Kunci saya",
        "description": "Jenis kunci, izin yang bisa dipakai sekarang, dan saluran yang boleh dipakai.\n\nPanggil ini lebih dulu untuk memastikan kunci benar. `usable: false` berarti role pembuat kunci tidak lagi punya izin itu.",
        "tags": [
          "API v2"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Berhasil",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "object": "api_key",
                    "name": "Toko online",
                    "prefix": "kf_test_Ab3dEf",
                    "mode": "test",
                    "business_id": 7,
                    "scopes": [
                      {
                        "scope": "messages:send",
                        "usable": true
                      }
                    ],
                    "channels": [
                      {
                        "id": "waba:3",
                        "channel": "whatsapp_official",
                        "name": "Toko Rina Official",
                        "connected": true
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_key, key_invalid, key_revoked, key_expired, member_inactive",
            "content": {
              "application/json": {
                "examples": {
                  "missing_key": {
                    "summary": "Kunci API belum dikirim",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "missing_key",
                        "message": "Kunci API belum dikirim",
                        "doc_url": "/docs/api/error#missing_key",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_invalid": {
                    "summary": "Kunci API tidak dikenal",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_invalid",
                        "message": "Kunci API tidak dikenal",
                        "doc_url": "/docs/api/error#key_invalid",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_revoked": {
                    "summary": "Kunci API sudah dicabut",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_revoked",
                        "message": "Kunci API sudah dicabut",
                        "doc_url": "/docs/api/error#key_revoked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "key_expired": {
                    "summary": "Kunci API kedaluwarsa",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "key_expired",
                        "message": "Kunci API kedaluwarsa",
                        "doc_url": "/docs/api/error#key_expired",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "member_inactive": {
                    "summary": "Pembuat kunci bukan anggota lagi",
                    "value": {
                      "error": {
                        "type": "authentication_error",
                        "code": "member_inactive",
                        "message": "Pembuat kunci bukan anggota lagi",
                        "doc_url": "/docs/api/error#member_inactive",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "ip_not_allowed, plan_no_api, tenant_blocked, console_test_only",
            "content": {
              "application/json": {
                "examples": {
                  "ip_not_allowed": {
                    "summary": "IP server tidak ada di daftar kunci",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "ip_not_allowed",
                        "message": "IP server tidak ada di daftar kunci",
                        "doc_url": "/docs/api/error#ip_not_allowed",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "plan_no_api": {
                    "summary": "Paket belum memuat API untuk kunci live",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "plan_no_api",
                        "message": "Paket belum memuat API untuk kunci live",
                        "doc_url": "/docs/api/error#plan_no_api",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "tenant_blocked": {
                    "summary": "Akses bisnis ditangguhkan",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "tenant_blocked",
                        "message": "Akses bisnis ditangguhkan",
                        "doc_url": "/docs/api/error#tenant_blocked",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  },
                  "console_test_only": {
                    "summary": "Konsol Coba hanya untuk kunci tes",
                    "value": {
                      "error": {
                        "type": "permission_error",
                        "code": "console_test_only",
                        "message": "Konsol Coba hanya untuk kunci tes",
                        "doc_url": "/docs/api/error#console_test_only",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "rate_limited",
            "content": {
              "application/json": {
                "examples": {
                  "rate_limited": {
                    "summary": "Terlalu banyak permintaan per menit",
                    "value": {
                      "error": {
                        "type": "rate_limit_error",
                        "code": "rate_limited",
                        "message": "Terlalu banyak permintaan per menit",
                        "doc_url": "/docs/api/error#rate_limited",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "internal_error",
            "content": {
              "application/json": {
                "examples": {
                  "internal_error": {
                    "summary": "Gangguan di Klik Flow",
                    "value": {
                      "error": {
                        "type": "api_error",
                        "code": "internal_error",
                        "message": "Gangguan di Klik Flow",
                        "doc_url": "/docs/api/error#internal_error",
                        "request_id": "req_8Kx2Qm"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-klikflow-plan": []
      }
    }
  },
  "webhooks": {
    "message.received": {
      "post": {
        "operationId": "webhook-message-received",
        "summary": "Pesan masuk",
        "description": "Pelanggan mengirim pesan di WhatsApp, live chat, Instagram, Messenger, atau Telegram.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "message.received"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.received"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "message.received",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "message_id": 99141,
                  "conversation_id": 812,
                  "contact_id": 301,
                  "channel": "whatsapp_official",
                  "from": "6281234567890",
                  "name": "Rina",
                  "type": "text",
                  "text": "Kak, pesanan INV-2207 sudah dikirim?",
                  "has_media": false,
                  "received_at": "2026-11-01T09:12:03+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "message.status": {
      "post": {
        "operationId": "webhook-message-status",
        "summary": "Status pesan",
        "description": "Pesan keluar terkirim, sampai, dibaca, atau gagal.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "message.status"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.status"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "message.status",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "message_id": 99140,
                  "conversation_id": 812,
                  "channel": "whatsapp_official",
                  "to": "6281234567890",
                  "status": "read",
                  "error": null,
                  "at": "2026-11-01T09:13:10+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "contact.created": {
      "post": {
        "operationId": "webhook-contact-created",
        "summary": "Kontak baru",
        "description": "Kontak baru tersimpan: dari chat pertama, formulir, pembeli toko, tambah manual, atau API. Impor massal tidak dikirim.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "contact.created"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "contact.created"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "contact.created",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "contact_id": 301,
                  "name": "Rina",
                  "phone": "6281234567890",
                  "email": "rina@contoh.com",
                  "source_channel": "whatsapp",
                  "created_at": "2026-11-01T09:12:03+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "lead.created": {
      "post": {
        "operationId": "webhook-lead-created",
        "summary": "Lead baru",
        "description": "Formulir landing page atau Bio Link dikirim, atau chat WhatsApp cocok dengan klik Smart Link. Smart Link menambah match, confidence, attribution_id, dan conversation_id.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "lead.created"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "lead.created"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "lead.created",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "source": "landing_page",
                  "source_id": 14,
                  "source_name": "Promo Ramadan",
                  "submission_id": 902,
                  "contact_id": 301,
                  "name": "Rina",
                  "phone": "6281234567890",
                  "email": "rina@contoh.com",
                  "message": "Mau tanya paket reseller",
                  "fields": [
                    {
                      "label": "Kota",
                      "value": "Bandung"
                    }
                  ],
                  "created_at": "2026-11-01T09:12:03+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "order.paid": {
      "post": {
        "operationId": "webhook-order-paid",
        "summary": "Pesanan dibayar",
        "description": "Pembayaran pesanan toko diterima (QRIS atau ditandai lunas).\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "order.paid"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "order.paid"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "order.paid",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "order_id": 5521,
                  "number": "INV-2207",
                  "total": 185000,
                  "currency": "IDR",
                  "payment_method": "qris",
                  "customer": {
                    "name": "Rina",
                    "phone": "6281234567890",
                    "email": "rina@contoh.com"
                  },
                  "contact_id": 301,
                  "items": 2,
                  "paid_at": "2026-11-01T09:20:00+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "ticket.created": {
      "post": {
        "operationId": "webhook-ticket-created",
        "summary": "Tiket baru",
        "description": "Tiket dibuat dari chat, formulir, atau oleh staf.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "ticket.created"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "ticket.created"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "ticket.created",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "ticket_id": 77,
                  "number": "#1077",
                  "subject": "Paket belum sampai",
                  "status": "open",
                  "priority": "high",
                  "source": "chat",
                  "contact_id": 301,
                  "conversation_id": 812,
                  "assignee_id": 5,
                  "created_at": "2026-11-01T09:15:00+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "ticket.status": {
      "post": {
        "operationId": "webhook-ticket-status",
        "summary": "Status tiket",
        "description": "Status tiket berubah, misalnya selesai.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "ticket.status"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "ticket.status"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "ticket.status",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "ticket_id": 77,
                  "number": "#1077",
                  "status": "resolved",
                  "previous_status": "open",
                  "at": "2026-11-01T11:40:00+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "template.status": {
      "post": {
        "operationId": "webhook-template-status",
        "summary": "Status template",
        "description": "Template WhatsApp Official disetujui, ditolak, atau dijeda.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "template.status"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "template.status"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "template.status",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "template_id": 41,
                  "channel_id": "waba:3",
                  "name": "konfirmasi_pesanan",
                  "language": "id",
                  "category": "UTILITY",
                  "status": "APPROVED",
                  "reason": null,
                  "at": "2026-11-01T10:02:00+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    },
    "channel.status": {
      "post": {
        "operationId": "webhook-channel-status",
        "summary": "Status saluran",
        "description": "Nomor WhatsApp tersambung atau terputus.\n\nDitandatangani dengan header Klikflow-Signature: t=<detik>,v1=<HMAC-SHA256 dari \"<t>.<body>\">. Jawab 2xx dalam 8 detik; bila tidak, dikirim ulang hingga 7 kali.",
        "tags": [
          "Webhook v2"
        ],
        "parameters": [
          {
            "name": "Klikflow-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "channel.status"
            }
          },
          {
            "name": "Klikflow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Klikflow-Delivery-Attempt",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 7
            }
          },
          {
            "name": "Klikflow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "type",
                  "created",
                  "business_id",
                  "data"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "const": "channel.status"
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "business_id": {
                    "type": "integer"
                  },
                  "test": {
                    "type": "boolean"
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "id": "evt_9Qx2Lm4Kp7Rt1Zs8",
                "type": "channel.status",
                "created": "2026-11-01T09:13:10+07:00",
                "business_id": 7,
                "data": {
                  "channel_id": "wa:12",
                  "channel": "whatsapp_qr",
                  "name": "CS Toko",
                  "connected": false,
                  "reason": "Perangkat logout dari WhatsApp.",
                  "at": "2026-11-01T08:55:00+07:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Diterima (setiap 2xx dihitung berhasil)."
          }
        }
      }
    }
  }
}