{
  "openapi": "3.0.3",
  "info": {
    "title": "KokilCloud Public API",
    "version": "1.0.0",
    "description": "Customer API-key endpoints for OTP calls and call status. POST requests create real calls."
  },
  "servers": [
    {
      "url": "https://api.kokilcloud.com/v1"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Voice Calls"
    }
  ],
  "paths": {
    "/otp-call": {
      "post": {
        "operationId": "sendOtpCall",
        "tags": [
          "Voice Calls"
        ],
        "summary": "Queue a voice OTP call",
        "parameters": [
          {
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Unique verification ID. Keep the same key and body for retries."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtpCallRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Call accepted, or an existing idempotent request returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedCall"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input, insufficient balance, or calling limit"
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Account, package, or sender not allowed"
          },
          "409": {
            "description": "Conflicting idempotency key"
          },
          "500": {
            "description": "Server error"
          }
        }
      }
    },
    "/calls/{callId}": {
      "get": {
        "operationId": "getCallStatus",
        "tags": [
          "Voice Calls"
        ],
        "summary": "Retrieve a call belonging to your account",
        "parameters": [
          {
            "in": "path",
            "name": "callId",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current call status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallStatus"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "403": {
            "description": "Account, package, or sender not allowed"
          },
          "404": {
            "description": "Call not found"
          },
          "500": {
            "description": "Server error"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    },
    "schemas": {
      "OtpCallRequest": {
        "type": "object",
        "required": [
          "phone",
          "otp"
        ],
        "additionalProperties": false,
        "properties": {
          "phone": {
            "type": "string",
            "maxLength": 32,
            "example": "01712345678",
            "description": "Valid Bangladesh mobile number."
          },
          "otp": {
            "type": "string",
            "pattern": "^[0-9]{4,8}$",
            "example": "482913"
          },
          "repeatCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "default": 2
          },
          "voiceId": {
            "type": "string",
            "description": "Optional. Copy the Bangla or English OTP voice ID from Dashboard \u2192 Voices, or use your own approved recording. When omitted, the system default OTP voice is used (initially Bangla)."
          },
          "senderId": {
            "type": "string",
            "description": "An active owned or shared sender available to the account."
          }
        }
      },
      "QueuedCall": {
        "type": "object",
        "properties": {
          "callId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "dispatching",
              "active",
              "completed",
              "failed",
              "canceled"
            ]
          },
          "queuePosition": {
            "type": "integer"
          }
        }
      },
      "CallStatus": {
        "type": "object",
        "properties": {
          "callId": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "dispatching",
              "active",
              "completed",
              "failed",
              "canceled"
            ]
          },
          "outcome": {
            "type": "string",
            "nullable": true
          },
          "answeredAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "endedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "talkDurationSec": {
            "type": "integer",
            "nullable": true
          },
          "costPoisha": {
            "type": "integer",
            "description": "Charge in poisha (100 poisha = 1 BDT)."
          }
        }
      }
    }
  }
}
