{
  "openapi": "3.1.0",
  "info": {
    "title": "NumberHub API",
    "version": "1.1.0",
    "description": "REST API for wallet balance, temporary SMS numbers, rentals, travel eSIMs, and email OTP orders."
  },
  "servers": [{ "url": "https://api.numberhub.io/v1" }],
  "security": [{ "bearerAuth": [] }],
  "paths": {
    "/balance": {
      "get": { "summary": "Get wallet balance", "responses": { "200": { "$ref": "#/components/responses/Json" }, "401": { "$ref": "#/components/responses/Error" } } }
    },
    "/orders": {
      "get": {
        "summary": "List recent orders",
        "parameters": [{ "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 40 } }],
        "responses": { "200": { "$ref": "#/components/responses/Json" }, "401": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/services": {
      "get": { "summary": "List SMS services", "responses": { "200": { "$ref": "#/components/responses/Json" } } }
    },
    "/countries": {
      "get": {
        "summary": "List countries, live prices, and stock for an SMS service",
        "parameters": [{ "name": "service", "in": "query", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/top-countries": {
      "get": { "summary": "Smart country recommendations using demand, live stock, price, and delivery quality", "responses": { "200": { "$ref": "#/components/responses/Json" } } }
    },
    "/numbers": {
      "post": {
        "summary": "Buy or queue a temporary SMS number",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object", "required": ["service", "country"],
            "properties": {
              "service": { "type": "string" }, "country": { "type": "string" },
              "max_price": { "type": "string" }, "queue": { "type": "boolean", "default": true }
            }
          } } }
        },
        "responses": { "201": { "$ref": "#/components/responses/Json" }, "402": { "$ref": "#/components/responses/Error" }, "409": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/numbers/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "get": { "summary": "Get an SMS number order", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } },
      "delete": { "summary": "Cancel an SMS number order", "responses": { "200": { "$ref": "#/components/responses/Json" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/numbers/{id}/another": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "post": { "summary": "Request another number for an order", "responses": { "201": { "$ref": "#/components/responses/Json" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/numbers/{id}/reactivate": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "post": { "summary": "Reactivate an eligible SMS number", "responses": { "200": { "$ref": "#/components/responses/Json" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/rent/durations": {
      "get": { "summary": "List rental durations", "responses": { "200": { "$ref": "#/components/responses/Json" } } }
    },
    "/rent/{h}/countries": {
      "parameters": [{ "$ref": "#/components/parameters/Duration" }],
      "get": { "summary": "List rental countries for a duration", "responses": { "200": { "$ref": "#/components/responses/Json" } } }
    },
    "/rent/{h}/{country}/services": {
      "parameters": [{ "$ref": "#/components/parameters/Duration" }, { "$ref": "#/components/parameters/Country" }],
      "get": { "summary": "List rental services", "responses": { "200": { "$ref": "#/components/responses/Json" } } }
    },
    "/rent/{h}/{country}/{code}/quote": {
      "parameters": [
        { "$ref": "#/components/parameters/Duration" }, { "$ref": "#/components/parameters/Country" },
        { "name": "code", "in": "path", "required": true, "schema": { "type": "string" } }
      ],
      "get": { "summary": "Get a rental quote", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/rentals": {
      "post": {
        "summary": "Create a number rental",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["h", "country", "code"],
          "properties": { "h": { "type": "integer" }, "country": { "type": "string" }, "code": { "type": "string" } }
        } } } },
        "responses": { "201": { "$ref": "#/components/responses/Json" }, "402": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/rentals/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "get": { "summary": "Get a rental", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } },
      "delete": { "summary": "Cancel a rental during its eligible window", "responses": { "200": { "$ref": "#/components/responses/Json" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/rentals/{id}/finish": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "post": { "summary": "Finish a rental", "responses": { "200": { "$ref": "#/components/responses/Json" }, "409": { "$ref": "#/components/responses/Error" } } }
    },
    "/esim/regions": {
      "get": { "summary": "List eSIM destinations and regions", "responses": { "200": { "$ref": "#/components/responses/Json" }, "503": { "$ref": "#/components/responses/Error" } } }
    },
    "/esim/regions/{region}/packages": {
      "parameters": [{ "name": "region", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "summary": "List live eSIM packages for a destination or region", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/esims": {
      "post": {
        "summary": "Purchase an eSIM package",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["region", "pkg"],
          "properties": { "region": { "type": "string" }, "pkg": { "type": "string" } }
        } } } },
        "responses": { "201": { "$ref": "#/components/responses/Json" }, "402": { "$ref": "#/components/responses/Error" }, "502": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/esims/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "get": { "summary": "Get an eSIM order and installation details", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/email/sites": {
      "get": { "summary": "List supported email OTP sites", "responses": { "200": { "$ref": "#/components/responses/Json" }, "503": { "$ref": "#/components/responses/Error" } } }
    },
    "/email/sites/{site}/domains": {
      "parameters": [{ "name": "site", "in": "path", "required": true, "schema": { "type": "string" } }],
      "get": { "summary": "List live email domains and prices for a site", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/emails": {
      "post": {
        "summary": "Purchase an email OTP address",
        "parameters": [{ "$ref": "#/components/parameters/IdempotencyKey" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["site"],
          "properties": { "site": { "type": "string" }, "domain": { "type": "string" } }
        } } } },
        "responses": { "201": { "$ref": "#/components/responses/Json" }, "402": { "$ref": "#/components/responses/Error" }, "502": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/emails/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "get": { "summary": "Get an email OTP order", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/webhooks": {
      "get": {
        "summary": "List active webhook endpoints",
        "responses": { "200": { "$ref": "#/components/responses/Json" } }
      },
      "post": {
        "summary": "Create a signed webhook endpoint",
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["url"],
          "properties": {
            "url": { "type": "string", "format": "uri", "pattern": "^https://" },
            "events": { "type": "array", "items": { "type": "string" }, "default": ["order.*"] }
          }
        } } } },
        "responses": { "201": { "$ref": "#/components/responses/Json" }, "400": { "$ref": "#/components/responses/Error" }, "409": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/webhooks/{id}": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "delete": { "summary": "Deactivate a webhook endpoint", "responses": { "200": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } }
    },
    "/webhooks/{id}/test": {
      "parameters": [{ "$ref": "#/components/parameters/Id" }],
      "post": { "summary": "Queue a test webhook event", "responses": { "202": { "$ref": "#/components/responses/Json" }, "404": { "$ref": "#/components/responses/Error" } } }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "NumberHub API key" }
    },
    "parameters": {
      "Id": { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } },
      "IdempotencyKey": {
        "name": "Idempotency-Key", "in": "header", "required": false,
        "description": "Unique key for a purchase attempt. Identical retries replay the first result for 24 hours.",
        "schema": { "type": "string", "minLength": 8, "maxLength": 128 }
      },
      "Duration": { "name": "h", "in": "path", "required": true, "schema": { "type": "integer", "description": "Rental duration in hours." } },
      "Country": { "name": "country", "in": "path", "required": true, "schema": { "type": "string" } }
    },
    "schemas": {
      "Error": {
        "type": "object", "required": ["error"],
        "properties": { "error": { "type": "string" }, "message": { "type": "string" }, "request_id": { "type": "string" } },
        "additionalProperties": true
      }
    },
    "responses": {
      "Json": { "description": "Successful JSON response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } },
      "Error": { "description": "Error response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  }
}
