{
  "openapi": "3.1.0",
  "info": {
    "title": "Siel SMS API",
    "version": "1.0",
    "summary": "Send SMS and OTP codes, and follow their delivery.",
    "description": "The REST API of Siel's SMS gateway. Every request carries one of your API\nkeys as a bearer token. Amounts are integers in micros, millionths of your\naccount's currency: 30000 is 0.03. Times are RFC 3339.\n\nGuides, examples in eight languages and the error codes are at\nhttps://docs.siellabs.com.\n",
    "contact": {
      "name": "Siel Labs",
      "url": "https://docs.siellabs.com"
    }
  },
  "servers": [
    {
      "url": "https://api.siellabs.com"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Messages",
      "description": "Send SMS and follow them."
    },
    {
      "name": "Account",
      "description": "Your balance and prices."
    },
    {
      "name": "OTP",
      "description": "One-time codes by Telegram or SMS."
    },
    {
      "name": "Templates",
      "description": "Texts kept for messages and OTPs."
    },
    {
      "name": "Sender IDs",
      "description": "The sender IDs your account may send from."
    },
    {
      "name": "Webhooks",
      "description": "Where OTP events go."
    }
  ],
  "paths": {
    "/v1/messages": {
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "sendMessage",
        "summary": "Send a message",
        "description": "Validates and prices a message, charges your balance and queues it.\nAnswers at once; delivery is reported by webhooks. Send `body`, or\n`template_id` with `variables`.\n",
        "x-permission": "messages",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendMessageRequest"
              },
              "example": {
                "to": "+447700900123",
                "from": "YourBrand",
                "body": "Your order #4821 has shipped",
                "client_reference": "order-4821"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Accepted and charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "200": {
            "description": "A repeat of an earlier request with the same Idempotency-Key; nothing sent or charged again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "tags": [
          "Messages"
        ],
        "operationId": "listMessages",
        "summary": "List messages",
        "description": "Your most recent messages, newest first, however they were sent.",
        "x-permission": "read",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The messages, without parts and links.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/messages/batch": {
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "sendBatch",
        "summary": "Send a batch",
        "description": "One text or template to up to 100 numbers, each with its own\nvariables and reference. What applies to every message is checked\nfirst and fails the whole call; then each message is sent and answers\nfor itself. A batch waits its turn under your messages per second for\nup to 25 seconds; messages that would wait longer come back\n`rate_limited`.\n",
        "x-permission": "messages",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendBatchRequest"
              },
              "example": {
                "from": "YourBrand",
                "body": "Hi {{name}}, your table is booked for {{time}}.",
                "variables": {
                  "time": "19:30"
                },
                "messages": [
                  {
                    "to": "+447700900123",
                    "variables": {
                      "name": "Amy"
                    },
                    "client_reference": "booking-311"
                  },
                  {
                    "to": "+447700900456",
                    "variables": {
                      "name": "Ben",
                      "time": "20:00"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The batch was looked at; each message's outcome is in `data`, in the order sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/v1/messages/{id}": {
      "get": {
        "tags": [
          "Messages"
        ],
        "operationId": "getMessage",
        "summary": "Retrieve a message",
        "description": "A message as it is now, with each part's delivery receipt and its short links.",
        "x-permission": "read",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "The message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/balance": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getBalance",
        "summary": "Balance",
        "description": "What your account has to send with, as of now.",
        "x-permission": "read",
        "responses": {
          "200": {
            "description": "The balance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/prices": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "listPrices",
        "summary": "Prices",
        "description": "What you pay per part, by country and network, under your key's product, with announced changes.",
        "x-permission": "read",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "description": "Only this country's prices, ISO 3166-1 alpha-2.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The price list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "currency",
                    "data"
                  ],
                  "properties": {
                    "currency": {
                      "type": "string",
                      "description": "ISO 4217."
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Price"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/verifications": {
      "post": {
        "tags": [
          "OTP"
        ],
        "operationId": "startVerification",
        "summary": "Send a code",
        "description": "Makes a code and sends it by the first channel that can take it, falling back to the next.",
        "x-permission": "otp",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartVerificationRequest"
              },
              "example": {
                "to": "+447700900123",
                "channels": [
                  "telegram",
                  "sms"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "description": "The request is invalid, or no channel could send the code (`not_sent`, with the verification).",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Error"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "verification": {
                          "$ref": "#/components/schemas/Verification"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "tags": [
          "OTP"
        ],
        "operationId": "listVerifications",
        "summary": "List codes",
        "x-permission": "otp",
        "parameters": [
          {
            "name": "to",
            "in": "query",
            "description": "Only this number.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/VerificationStatus"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "description": "Only codes now carried by this channel.",
            "schema": {
              "type": "string",
              "enum": [
                "telegram",
                "sms"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The codes, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Verification"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/v1/verifications/{id}": {
      "get": {
        "tags": [
          "OTP"
        ],
        "operationId": "getVerification",
        "summary": "Look a code up",
        "x-permission": "otp",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "The verification; never its code.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Verification"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/verifications/{id}/check": {
      "post": {
        "tags": [
          "OTP"
        ],
        "operationId": "checkVerification",
        "summary": "Check a code",
        "x-permission": "otp",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "code"
                ],
                "additionalProperties": false,
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "What the person typed."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The result. A wrong code is a 200 too, with `valid` false.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/verifications/check": {
      "post": {
        "tags": [
          "OTP"
        ],
        "operationId": "checkNumber",
        "summary": "Check a code by number",
        "description": "Checks the latest code sent to a number, for when you didn't keep its id.",
        "x-permission": "otp",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "to",
                  "code"
                ],
                "additionalProperties": false,
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "The number the code went to."
                  },
                  "code": {
                    "type": "string",
                    "description": "What the person typed."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/templates": {
      "get": {
        "tags": [
          "Templates"
        ],
        "operationId": "listTemplates",
        "summary": "List templates",
        "x-permission": "templates",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "description": "Only templates whose name starts with this.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The templates.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Template"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Templates"
        ],
        "operationId": "createTemplate",
        "summary": "Create a template",
        "x-permission": "templates",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/v1/templates/{id}": {
      "get": {
        "tags": [
          "Templates"
        ],
        "operationId": "getTemplate",
        "summary": "Retrieve a template",
        "x-permission": "templates",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "The template.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "tags": [
          "Templates"
        ],
        "operationId": "updateTemplate",
        "summary": "Update a template",
        "x-permission": "templates",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      },
      "delete": {
        "tags": [
          "Templates"
        ],
        "operationId": "deleteTemplate",
        "summary": "Delete a template",
        "x-permission": "templates",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/senders": {
      "get": {
        "tags": [
          "Sender IDs"
        ],
        "operationId": "listSenders",
        "summary": "List sender IDs",
        "description": "Registering one happens in the web app, where it's reviewed.",
        "x-permission": "read",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "approved",
                "rejected"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The sender IDs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SenderID"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/v1/senders/{id}": {
      "get": {
        "tags": [
          "Sender IDs"
        ],
        "operationId": "getSender",
        "summary": "Retrieve a sender ID",
        "x-permission": "read",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "The sender ID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SenderID"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "description": "Where OTP events go. Message status events go to each message's callback URL instead.",
        "x-permission": "webhooks",
        "responses": {
          "200": {
            "description": "The webhooks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "createWebhook",
        "summary": "Create a webhook",
        "x-permission": "webhooks",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "getWebhook",
        "summary": "Retrieve a webhook",
        "x-permission": "webhooks",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "updateWebhook",
        "summary": "Update a webhook",
        "x-permission": "webhooks",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook",
        "x-permission": "webhooks",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "webhooks": {
    "message.status": {
      "post": {
        "summary": "A message's status changed",
        "description": "POSTed to the message's callback URL. Signed: HMAC-SHA256 of\n`\u003cX-Smsgw-Timestamp\u003e.\u003craw body\u003e` with your webhook secret, in lowercase\nhex after `v1=`, in `X-Smsgw-Signature`. Answer 2xx within 10 seconds.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SignatureTimestamp"
          },
          {
            "$ref": "#/components/parameters/Signature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageEvent"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    },
    "verification.status": {
      "post": {
        "summary": "A code's status or channel changed",
        "description": "Signed like message events. Goes to the request's callback_url, else your webhooks, else your account's callback URL.",
        "parameters": [
          {
            "$ref": "#/components/parameters/SignatureTimestamp"
          },
          {
            "$ref": "#/components/parameters/Signature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerificationEvent"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "One of your API keys, `smsgw_…`, from the web app's API keys page. A key may be limited to some permissions (each operation's `x-permission`), addresses and a date."
      }
    },
    "parameters": {
      "Id": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "1 to 200. Default 50.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "description": "Up to 255 characters, unique per message. A retry with the same key returns the original instead of sending again.",
        "schema": {
          "type": "string",
          "maxLength": 255
        }
      },
      "SignatureTimestamp": {
        "name": "X-Smsgw-Timestamp",
        "in": "header",
        "required": true,
        "description": "Unix seconds. Refuse events more than five minutes old.",
        "schema": {
          "type": "string"
        }
      },
      "Signature": {
        "name": "X-Smsgw-Signature",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "example": "v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"
        }
      }
    },
    "headers": {
      "RetryAfter": {
        "description": "Seconds until the same request can work.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The body isn't JSON, has an unknown field or a field of the wrong type (`invalid_json`), or a parameter is wrong.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "No key, an unknown or revoked one (`unauthorized`), or one past its expiry date (`key_expired`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InsufficientBalance": {
        "description": "Your balance and credit limit don't cover the price (`insufficient_balance`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The account or service can't send (`account_pending`, `account_suspended`, `service_suspended`),\nfraud protection refused it (`country_not_allowed`, `unsafe_link`, `content_blocked`,\n`spending_limit_reached`, `trial_number`), or the key may not do it (`ip_not_allowed`,\n`permission_denied`).\n",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such resource of yours (`not_found`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "An Idempotency-Key reused for a different message (`idempotency_key_reused`), or a template name taken (`template_exists`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "A field's value can't be used; the code says which (`invalid_to`, `sender_not_approved`, `missing_variables`…).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Over your account's messages per second (`rate_limited`), or an OTP limit (`too_many_codes`).",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable and machine-readable: branch on it."
              },
              "message": {
                "type": "string",
                "description": "For people; may change."
              },
              "retry_after": {
                "type": "integer",
                "description": "Seconds until the same request can work, when that's known."
              }
            }
          }
        }
      },
      "SendMessageRequest": {
        "type": "object",
        "required": [
          "to",
          "from"
        ],
        "additionalProperties": false,
        "properties": {
          "to": {
            "type": "string",
            "description": "The recipient in international format: +447700900123."
          },
          "from": {
            "type": "string",
            "description": "One of your approved sender IDs."
          },
          "body": {
            "type": "string",
            "description": "The text, unless you send template_id. Up to 10 parts."
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "description": "One of your templates instead of body."
          },
          "variables": {
            "$ref": "#/components/schemas/Variables"
          },
          "callback_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Where this message's webhooks go instead of your account's callback URL."
          },
          "smart_encoding": {
            "type": "boolean",
            "default": false,
            "description": "Replace typographic characters so the text stays GSM-7."
          },
          "shorten_links": {
            "type": "boolean",
            "default": false,
            "description": "Turn links into short links whose clicks are counted."
          },
          "validity_period": {
            "type": "integer",
            "minimum": 10,
            "maximum": 86400,
            "description": "Seconds we may try to send it; not sent by then, it fails as EXPIRED and is refunded."
          },
          "client_reference": {
            "type": "string",
            "maxLength": 256,
            "description": "Your own id for the message, echoed in the message and its webhooks."
          }
        }
      },
      "Variables": {
        "type": "object",
        "description": "Values for the text's {{variables}}; names match whatever their case.",
        "additionalProperties": {
          "type": [
            "string",
            "number",
            "boolean"
          ]
        }
      },
      "SendBatchRequest": {
        "type": "object",
        "required": [
          "from",
          "messages"
        ],
        "additionalProperties": false,
        "properties": {
          "from": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "template_id": {
            "type": "string",
            "format": "uuid"
          },
          "variables": {
            "$ref": "#/components/schemas/Variables"
          },
          "callback_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "smart_encoding": {
            "type": "boolean",
            "default": false
          },
          "shorten_links": {
            "type": "boolean",
            "default": false
          },
          "validity_period": {
            "type": "integer",
            "minimum": 10,
            "maximum": 86400
          },
          "messages": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "object",
              "required": [
                "to"
              ],
              "additionalProperties": false,
              "properties": {
                "to": {
                  "type": "string"
                },
                "variables": {
                  "$ref": "#/components/schemas/Variables"
                },
                "client_reference": {
                  "type": "string",
                  "maxLength": 256
                }
              }
            }
          }
        }
      },
      "BatchResponse": {
        "type": "object",
        "required": [
          "accepted",
          "refused",
          "data"
        ],
        "properties": {
          "accepted": {
            "type": "integer"
          },
          "refused": {
            "type": "integer"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BatchResult"
            }
          }
        }
      },
      "BatchResult": {
        "type": "object",
        "required": [
          "index"
        ],
        "properties": {
          "index": {
            "type": "integer",
            "description": "Its place in messages."
          },
          "message": {
            "$ref": "#/components/schemas/Message"
          },
          "to": {
            "type": "string",
            "description": "As sent, on a refused message."
          },
          "client_reference": {
            "type": "string",
            "description": "As sent, on a refused message."
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "retry_after": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Message": {
        "type": "object",
        "required": [
          "id",
          "to",
          "from",
          "body",
          "status",
          "country",
          "encoding",
          "segments",
          "price_micros",
          "campaign_id",
          "error_code",
          "error_message",
          "attempts",
          "created_at",
          "sent_at",
          "done_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "to": {
            "type": "string",
            "description": "E.164."
          },
          "from": {
            "type": "string"
          },
          "body": {
            "type": "string",
            "description": "As sent: after smart encoding and link shortening. Empty once retention erased it."
          },
          "body_erased": {
            "type": "boolean",
            "description": "Only when retention erased the text."
          },
          "links": {
            "type": "array",
            "description": "Only when it has short links.",
            "items": {
              "$ref": "#/components/schemas/ShortLink"
            }
          },
          "status": {
            "$ref": "#/components/schemas/MessageStatus"
          },
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2."
          },
          "network": {
            "type": "string",
            "description": "Only when known."
          },
          "encoding": {
            "type": "string",
            "enum": [
              "gsm7",
              "ucs2"
            ]
          },
          "segments": {
            "type": "integer",
            "description": "The parts billed."
          },
          "price_micros": {
            "type": "integer"
          },
          "local": {
            "type": "boolean",
            "description": "Only where your prices tell local and international apart."
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "client_reference": {
            "type": "string",
            "description": "Only when you set one."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Only when you set a validity_period."
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why it didn't arrive; RETRYING while it waits to be tried again."
          },
          "error_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "attempts": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "done_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "parts": {
            "type": "array",
            "description": "Only in GET /v1/messages/{id}.",
            "items": {
              "$ref": "#/components/schemas/MessagePart"
            }
          }
        }
      },
      "MessageStatus": {
        "type": "string",
        "enum": [
          "queued",
          "sending",
          "sent",
          "delivered",
          "undelivered",
          "failed"
        ]
      },
      "MessagePart": {
        "type": "object",
        "required": [
          "seq",
          "units",
          "limit",
          "status",
          "smsc_id",
          "receipt_stat",
          "receipt_err",
          "submitted_at",
          "done_at"
        ],
        "properties": {
          "seq": {
            "type": "integer"
          },
          "units": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "accepted",
              "delivered",
              "undelivered",
              "failed"
            ]
          },
          "smsc_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "receipt_stat": {
            "type": [
              "string",
              "null"
            ]
          },
          "receipt_err": {
            "type": [
              "string",
              "null"
            ]
          },
          "submitted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "done_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ShortLink": {
        "type": "object",
        "required": [
          "code",
          "short_url",
          "url",
          "clicks",
          "first_click_at",
          "last_click_at"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "short_url": {
            "type": "string",
            "format": "uri"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "clicks": {
            "type": "integer"
          },
          "first_click_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_click_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Balance": {
        "type": "object",
        "required": [
          "balance_micros",
          "credit_limit_micros",
          "available_micros",
          "currency"
        ],
        "properties": {
          "balance_micros": {
            "type": "integer"
          },
          "credit_limit_micros": {
            "type": "integer"
          },
          "available_micros": {
            "type": "integer",
            "description": "Balance plus credit limit: what you can still spend."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217."
          }
        }
      },
      "Price": {
        "type": "object",
        "required": [
          "country",
          "mccmnc",
          "price_micros",
          "effective_from",
          "state"
        ],
        "properties": {
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2, or * for every country not listed."
          },
          "mccmnc": {
            "type": "string",
            "description": "The network; empty for the rest of the country."
          },
          "network": {
            "type": "string"
          },
          "price_micros": {
            "type": "integer",
            "description": "Per part."
          },
          "pricing": {
            "type": "string",
            "enum": [
              "local",
              "international"
            ]
          },
          "effective_from": {
            "type": "string",
            "format": "date-time"
          },
          "state": {
            "type": "string",
            "enum": [
              "current",
              "scheduled"
            ]
          }
        }
      },
      "StartVerificationRequest": {
        "type": "object",
        "required": [
          "to"
        ],
        "additionalProperties": false,
        "properties": {
          "to": {
            "type": "string"
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "telegram",
                "sms"
              ]
            },
            "description": "In order. Default: Telegram, then SMS."
          },
          "code_length": {
            "type": "integer",
            "minimum": 4,
            "maximum": 8,
            "default": 6
          },
          "code": {
            "type": "string",
            "pattern": "^[0-9]{4,8}$",
            "description": "Your own code instead of one we make."
          },
          "ttl_seconds": {
            "type": "integer",
            "minimum": 60,
            "maximum": 86400,
            "default": 600
          },
          "from": {
            "type": "string",
            "description": "The SMS sender; default your first approved one."
          },
          "sms_template": {
            "type": "string",
            "maxLength": 300,
            "description": "The SMS text, with {code} where the code goes."
          },
          "template_id": {
            "type": "string",
            "format": "uuid"
          },
          "payload": {
            "type": "string",
            "maxLength": 500,
            "description": "Returned with the code and in every event."
          },
          "callback_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Verification": {
        "type": "object",
        "required": [
          "id",
          "to",
          "status",
          "channel",
          "channels",
          "price_micros",
          "checks_left",
          "expires_at",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "to": {
            "type": "string"
          },
          "status": {
            "$ref": "#/components/schemas/VerificationStatus"
          },
          "channel": {
            "type": "string",
            "enum": [
              "telegram",
              "sms"
            ]
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "telegram",
                "sms"
              ]
            }
          },
          "telegram_status": {
            "type": "string",
            "enum": [
              "sent",
              "delivered",
              "read",
              "expired",
              "revoked"
            ]
          },
          "sms_message_id": {
            "type": "string",
            "format": "uuid"
          },
          "sms_status": {
            "$ref": "#/components/schemas/MessageStatus"
          },
          "price_micros": {
            "type": "integer"
          },
          "checks_left": {
            "type": "integer"
          },
          "error": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time"
          },
          "verified_at": {
            "type": "string",
            "format": "date-time"
          },
          "payload": {
            "type": "string"
          }
        }
      },
      "VerificationStatus": {
        "type": "string",
        "enum": [
          "pending",
          "sent",
          "delivered",
          "read",
          "verified",
          "failed",
          "expired"
        ]
      },
      "CheckResult": {
        "type": "object",
        "required": [
          "valid",
          "result",
          "verification"
        ],
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "result": {
            "type": "string",
            "enum": [
              "valid",
              "invalid",
              "expired",
              "max_attempts",
              "closed"
            ]
          },
          "verification": {
            "$ref": "#/components/schemas/Verification"
          }
        }
      },
      "TemplateRequest": {
        "type": "object",
        "required": [
          "name",
          "body"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "category": {
            "type": "string",
            "maxLength": 40
          },
          "body": {
            "type": "string",
            "description": "With {code} for OTPs, or {{variables}} for messages."
          }
        }
      },
      "Template": {
        "type": "object",
        "required": [
          "id",
          "name",
          "category",
          "body",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SenderID": {
        "type": "object",
        "required": [
          "id",
          "sender",
          "status",
          "use_case",
          "countries",
          "review_note",
          "fee_micros",
          "created_at",
          "reviewed_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sender": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "rejected"
            ]
          },
          "use_case": {
            "type": "string"
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "review_note": {
            "type": [
              "string",
              "null"
            ]
          },
          "fee_micros": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "reviewed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "WebhookRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "telegram",
                "sms"
              ]
            },
            "description": "Only these channels' events; empty for all."
          }
        }
      },
      "Webhook": {
        "type": "object",
        "required": [
          "id",
          "name",
          "url",
          "channels",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "MessageEvent": {
        "type": "object",
        "required": [
          "event_id",
          "type",
          "message_id",
          "status",
          "to",
          "from",
          "segments",
          "error_code",
          "error_message",
          "created_at",
          "occurred_at"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "description": "The same on every retry: ignore one you've handled."
          },
          "type": {
            "type": "string",
            "const": "message.status"
          },
          "message_id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/MessageStatus"
          },
          "to": {
            "type": "string"
          },
          "from": {
            "type": "string"
          },
          "segments": {
            "type": "integer"
          },
          "error_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "error_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "client_reference": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "VerificationEvent": {
        "type": "object",
        "required": [
          "event_id",
          "type",
          "verification_id",
          "status",
          "channel",
          "to",
          "error",
          "created_at",
          "occurred_at"
        ],
        "properties": {
          "event_id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "const": "verification.status"
          },
          "verification_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/VerificationStatus"
          },
          "channel": {
            "type": "string",
            "enum": [
              "telegram",
              "sms"
            ]
          },
          "to": {
            "type": "string"
          },
          "payload": {
            "type": "string"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}
