{
  "openapi": "3.0.3",
  "info": {
    "title": "ringbeta Developer API",
    "version": "1.0.0",
    "description": "ringbeta Developer API: phone number rental, access to purchased mailboxes, eSIM purchase, and account information. Every business endpoint requires exchanging your static API Token for a JWT via /auth/token first, then calling with Authorization: Bearer <JWT>."
  },
  "servers": [
    { "url": "https://api.ringbeta.com", "description": "Production" }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Call POST /auth/token first to get a JWT, then paste it here (no need to add the Bearer prefix, Swagger adds it automatically)"
      }
    },
    "schemas": {
      "StandardResponse": {
        "type": "object",
        "properties": {
          "status": { "type": "boolean" },
          "msg": { "type": "string" },
          "data": {}
        }
      }
    }
  },
  "security": [{ "bearerAuth": [] }],
  "paths": {
    "/api/v1/auth/token": {
      "post": {
        "summary": "Exchange for a JWT",
        "tags": ["Auth"],
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["api_token"],
                "properties": { "api_token": { "type": "string", "description": "Static API Token from the /dash/account page" } }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "boolean" },
                "msg": { "type": "string" },
                "data": {
                  "type": "object",
                  "properties": {
                    "jwt": { "type": "string" },
                    "expires_in": { "type": "integer", "description": "Validity in seconds, 7 days = 604800" }
                  }
                }
              }
            } } }
          },
          "401": { "description": "Invalid api_token" }
        }
      }
    },
    "/api/v1/user/profile": {
      "get": {
        "summary": "Account profile (includes balance)",
        "tags": ["User"],
        "responses": {
          "200": {
            "description": "Success",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "status": { "type": "boolean" },
                "msg": { "type": "string" },
                "data": {
                  "type": "object",
                  "properties": {
                    "mail": { "type": "string" },
                    "name": { "type": "string" },
                    "level": { "type": "integer" },
                    "balance": { "type": "integer", "description": "Account balance, in cents" },
                    "createTime": { "type": "integer" }
                  }
                }
              }
            } } }
          }
        }
      }
    },
    "/api/v1/billing/consume": {
      "post": {
        "summary": "Consumption records (read-only)",
        "tags": ["Billing"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "page": { "type": "integer", "default": 1, "description": "Page number, starting from 1" },
              "limit": { "type": "integer", "default": 10, "description": "Results per page, 1-100" }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/billing/recharge": {
      "post": {
        "summary": "Recharge history (read-only, creating a new recharge via the API is not supported)",
        "tags": ["Billing"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "page": { "type": "integer", "default": 1, "description": "Page number, starting from 1" },
              "limit": { "type": "integer", "default": 10, "description": "Results per page, 1-100" }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/phone/options": {
      "get": {
        "summary": "Phone rental options: countries + suppliers + prices + stock",
        "description": "The `stock` field is an exact real-time count for warehouse-inventory suppliers. For on-demand/real-time-provisioning suppliers, `stock` is a fixed placeholder value (999) meaning \"plenty available\" rather than an exact count — actual availability is confirmed when you call /phone/rent.",
        "tags": ["Phone"],
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/phone/list": {
      "post": {
        "summary": "List your rented numbers",
        "tags": ["Phone"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "page": { "type": "integer", "default": 1, "description": "Page number, starting from 1" },
              "limit": { "type": "integer", "default": 10, "description": "Results per page, 1-100" }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/phone/rent": {
      "post": {
        "summary": "Rent a phone number",
        "tags": ["Phone"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object",
            "required": ["countrycode", "supplierId"],
            "properties": {
              "countrycode": { "type": "string", "example": "us", "description": "Required. Country code, see /phone/options for the full list of supported countries." },
              "supplierId": { "type": "string", "description": "Required. Supplier ID for the chosen country, see /phone/options." },
              "period": { "type": "integer", "enum": [7, 30, 90, 365], "default": 7, "description": "Optional. Rental duration in days for a brand-new number, only applies when reused is not true." },
              "reused": { "type": "boolean", "default": false, "description": "Optional. false (or omitted) = a brand-new number using the chosen period. true = a previously-used number, cheaper, always fixed at a 7-day period." },
              "count": { "type": "integer", "default": 1, "maximum": 50, "description": "Optional. How many numbers to rent at once, 1-50." }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" }, "400": { "description": "Failed" } }
      }
    },
    "/api/v1/phone/renew": {
      "post": {
        "summary": "Renew a number",
        "tags": ["Phone"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object", "required": ["phone"],
            "properties": { "phone": { "type": "string", "description": "Required. One of your numbers. It doesn't need to be currently active - an expired number can still be renewed as long as it hasn't since been rented out to another account." } }
          } } }
        },
        "responses": { "200": { "description": "Success" }, "404": { "description": "Number not found under your account, or it has since been rented out to another account" } }
      }
    },
    "/api/v1/phone/messages": {
      "post": {
        "summary": "Get SMS received by your number(s)",
        "tags": ["Phone"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "phone": { "type": "string", "description": "Optional. Omit to get messages across all of your currently rented numbers, merged and paginated." },
              "page": { "type": "integer", "default": 1, "description": "Page number, starting from 1" },
              "limit": { "type": "integer", "default": 10, "description": "Results per page, 1-100" }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" }, "404": { "description": "Number not found, or not currently active under your account" } }
      }
    },
    "/api/v1/phone/transfer": {
      "post": {
        "summary": "Transfer numbers to another account",
        "tags": ["Phone"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object", "required": ["phones", "to"],
            "properties": {
              "phones": { "type": "array", "items": { "type": "string" }, "description": "Required. 1-50 of your currently active numbers to transfer." },
              "to": { "type": "string", "format": "email", "description": "Required. The recipient's ringbeta account email. Must be an existing registered account; you cannot transfer to yourself." }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" }, "400": { "description": "Failed" }, "404": { "description": "None of the given numbers are currently active under your account" } }
      }
    },
    "/api/v1/mail/list": {
      "post": {
        "summary": "List your purchased mailboxes",
        "tags": ["Mail"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "page": { "type": "integer", "default": 1, "description": "Page number, starting from 1" },
              "limit": { "type": "integer", "default": 10, "description": "Results per page, 1-100" }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/mail/messages": {
      "get": {
        "summary": "Get messages received by a mailbox",
        "tags": ["Mail"],
        "parameters": [ { "name": "mailId", "in": "query", "required": true, "description": "Required. The mailbox's ID, from /mail/list.", "schema": { "type": "string" } } ],
        "responses": { "200": { "description": "Success" }, "404": { "description": "Mailbox not found" } }
      }
    },
    "/api/v1/esim/products": {
      "post": {
        "summary": "Browse eSIM data plans",
        "tags": ["eSIM"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "type": { "type": "string", "enum": ["all", "number", "data"], "default": "all", "description": "Optional. Which of the two response groups (number_plans / data_plans) to return." },
              "countryCode": { "type": "string", "description": "Optional. Filter by country code." }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/esim/purchase": {
      "post": {
        "summary": "Buy an eSIM plan",
        "tags": ["eSIM"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object",
            "required": ["productType", "productCode"],
            "properties": {
              "productType": { "type": "string", "enum": ["number", "data"], "description": "Required. 'number' if the item came from /esim/products' number_plans array, or 'data' if it came from data_plans - tells the server which catalog to look the code up in." },
              "productCode": { "type": "string", "description": "Required. From /esim/products: the item's id field for number_plans, or its package_code field for data_plans." }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" }, "400": { "description": "Failed" } }
      }
    },
    "/api/v1/esim/list": {
      "post": {
        "summary": "List your purchased eSIMs",
        "tags": ["eSIM"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "page": { "type": "integer", "default": 1, "description": "Page number, starting from 1" },
              "limit": { "type": "integer", "default": 6, "description": "Results per page, 1-50" }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/esim/usage": {
      "post": {
        "summary": "Data usage",
        "tags": ["eSIM"],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": {
            "type": "object",
            "required": ["iccids"],
            "properties": {
              "iccids": { "type": "string", "description": "Required. One or more ICCIDs, separated by commas." }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    },
    "/api/v1/esim/orders": {
      "post": {
        "summary": "eSIM order history",
        "tags": ["eSIM"],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": {
            "type": "object",
            "properties": {
              "page": { "type": "integer", "default": 1, "description": "Page number, starting from 1" },
              "limit": { "type": "integer", "default": 10, "description": "Results per page, 1-100" }
            }
          } } }
        },
        "responses": { "200": { "description": "Success" } }
      }
    }
  }
}
