{
  "openapi": "3.1.0",
  "info": {
    "title": "MilliySavdo API",
    "summary": "Virtual raqamlar va SMS aktivatsiya API",
    "description": "Hujjatlar: https://api.milliysavdo.uz/docs · Barcha so'rovlar HTTPS orqali, `Authorization: Bearer <API kalit>` bilan. Test kalitlari (`ms_test_`) — sandbox, live kalitlar (`ms_live_`) — haqiqiy buyurtmalar.",
    "version": "2026-10-16"
  },
  "servers": [
    {
      "url": "http://localhost:3100/v1",
      "description": "Production"
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "tags": [
          "Akkaunt"
        ],
        "summary": "Kalit va limitlar haqida",
        "description": "Kalit qaysi rejimda (test/live), qaysi ruxsatlar bilan ishlayotgani va amaldagi limitlar.",
        "operationId": "me_me_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-scope": "catalog:read"
      }
    },
    "/balance": {
      "get": {
        "tags": [
          "Akkaunt"
        ],
        "summary": "Balans",
        "description": "Live: MilliySavdo hisobingiz balansi (sayt bilan umumiy). Test: virtual balans, kamaymaydi.",
        "operationId": "balance_balance_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-scope": "balance:read"
      }
    },
    "/countries": {
      "get": {
        "tags": [
          "Katalog"
        ],
        "summary": "Davlatlar",
        "description": "Hozir raqam olish mumkin bo'lgan davlatlar (mashhurlari birinchi).",
        "operationId": "countries_countries_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_Country_"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-scope": "catalog:read"
      }
    },
    "/services": {
      "get": {
        "tags": [
          "Katalog"
        ],
        "summary": "Davlatdagi xizmatlar va narxlar",
        "description": "Narx — sizning chegirmangiz qo'llangan holda. `next_cursor` — keyingi `offset`.",
        "operationId": "services_services_get",
        "parameters": [
          {
            "name": "country_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "`/v1/countries` dagi id",
              "title": "Country Id"
            },
            "description": "`/v1/countries` dagi id"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 64
                },
                {
                  "type": "null"
                }
              ],
              "description": "Nomi yoki kodi bo'yicha qidiruv",
              "title": "Q"
            },
            "description": "Nomi yoki kodi bo'yicha qidiruv"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 32
                },
                {
                  "type": "null"
                }
              ],
              "examples": [
                "messenger"
              ],
              "title": "Category"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100000,
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_Service_"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-scope": "catalog:read"
      }
    },
    "/prices": {
      "get": {
        "tags": [
          "Katalog"
        ],
        "summary": "Xizmat narxi barcha davlatlarda",
        "description": "Eng arzonidan boshlab saralangan.",
        "operationId": "prices_prices_get",
        "parameters": [
          {
            "name": "service_code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[A-Za-z0-9_.-]+$",
              "title": "Service Code"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_ServicePrice_"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-scope": "catalog:read"
      }
    },
    "/orders": {
      "post": {
        "tags": [
          "Buyurtmalar"
        ],
        "summary": "Raqam olish (buyurtma yaratish)",
        "description": "Live kalit: balansdan yechiladi, SMS 20 daqiqada kelmasa pul avtomatik qaytadi. Test kalit: simulyatsiya, pul yechilmaydi.\n\n**Idempotency-Key** yuboring: tarmoq uzilib qayta yuborsangiz ikkinchi raqam olinmaydi — o'sha buyurtma `200` va `Idempotent-Replayed: true` bilan qaytadi.",
        "operationId": "create_order_orders_post",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 80
                },
                {
                  "type": "null"
                }
              ],
              "title": "Idempotency-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "200": {
            "description": "Idempotent takror — avvalgi buyurtma",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "402": {
            "description": "Balans yetarli emas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Xizmat/davlat topilmadi",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Raqamlar tugagan / xizmat vaqtincha yopiq / parallel so'rov",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validatsiya xatosi yoki Idempotency-Key qayta ishlatilgan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-scope": "orders:write"
      },
      "get": {
        "tags": [
          "Buyurtmalar"
        ],
        "summary": "Buyurtmalar ro'yxati",
        "description": "Faqat API orqali olingan buyurtmalar, yangilari birinchi.",
        "operationId": "list_orders_orders_get",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "waiting_sms | sms_received | cancelled | expired | failed",
              "title": "Status"
            },
            "description": "waiting_sms | sms_received | cancelled | expired | failed"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 40
                },
                {
                  "type": "null"
                }
              ],
              "description": "Oldingi sahifadagi `next_cursor`",
              "title": "Starting After"
            },
            "description": "Oldingi sahifadagi `next_cursor`"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_Order_"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-scope": "orders:read"
      }
    },
    "/orders/{order_id}": {
      "get": {
        "tags": [
          "Buyurtmalar"
        ],
        "summary": "Buyurtma holati va SMS kod",
        "description": "SMS kodni olish uchun shu endpointni 3–5 soniyada bir so'rang yoki webhook'dan foydalaning (`order.sms_received`). Har so'rov provayder holatini ham yangilaydi.",
        "operationId": "get_order_orders__order_id__get",
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 40,
              "description": "`ord_<n>` (live) yoki `ord_test_<n>` (test)",
              "examples": [
                "ord_10452"
              ],
              "title": "Order Id"
            },
            "description": "`ord_<n>` (live) yoki `ord_test_<n>` (test)"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-scope": "orders:read"
      }
    },
    "/orders/{order_id}/cancel": {
      "post": {
        "tags": [
          "Buyurtmalar"
        ],
        "summary": "Bekor qilish (pul qaytadi)",
        "description": "Faqat `waiting_sms` holatida. SMS kelgan bo'lsa 409.",
        "operationId": "cancel_order_orders__order_id__cancel_post",
        "parameters": [
          {
            "name": "order_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 40,
              "description": "`ord_<n>` (live) yoki `ord_test_<n>` (test)",
              "examples": [
                "ord_10452"
              ],
              "title": "Order Id"
            },
            "description": "`ord_<n>` (live) yoki `ord_test_<n>` (test)"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "401": {
            "description": "Kalit yo'q, yaroqsiz, muddati tugagan yoki bekor qilingan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Scope yetarli emas, akkaunt to'xtatilgan yoki IP ruxsat etilmagan",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate-limit yoki kvota oshdi (`Retry-After` headeriga qarang)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Not Found"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Conflict"
          },
          "503": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "description": "Service Unavailable"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-scope": "orders:write"
      }
    }
  },
  "components": {
    "schemas": {
      "Balance": {
        "properties": {
          "object": {
            "type": "string",
            "const": "balance",
            "title": "Object",
            "default": "balance"
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "title": "Mode"
          },
          "amount": {
            "type": "string",
            "title": "Amount",
            "examples": [
              "125000.00"
            ]
          },
          "amount_cents": {
            "type": "integer",
            "title": "Amount Cents",
            "examples": [
              12500000
            ]
          },
          "currency": {
            "type": "string",
            "const": "UZS",
            "title": "Currency",
            "default": "UZS"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Note",
            "description": "Test rejimida balans virtual"
          }
        },
        "type": "object",
        "required": [
          "mode",
          "amount",
          "amount_cents"
        ],
        "title": "Balance"
      },
      "Country": {
        "properties": {
          "id": {
            "type": "integer",
            "title": "Id",
            "examples": [
              187
            ]
          },
          "name": {
            "type": "string",
            "title": "Name",
            "examples": [
              "United States"
            ]
          },
          "iso_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Iso Code",
            "examples": [
              "US"
            ]
          },
          "phone_code": {
            "type": "string",
            "title": "Phone Code",
            "examples": [
              "1"
            ]
          },
          "flag": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Flag",
            "examples": [
              "🇺🇸"
            ]
          },
          "popular": {
            "type": "boolean",
            "title": "Popular",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "phone_code"
        ],
        "title": "Country"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "KeyInfo": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "prefix": {
            "type": "string",
            "title": "Prefix",
            "description": "Kalitning maskalangan ko'rinishi",
            "examples": [
              "ms_live_a1B2c3…9xYz"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "title": "Mode"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Scopes"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          }
        },
        "type": "object",
        "required": [
          "name",
          "prefix",
          "mode",
          "scopes"
        ],
        "title": "KeyInfo"
      },
      "Limits": {
        "properties": {
          "rate_limit_per_minute": {
            "type": "integer",
            "title": "Rate Limit Per Minute"
          },
          "daily_request_quota": {
            "type": "integer",
            "title": "Daily Request Quota"
          },
          "monthly_request_quota": {
            "type": "integer",
            "title": "Monthly Request Quota"
          },
          "daily_order_limit": {
            "type": "integer",
            "title": "Daily Order Limit"
          },
          "max_active_orders": {
            "type": "integer",
            "title": "Max Active Orders"
          },
          "discount_percent": {
            "type": "string",
            "title": "Discount Percent"
          }
        },
        "type": "object",
        "required": [
          "rate_limit_per_minute",
          "daily_request_quota",
          "monthly_request_quota",
          "daily_order_limit",
          "max_active_orders",
          "discount_percent"
        ],
        "title": "Limits"
      },
      "ListResponse_Country_": {
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "title": "Object",
            "default": "list"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/Country"
            },
            "type": "array",
            "title": "Data"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "Yana sahifa bormi"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor",
            "description": "Keyingi sahifa uchun `starting_after` qiymati"
          }
        },
        "type": "object",
        "required": [
          "data",
          "has_more"
        ],
        "title": "ListResponse[Country]"
      },
      "ListResponse_Order_": {
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "title": "Object",
            "default": "list"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/Order"
            },
            "type": "array",
            "title": "Data"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "Yana sahifa bormi"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor",
            "description": "Keyingi sahifa uchun `starting_after` qiymati"
          }
        },
        "type": "object",
        "required": [
          "data",
          "has_more"
        ],
        "title": "ListResponse[Order]"
      },
      "ListResponse_ServicePrice_": {
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "title": "Object",
            "default": "list"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/ServicePrice"
            },
            "type": "array",
            "title": "Data"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "Yana sahifa bormi"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor",
            "description": "Keyingi sahifa uchun `starting_after` qiymati"
          }
        },
        "type": "object",
        "required": [
          "data",
          "has_more"
        ],
        "title": "ListResponse[ServicePrice]"
      },
      "ListResponse_Service_": {
        "properties": {
          "object": {
            "type": "string",
            "const": "list",
            "title": "Object",
            "default": "list"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/Service"
            },
            "type": "array",
            "title": "Data"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "Yana sahifa bormi"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor",
            "description": "Keyingi sahifa uchun `starting_after` qiymati"
          }
        },
        "type": "object",
        "required": [
          "data",
          "has_more"
        ],
        "title": "ListResponse[Service]"
      },
      "Me": {
        "properties": {
          "object": {
            "type": "string",
            "const": "api_key_info",
            "title": "Object",
            "default": "api_key_info"
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "title": "Mode"
          },
          "key": {
            "$ref": "#/components/schemas/KeyInfo"
          },
          "account": {
            "additionalProperties": true,
            "type": "object",
            "title": "Account",
            "description": "`tier` (demo|production) va kompaniya nomi"
          },
          "limits": {
            "$ref": "#/components/schemas/Limits"
          }
        },
        "type": "object",
        "required": [
          "mode",
          "key",
          "account",
          "limits"
        ],
        "title": "Me"
      },
      "Order": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "`ord_<n>` (live) yoki `ord_test_<n>` (test)",
            "examples": [
              "ord_10452"
            ]
          },
          "object": {
            "type": "string",
            "const": "order",
            "title": "Object",
            "default": "order"
          },
          "mode": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "title": "Mode"
          },
          "status": {
            "type": "string",
            "enum": [
              "waiting_sms",
              "sms_received",
              "cancelled",
              "expired",
              "failed"
            ],
            "title": "Status",
            "description": "`waiting_sms` → `sms_received` | `cancelled` | `expired` | `failed`. Yakuniy holatlarda pul qaytarilgan (sms_received bundan mustasno)."
          },
          "phone": {
            "type": "string",
            "title": "Phone",
            "examples": [
              "+12025550143"
            ]
          },
          "sms_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sms Code",
            "examples": [
              "482913"
            ]
          },
          "country": {
            "$ref": "#/components/schemas/OrderCountry"
          },
          "service": {
            "$ref": "#/components/schemas/OrderService"
          },
          "price": {
            "$ref": "#/components/schemas/Price"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "title": "Expires At",
            "description": "Shu vaqtgacha SMS kelmasa buyurtma `expired` bo'ladi va pul qaytadi"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "mode",
          "status",
          "phone",
          "country",
          "service",
          "price",
          "created_at",
          "expires_at"
        ],
        "title": "Order"
      },
      "OrderCountry": {
        "properties": {
          "id": {
            "type": "integer",
            "title": "Id",
            "examples": [
              187
            ]
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "examples": [
              "United States"
            ]
          },
          "iso_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Iso Code",
            "examples": [
              "US"
            ]
          }
        },
        "type": "object",
        "required": [
          "id"
        ],
        "title": "OrderCountry"
      },
      "OrderCreate": {
        "properties": {
          "country_id": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Country Id",
            "description": "`GET /v1/countries` dagi `id`",
            "examples": [
              187
            ]
          },
          "service_code": {
            "type": "string",
            "maxLength": 50,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9_.-]+$",
            "title": "Service Code",
            "examples": [
              "907"
            ]
          },
          "sandbox_scenario": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "success",
                  "no_sms",
                  "expire_fast"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Sandbox Scenario",
            "description": "Faqat test kalitlari: `success` — ~8 soniyada SMS keladi (standart); `no_sms` — SMS kelmaydi, 20 daqiqada `expired`; `expire_fast` — 30 soniyada `expired`."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "country_id",
          "service_code"
        ],
        "title": "OrderCreate"
      },
      "OrderService": {
        "properties": {
          "code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Code",
            "examples": [
              "907"
            ]
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title",
            "examples": [
              "Telegram"
            ]
          }
        },
        "type": "object",
        "title": "OrderService"
      },
      "Price": {
        "properties": {
          "amount": {
            "type": "string",
            "title": "Amount",
            "description": "Chegirmali narx, so'm (string — suzuvchi nuqta xatosiz)",
            "examples": [
              "8550.00"
            ]
          },
          "amount_cents": {
            "type": "integer",
            "title": "Amount Cents",
            "description": "Chegirmali narx, tiyin",
            "examples": [
              855000
            ]
          },
          "retail_amount": {
            "type": "string",
            "title": "Retail Amount",
            "description": "Saytdagi chakana narx, so'm",
            "examples": [
              "9500.00"
            ]
          },
          "retail_amount_cents": {
            "type": "integer",
            "title": "Retail Amount Cents",
            "examples": [
              950000
            ]
          },
          "discount_percent": {
            "type": "string",
            "title": "Discount Percent",
            "description": "Qo'llangan chegirma, %",
            "examples": [
              "10.00"
            ]
          },
          "currency": {
            "type": "string",
            "const": "UZS",
            "title": "Currency",
            "default": "UZS"
          }
        },
        "type": "object",
        "required": [
          "amount",
          "amount_cents",
          "retail_amount",
          "retail_amount_cents",
          "discount_percent"
        ],
        "title": "Price"
      },
      "Problem": {
        "properties": {
          "type": {
            "type": "string",
            "title": "Type",
            "examples": [
              "https://api.milliysavdo.uz/docs/errors#insufficient_balance"
            ]
          },
          "title": {
            "type": "string",
            "title": "Title",
            "examples": [
              "Balans yetarli emas"
            ]
          },
          "status": {
            "type": "integer",
            "title": "Status",
            "examples": [
              402
            ]
          },
          "detail": {
            "type": "string",
            "title": "Detail",
            "examples": [
              "Balans yetarli emas"
            ]
          },
          "code": {
            "type": "string",
            "title": "Code",
            "description": "Barqaror mashina kodi — shunga qarab tarmoqlang",
            "examples": [
              "insufficient_balance"
            ]
          },
          "request_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Id",
            "examples": [
              "req_5f2c1e9a0b7d4c3e8f1a2b3c"
            ]
          },
          "errors": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Errors",
            "description": "`validation_error` da maydonlar bo'yicha xatolar"
          }
        },
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code"
        ],
        "title": "Problem",
        "description": "RFC 9457 xato javobi (`application/problem+json`)."
      },
      "Service": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code",
            "examples": [
              "907"
            ]
          },
          "title": {
            "type": "string",
            "title": "Title",
            "examples": [
              "Telegram"
            ]
          },
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category",
            "examples": [
              "messenger"
            ]
          },
          "country_id": {
            "type": "integer",
            "title": "Country Id",
            "examples": [
              187
            ]
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "in_stock": {
            "type": "integer",
            "title": "In Stock",
            "description": "Taxminiy zaxira (provayder ma'lumoti)",
            "examples": [
              1240
            ]
          },
          "available": {
            "type": "boolean",
            "title": "Available",
            "description": "false — provayder tomonida vaqtincha yopiq"
          },
          "price": {
            "$ref": "#/components/schemas/Price"
          }
        },
        "type": "object",
        "required": [
          "code",
          "title",
          "country_id",
          "in_stock",
          "available",
          "price"
        ],
        "title": "Service"
      },
      "ServicePrice": {
        "properties": {
          "country": {
            "$ref": "#/components/schemas/OrderCountry"
          },
          "service": {
            "$ref": "#/components/schemas/OrderService"
          },
          "in_stock": {
            "type": "integer",
            "title": "In Stock"
          },
          "available": {
            "type": "boolean",
            "title": "Available"
          },
          "price": {
            "$ref": "#/components/schemas/Price"
          }
        },
        "type": "object",
        "required": [
          "country",
          "service",
          "in_stock",
          "available",
          "price"
        ],
        "title": "ServicePrice"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          },
          "input": {
            "title": "Input"
          },
          "ctx": {
            "type": "object",
            "title": "Context"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ms_live_… / ms_test_…"
      }
    }
  },
  "tags": [
    {
      "name": "Akkaunt",
      "description": "Kalit, limitlar va balans"
    },
    {
      "name": "Katalog",
      "description": "Davlatlar, xizmatlar va narxlar"
    },
    {
      "name": "Buyurtmalar",
      "description": "Raqam olish, SMS kodni kutish, bekor qilish"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "x-error-codes": {
    "invalid_request": {
      "status": 400,
      "title": "So'rov noto'g'ri"
    },
    "validation_error": {
      "status": 422,
      "title": "Maydonlar tekshiruvdan o'tmadi"
    },
    "authentication_required": {
      "status": 401,
      "title": "API kalit berilmagan"
    },
    "invalid_api_key": {
      "status": 401,
      "title": "API kalit yaroqsiz"
    },
    "api_key_expired": {
      "status": 401,
      "title": "API kalit muddati tugagan"
    },
    "api_key_revoked": {
      "status": 401,
      "title": "API kalit bekor qilingan"
    },
    "api_key_in_query": {
      "status": 400,
      "title": "API kalit URL'da yuborilmasin"
    },
    "insufficient_scope": {
      "status": 403,
      "title": "Kalitda bu amal uchun ruxsat yo'q"
    },
    "live_access_not_granted": {
      "status": 403,
      "title": "Production ruxsati berilmagan"
    },
    "client_suspended": {
      "status": 403,
      "title": "Akkaunt vaqtincha to'xtatilgan"
    },
    "client_blocked": {
      "status": 403,
      "title": "Akkaunt bloklangan"
    },
    "ip_not_allowed": {
      "status": 403,
      "title": "IP manzil ruxsat ro'yxatida yo'q"
    },
    "forbidden": {
      "status": 403,
      "title": "Ruxsat yo'q"
    },
    "not_found": {
      "status": 404,
      "title": "Topilmadi"
    },
    "conflict": {
      "status": 409,
      "title": "Holat ziddiyati"
    },
    "idempotency_in_progress": {
      "status": 409,
      "title": "Shu Idempotency-Key bilan so'rov hali bajarilmoqda"
    },
    "idempotency_key_reused": {
      "status": 422,
      "title": "Idempotency-Key boshqa so'rov uchun ishlatilgan"
    },
    "sms_already_received": {
      "status": 409,
      "title": "SMS kod allaqachon kelgan"
    },
    "order_not_cancellable": {
      "status": 409,
      "title": "Buyurtmani bekor qilib bo'lmaydi"
    },
    "insufficient_balance": {
      "status": 402,
      "title": "Balans yetarli emas"
    },
    "out_of_stock": {
      "status": 409,
      "title": "Raqamlar tugagan"
    },
    "service_unavailable": {
      "status": 409,
      "title": "Xizmat vaqtincha ishlamayapti"
    },
    "rate_limited": {
      "status": 429,
      "title": "So'rovlar chegarasi oshdi"
    },
    "quota_exceeded": {
      "status": 429,
      "title": "Kunlik/oylik kvota tugadi"
    },
    "order_limit_reached": {
      "status": 429,
      "title": "Buyurtmalar chegarasi oshdi"
    },
    "too_many_failed_orders": {
      "status": 429,
      "title": "SMS kelmagan buyurtmalar ko'p — vaqtincha cheklov"
    },
    "temporarily_blocked": {
      "status": 429,
      "title": "Shubhali trafik — vaqtincha cheklov"
    },
    "upstream_unavailable": {
      "status": 503,
      "title": "Operator bilan aloqa yo'q"
    },
    "internal_error": {
      "status": 500,
      "title": "Ichki xato"
    },
    "session_required": {
      "status": 401,
      "title": "Portal sessiyasi yo'q yoki tugagan"
    },
    "csrf_failed": {
      "status": 403,
      "title": "So'rov manbasi tasdiqlanmadi"
    },
    "invalid_grant": {
      "status": 400,
      "title": "SSO kodi yaroqsiz yoki muddati tugagan"
    },
    "webhook_url_rejected": {
      "status": 422,
      "title": "Webhook manzili qabul qilinmadi"
    },
    "limit_reached": {
      "status": 409,
      "title": "Chegara: yangi obyekt yaratib bo'lmaydi"
    }
  },
  "webhooks": {
    "order.created": {
      "post": {
        "summary": "order.created",
        "description": "Standard Webhooks imzosi: `webhook-id`, `webhook-timestamp`, `webhook-signature` headerlari. 2xx qaytaring; aks holda 8 martagacha qayta yuboriladi.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "examples": [
                      "evt_3f9a2c7d1e5b8a0c4d6e2f1a"
                    ]
                  },
                  "object": {
                    "const": "event"
                  },
                  "type": {
                    "const": "order.created"
                  },
                  "mode": {
                    "enum": [
                      "test",
                      "live"
                    ]
                  },
                  "api_version": {
                    "type": "string"
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "order": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Qabul qilindi"
          }
        }
      }
    },
    "order.sms_received": {
      "post": {
        "summary": "order.sms_received",
        "description": "Standard Webhooks imzosi: `webhook-id`, `webhook-timestamp`, `webhook-signature` headerlari. 2xx qaytaring; aks holda 8 martagacha qayta yuboriladi.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "examples": [
                      "evt_3f9a2c7d1e5b8a0c4d6e2f1a"
                    ]
                  },
                  "object": {
                    "const": "event"
                  },
                  "type": {
                    "const": "order.sms_received"
                  },
                  "mode": {
                    "enum": [
                      "test",
                      "live"
                    ]
                  },
                  "api_version": {
                    "type": "string"
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "order": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Qabul qilindi"
          }
        }
      }
    },
    "order.cancelled": {
      "post": {
        "summary": "order.cancelled",
        "description": "Standard Webhooks imzosi: `webhook-id`, `webhook-timestamp`, `webhook-signature` headerlari. 2xx qaytaring; aks holda 8 martagacha qayta yuboriladi.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "examples": [
                      "evt_3f9a2c7d1e5b8a0c4d6e2f1a"
                    ]
                  },
                  "object": {
                    "const": "event"
                  },
                  "type": {
                    "const": "order.cancelled"
                  },
                  "mode": {
                    "enum": [
                      "test",
                      "live"
                    ]
                  },
                  "api_version": {
                    "type": "string"
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "order": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Qabul qilindi"
          }
        }
      }
    },
    "order.expired": {
      "post": {
        "summary": "order.expired",
        "description": "Standard Webhooks imzosi: `webhook-id`, `webhook-timestamp`, `webhook-signature` headerlari. 2xx qaytaring; aks holda 8 martagacha qayta yuboriladi.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "examples": [
                      "evt_3f9a2c7d1e5b8a0c4d6e2f1a"
                    ]
                  },
                  "object": {
                    "const": "event"
                  },
                  "type": {
                    "const": "order.expired"
                  },
                  "mode": {
                    "enum": [
                      "test",
                      "live"
                    ]
                  },
                  "api_version": {
                    "type": "string"
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "order": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Qabul qilindi"
          }
        }
      }
    },
    "order.failed": {
      "post": {
        "summary": "order.failed",
        "description": "Standard Webhooks imzosi: `webhook-id`, `webhook-timestamp`, `webhook-signature` headerlari. 2xx qaytaring; aks holda 8 martagacha qayta yuboriladi.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "examples": [
                      "evt_3f9a2c7d1e5b8a0c4d6e2f1a"
                    ]
                  },
                  "object": {
                    "const": "event"
                  },
                  "type": {
                    "const": "order.failed"
                  },
                  "mode": {
                    "enum": [
                      "test",
                      "live"
                    ]
                  },
                  "api_version": {
                    "type": "string"
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "order": {
                        "$ref": "#/components/schemas/Order"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Qabul qilindi"
          }
        }
      }
    }
  }
}