{
  "openapi": "3.1.0",
  "info": {
    "title": "Rayo SMS API",
    "version": "1.0.0",
    "description": "# Introduction\n\nWelcome to the [Rayo SMS](https://www.rayo.gr) API documentation.\n\nYou need to study this guide if you want to integrate your application with Web-to-SMS Functionality via [Rayo SMS](https://www.rayo.gr).\n\n# SDKs Documentation\n\nIf you prefer using a ready-made SDK instead of calling the HTTP endpoints directly, check out the [Rayo SMS SDKs documentation](https://sms-sdks-docs.rayo.gr).\n\n# Base Endpoint\n\nThe endpoint that you should be sending your API requests to is:\n\n```text\nhttps://sms-api.rayo.gr/v1/\n```\n\n# Authentication\n\nThe endpoint, although public, it requires that you send your own, private, API Key as part of the HTTP `Authorization` header.\n\nYou can get and manage your API keys from the `Actions -> Settings` page inside the [Rayo SMS](https://sms.rayo.gr) Web application.\n\nNote that you can have many API keys active at the same time. This will be useful when you decide to decommission an old API key\nand replace it with a new one. You might want to keep both active at the same time for a short period of time until all of your\nsystems that integrate with Rayo SMS finally use the new API key. Or you can use two different API keys for\ndifferent purposes. It's up to you.\n\nIn the following paragraphs, where we describe the different API features, we will give examples on how you would pass the Authorization\nas part of the HTTP Request Headers, but until then, here is an example of a valid header:\n\n`Authorization: Bearer 1212845e-3517-436f-8f31-86cfb51f6251`\n\nWhere `1212845e-3517-436f-8f31-86cfb51f6251`, is valid API key. Replace this, with your own API key.\n\n**Important**: Treat the API keys as confidential as you keep your passwords. Do not store them in version control systems and do not reveal to\npublic. Always use end-to-end encryption (`HTTPS`) between the client application and the Rayo SMS endpoints when using the API.\n\n# Errors\n\nA lot of things might go wrong with your HTTP Requests. Rayo SMS API returns\n[Standard HTTP Response Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) to\nindicate the success or failure of the request.\n\nWhen the HTTP Response code is in the range `400-599`, this means that something has gone wrong.\n\nThe following are common error cases. You can see the HTTP Response Status Code and possible\ncauses of error:\n\n| Status Code | Explanation |\n| --- | --- |\n| `401` | You have provided a non-existing or inactive API key |\n| `422` | When the data in the request are invalid. For example, for an SMS request, the `fromLabel` does not belong to you. |\n| `500-599` | Indicates an error that took place on the server side. Rayo SMS developers are automatically notified for such errors and will immediately try to remedy this situation. If your problem persists, use the contact form on [Rayo SMS Web site](https://www.rayo.gr) to report the problem. |\n\nIn case you get an error in the range `500-599`, we are suggesting that you retry your\nrequest. Maybe with an increasing wait time in-between the retries. You can retry up to a certain\namount of times before you give up.\n\n**Structure of JSON Object in Response Body when Error:**\n\n```json\n{\n  \"result\": {\n    \"username\": \"...\",\n    \"resultCode\": \"0\",\n    \"resultDescription\": \"ERROR: ...\",\n    \"clientRequestId\": \"...\",\n    \"smsServerRequestId\": null\n  },\n  \"error\": \"...\"\n}\n```\n\nThe body of the HTTP Response body, might give you more information about what was the problem. If it is\nnot empty, it will contain a JSON object. Take a look at the `Structure of JSON Object in Response Body when Error`.\n\n# More API Endpoints on the Way\n\nWe are in the process of developing more API endpoints that will allow you to:\n\n* Manage Contacts, and\n* Manage groups\n",
    "contact": {
      "url": "https://www.rayo.gr"
    }
  },
  "servers": [
    {
      "url": "https://sms-api.rayo.gr",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "SMS",
      "description": "Send SMS messages immediately or schedule them for future delivery."
    },
    {
      "name": "Account",
      "description": "Retrieve account information."
    },
    {
      "name": "Delivery status",
      "description": "Retrieve SMS delivery information."
    },
    {
      "name": "Schedules",
      "description": "Manage scheduled SMS deliveries."
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "paths": {
    "/v1/send_sms": {
      "post": {
        "tags": [
          "SMS"
        ],
        "summary": "Sending an SMS",
        "description": "Sending an SMS requires you to send a `POST` request to the path `/send_sms`.\n\nThe HTTP Request should have the following headers, as a minimum requirement:\n\n### Request Headers\n\n| Name | Value |\n| --- | --- |\n| Content-Type | application/json |\n| Accept | application/json |\n| Authorization | Bearer [your API key here] |\n\nFor the `Authorization` header above, replace the `[your API key here]` with your\nown API key.\n\nThe payload of the request should be sent in the body of the request as a string.\nThe string should be a string encoding of a JSON object. The JSON object should\nhave the following properties:\n\n### JSON Object Properties\n\n| Name | Type | Description | Example |\n| --- | --- | --- | --- |\n| `toMobileNumber` | string | The mobile number this sms will be sent to. It can be a comma-separated or semi-colon separated list of mobile numbers. | `306972669766` or `306972669766;306972669764` |\n| `toGroup` | string | The name of the Group this sms will be sent to. Group is one of your groups registered in the application. You can specify multiple groups separated using `;` | `High Valued Customers;Promotion Customers` |\n| `fromLabel` | string | The sender identifier. One of the sender ids that you have registered in the application. | `BOXNOW` |\n| `smsBody` | string | The SMS content. | `Hello! You have just won 5 Euro Gift Card!` |\n| `clientRequestId` | string | The client request id that will be attached to the sms request. This is optional. It can be used for searching/reporting. It's a business-level value that makes sense to your own business. The application does not process it at all, other than for indexing the message. | `9543212` |\n| `callbackWhenProcessedFlag` | boolean | Default `false`. When `true`, SMS server will call the callback api endpoint to report back the status of delivery. You must have set up a callback api in the application settings. | `true` |\n| `simulateSendFlag` | boolean | Default `false`. When `true`, the SMS will not actually be delivered. This can be used to test the integration without consuming credits. | `false` |\n| `scheduledAt` | string | You can schedule a delivery to take place in the future. **Important:** It should not be earlier than 5 minutes in the future. It needs to be ISO8601 with Time Zone representation of a date and time | `\"2024-12-13T11:34:29+02:00\"` |\n\n### HTTP Response\n\n#### Success\n\nOn successful sending of the HTTP request, you will get back a standard HTTP response code with value `200`. It will have\na body that will be a JSON object encoded as string. The JSON object will have the following structure:\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `result` | object | JSON root level object. All the other properties, below, they are properties of this object. |\n| `result.username` | string | The username identified by the API key used in the incoming SMS request. |\n| `result.resultCode` | string | It will have the value \"1\" on success. Different from \"1\" on failure. |\n| `result.resultDescription` | string | It will have the value \"SUCCESS\" on success. Different from \"SUCCESS\" on failure. |\n| `result.clientRequestId` | string | It will be either `null` or it will have the value of the `clientRequestId` sent in the incoming SMS request. |\n| `result.smsServerRequestId` | string | A unique identifier from the SMS server side. This uniquely identifies your SMS request. It will value `null` if you schedule the SMS in the future. |\n| `result.smsRequestScheduleId` | string | A unique identifier of the schedule created when you schedule an SMS to be delivered in the future. It will have value `null` if you don't schedule. |\n\n#### Error\n\nWith regards to error handling, read the corresponding **Errors** section above.\n",
        "operationId": "sendSms",
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -v -X POST 'https://sms-api.rayo.gr/v1/send_sms' \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json' \\\n  -H 'Authorization: Bearer 5a2a5816-5f32-4234-a9a1-7d59986c06a5' \\\n  -d '{\n    \"toMobileNumber\":\"6972669766\",\n    \"fromLabel\":\"306972669766\",\n    \"smsBody\":\"test message\"\n  }'\n"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "# This Ruby example uses Rest Client library (https://github.com/rest-client/rest-client).\n# You can use any other Ruby library that can construct standard HTTPS requests.\n#\nrequire 'rest-client'\n\napi_key = '5a2a5816-5f32-4234-a9a1-7d59986c06a5'\nsms_body = 'test message'\n\nurl = 'https://sms-api.rayo.gr/v1/send_sms'\npayload = {\n  toMobileNumber: '6972669766',\n  fromLabel: '306972669766',\n  smsBody: sms_body\n}.to_json\nheaders = {\n  'Content-Type' => 'application/json',\n  'Accept' => 'application/json',\n  'Authorization' => \"Bearer #{api_key}\"\n}\n\nresponse = RestClient.post url, payload, headers\n"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendSmsRequest"
              },
              "examples": {
                "mobileNumber": {
                  "summary": "Send to one mobile number",
                  "value": {
                    "toMobileNumber": "6972669766",
                    "fromLabel": "306972669766",
                    "smsBody": "test message"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "On successful sending of the HTTP request, you will get back a standard HTTP response code with value `200`. It will have\na body that will be a JSON object encoded as string. The JSON object will have the following structure:\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `result` | object | JSON root level object. All the other properties, below, they are properties of this object. |\n| `result.username` | string | The username identified by the API key used in the incoming SMS request. |\n| `result.resultCode` | string | It will have the value \"1\" on success. Different from \"1\" on failure. |\n| `result.resultDescription` | string | It will have the value \"SUCCESS\" on success. Different from \"SUCCESS\" on failure. |\n| `result.clientRequestId` | string | It will be either `null` or it will have the value of the `clientRequestId` sent in the incoming SMS request. |\n| `result.smsServerRequestId` | string | A unique identifier from the SMS server side. This uniquely identifies your SMS request. It will value `null` if you schedule the SMS in the future. |\n| `result.smsRequestScheduleId` | string | A unique identifier of the schedule created when you schedule an SMS to be delivered in the future. It will have value `null` if you don't schedule. |\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendSmsSuccessResponse"
                },
                "example": {
                  "result": {
                    "username": "user1",
                    "resultCode": "1",
                    "resultDescription": "SUCCESS",
                    "clientRequestId": "932831",
                    "smsServerRequestId": "cc479845-0f15-4ae7-b645-6ef6489868c1",
                    "smsRequestScheduleId": "e0b107da-669a-40f5-b4d0-24fc70409307"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/v1/balance_in_credits": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Get Balance in Credits",
        "description": "This is the API that will return your current balance in credits. It is a `GET` request to the path\n`/balance_in_credits`.\n\nThe HTTP Request should have the following headers, as a minimum requirement:\n\n### Request Headers\n\n| Name | Value |\n| --- | --- |\n| Accept | application/json |\n| Authorization | Bearer [your API key here] |\n\nFor the `Authorization` header above, replace the `[your API key here]` with your\nown API key.\n\n### HTTP Response\n\n#### Success\n\nOn successful return of the HTTP request, you will get back a standard HTTP response code with value `200`. It will have\na body that will be a JSON object encoded as string. The JSON object will have the following structure:\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `request_id` | string | Unique identifier of your request. |\n| `balance` | object | Object with details about your balance. |\n| `balance.credits` | number | The credits remaining in your balance. |\n\n#### Error\n\nWith regards to error handling, read the corresponding **Errors** section above.\n",
        "operationId": "getBalanceInCredits",
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -v -X GET 'https://sms-api.rayo.gr/v1/balance_in_credits' \\\n  -H 'Accept: application/json' \\\n  -H 'Authorization: Bearer 5a2a5816-5f32-4234-a9a1-7d59986c06a5'\n"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "# This Ruby example uses Rest Client library (https://github.com/rest-client/rest-client).\n# You can use any other Ruby library that can construct standard HTTPS requests.\n#\nrequire 'rest-client'\n\napi_key = '5a2a5816-5f32-4234-a9a1-7d59986c06a5'\n\nurl = 'https://sms-api.rayo.gr/v1/balance_in_credits'\nheaders = {\n  'Accept' => 'application/json',\n  'Authorization' => \"Bearer #{api_key}\"\n}\n\nresponse = RestClient.get url, headers\n"
          }
        ],
        "responses": {
          "200": {
            "description": "On successful return of the HTTP request, you will get back a standard HTTP response code with value `200`. It will have\na body that will be a JSON object encoded as string. The JSON object will have the following structure:\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `request_id` | string | Unique identifier of your request. |\n| `balance` | object | Object with details about your balance. |\n| `balance.credits` | number | The credits remaining in your balance. |\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BalanceResponse"
                },
                "example": {
                  "request_id": "7d6939ec-7213-4bf9-9b41-2902b54cfa71",
                  "balance": {
                    "credits": 4240
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/v1/check_status": {
      "get": {
        "tags": [
          "Delivery status"
        ],
        "summary": "Check Status of Sms Request",
        "description": "This is the API that will return back the status of an SMS Request. Note that\nan SMS Request might correspond to multiple outgoing SMS messages. This\nAPI request will return the status of each one of the outgoing message\nthat belongs to the specified SMS request.\n\nThe SMS Request can be located by one, but not both, of the following:\n\n1. `clientRequestId`. This should be the `clientRequestId` that you specified when\nyou sent the request.\n2. `smsServerRequestId`. This should be the `smsServerRequestId` that you got back\nin the response of the send request.\n\nThe HTTP Request should have the following headers, as a minimum requirement:\n\n### Request Headers\n\n| Name | Value |\n| --- | --- |\n| Accept | application/json |\n| Authorization | Bearer [your API key here] |\n\nFor the `Authorization` header above, replace the `[your API key here]` with your\nown API key.\n\n### HTTP Response\n\n#### Success\n\nOn successful return of the HTTP request, you will get back a standard HTTP response code with value `200`. It will have\na body that will be a JSON object encoded as string. The JSON object will have the following structure:\n\nIt will be an `Array` of objects of the following structure.\n\n> Note that an SMS Request might correspond to multiple outgoing SMS messages. This\n> API request will return the status of each one of the outgoing message\n> that belongs to the specified SMS request.\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `smsServerRequestId` | string | The SMS Server Request Id of the original SMS Request |\n| `clientRequestId` | string | The Client Request Id that you have assigned to the SMS Request |\n| `internalSmsOutDeliveryId` | string | Unique identifier of the outgoing SMS |\n| `mobileNumber` | string | The destination mobile number for the specific outgoing SMS |\n| `status` | string | The delivery status of the outgoing SMS. See below the table with possible values |\n\n##### SMS Delivery Status\n\nThe possible delivery status values are:\n\n| Status | Explanation |\n| --- | --- |\n| `new` | Initial Status. |\n| `temp_locked` | Internal Status. |\n| `processing_error` | Failed to Process the Request. Message was not sent out. We will not retry to send it out. |\n| `failure` | We tried to send the message out multiple times, but we failed all of them. |\n| `sent` | The message was sent out. |\n| `error` | There is a temporary error. We will try to send the message again. |\n| `delivered` | Message was delivered to the handset. |\n| `not_delivered` | Message was sent out, but it was not delivered to the handset. |\n| `unknown_delivery` | Message was sent out, but we don't know whether it was delivered or not. |\n\nAn outgoing message that leaves our network is on status `sent`.\nIf it is delivered to the handset, it will be on status `delivered`.\nIf it cannot be delivered by the mobile network, it will be on\nstatus `not_delivered`. If we don't get a feedback from the\ndevice whether the message has been delivered or not after a day,\nit will be turned to `unknown_delivery`.\n\n#### Error\n\nWith regards to error handling, read the corresponding **Errors** section above.\n\nNote, that if you specify a `clientRequestId` and/or an `smsServerRequestId` that does not match\nany SMS Request in your account, the API request will return HTTP Response Status code `404` and\nthe response body will be:\n\n```json\n{\n  \"error\": \"No record(s) found\"\n}\n```\n",
        "operationId": "checkSmsRequestStatus",
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "# Get the status of an SMS request by Client Request Id (clientRequestId).\n#\ncurl -v -X GET 'https://sms-api.rayo.gr/v1/check_status?clientRequestId=<a-client-request-id>' \\\n  -H 'Accept: application/json' \\\n  -H 'Authorization: Bearer 5a2a5816-5f32-4234-a9a1-7d59986c06a5'\n\n# Get the status of an SMS request by SMS Server Request Id (smsServerRequestId).\n#\ncurl -v -X GET 'https://sms-api.rayo.gr/v1/check_status?smsServerRequestId=<an-sms-server-request-id>' \\\n  -H 'Accept: application/json' \\\n  -H 'Authorization: Bearer 5a2a5816-5f32-4234-a9a1-7d59986c06a5'\n"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "# This Ruby example uses Rest Client library (https://github.com/rest-client/rest-client).\n# You can use any other Ruby library that can construct standard HTTPS requests.\n#\nrequire 'rest-client'\n\napi_key = '5a2a5816-5f32-4234-a9a1-7d59986c06a5'\n\n# Get the status of an SMS request by Client Request Id (clientRequestId).\n#\nurl = 'https://sms-api.rayo.gr/v1/check_status?clientRequestId=<a-client-request-id>'\nheaders = {\n  'Accept' => 'application/json',\n  'Authorization' => \"Bearer #{api_key}\"\n}\n\nresponse = RestClient.get url, headers\n\n# Get the status of an SMS request by SMS Server Request Id (smsServerRequestId).\n#\nurl = 'https://sms-api.rayo.gr/v1/check_status?smsServerRequestId=<an-sms-server-request-id>'\nheaders = {\n  'Accept' => 'application/json',\n  'Authorization' => \"Bearer #{api_key}\"\n}\n\nresponse = RestClient.get url, headers\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientRequestId"
          },
          {
            "$ref": "#/components/parameters/SmsServerRequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "On successful return of the HTTP request, you will get back a standard HTTP response code with value `200`. It will have\na body that will be a JSON object encoded as string. It will be an `Array` of objects of the following structure:\n\n| Name | Type | Description |\n| --- | --- | --- |\n| `smsServerRequestId` | string | The SMS Server Request Id of the original SMS Request |\n| `clientRequestId` | string | The Client Request Id that you have assigned to the SMS Request |\n| `internalSmsOutDeliveryId` | string | Unique identifier of the outgoing SMS |\n| `mobileNumber` | string | The destination mobile number for the specific outgoing SMS |\n| `status` | string | The delivery status of the outgoing SMS. |\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SmsDeliveryStatus"
                  }
                },
                "example": [
                  {
                    "smsServerRequestId": "1396522",
                    "clientRequestId": "20240316203045",
                    "internalSmsOutDeliveryId": "1065597",
                    "mobileNumber": "306972669766",
                    "status": "delivered"
                  }
                ]
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "If you specify a `clientRequestId` and/or an `smsServerRequestId` that does not match\nany SMS Request in your account, the API request will return HTTP Response Status code `404`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundResponse"
                },
                "example": {
                  "error": "No record(s) found"
                }
              }
            }
          },
          "5XX": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/v1/sms_request_schedules/{id}": {
      "delete": {
        "tags": [
          "Schedules"
        ],
        "summary": "Deleting a schedule",
        "description": "You can delete a schedule that you have created. This is only possible as long as the\nschedule has not fired.\n\nYou have to pass the correct authorization headers as described in the Authentication section.\n",
        "operationId": "deleteSmsRequestSchedule",
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "# Delete a schedule using the schedule identifier\n#\ncurl -v -X DELETE 'https://sms-api.rayo.gr/v1/sms_request_schedules/e0b107da-669a-40f5-b4d0-24fc70409307' \\\n  -H 'Accept: application/json' \\\n  -H 'Authorization: Bearer 5a2a5816-5f32-4234-a9a1-7d59986c06a5'\n"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "# This Ruby example uses Rest Client library (https://github.com/rest-client/rest-client).\n# You can use any other Ruby library that can construct standard HTTPS requests.\n#\nrequire 'rest-client'\n\napi_key = '5a2a5816-5f32-4234-a9a1-7d59986c06a5'\n\n# Delete a schedule using the schedule identifier\n#\nurl = 'https://sms-api.rayo.gr/v1/sms_request_schedules/<schedule-identifier>'\nheaders = {\n  'Accept' => 'application/json',\n  'Authorization' => \"Bearer #{api_key}\"\n}\n\nresponse = RestClient.delete url, headers\n"
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identifier returned as `smsRequestScheduleId` when the SMS was scheduled.",
            "schema": {
              "type": "string"
            },
            "example": "e0b107da-669a-40f5-b4d0-24fc70409307"
          }
        ],
        "responses": {
          "default": {
            "description": "The public API documentation does not define this response contract."
          }
        }
      }
    }
  },
  "webhooks": {
    "deliveryStatusUpdate": {
      "get": {
        "summary": "Delivery Updates via a Callback Webhook (GET)",
        "description": "You can set up your own endpoint which Rayo SMS API will call every time there is an update\non the status of an outgoing SMS. However, in order for this to take place, you need to have set the value\nof parameter `callbackWhenProcessedFlag` to `true` when sending an SMS.\n\nGo to `Actions -> Settings` and locate the section `Callbacks API`. The Callback URL is a service offered by\nRayo SMS. It gives you the ability to receive delivery reports via a specific URL.\nYou specify the URL, as well as whether you want the HTTP request to be a `GET` or a `POST` request.\n\nMoreover, each call the Rayo SMS API does to your service as a callback, it will have\na signature that you can check to make sure that the request is legitimate and it is coming from our\nservers. This signature is delivered in the HTTP Request Header `Rayo-SMS-Signature`.\n\nWhenever we need to update the status of a message, we will be calling your callback endpoint.\nIf you prefer the HTTP Verb to be `GET` then the parameters alongside their values are being URL-encoded.\n\n### Parameters/Attributes of payload\n\nThe status of the message will be sent back to your endpoint alongside the following parameters:\n\n| Parameter Name | Type | Description |\n| --- | --- | --- |\n| `smsServerRequestId` | string | This is the unique identifier that matches the initial request to send an SMS. Note that each one request, may be corresponding to more than one SMS sent out. For example, if your request refers to a group with more than one member |\n| `clientRequestId` | string | This is the identifier that you have provided when you sent your initial request. Since this parameter is optional on requests, then it may not be present on the delivery reports. |\n| `internalSmsOutDeliveryId` | string | This is unique identifier for each SMS sent out. It is internally generated. |\n| `senderId` | string | This is the Sender Identifier that has been used to send the SMS out. |\n| `mobileNumber` | string | This is the mobile number that the SMS has been sent out to. |\n| `status` | string | This is the delivery status of the outgoing SMS. Read about the possible values above. |\n| `errorDescription` | string | Usually it contains `no error` but it may contain an error description if the status implies an error. |\n| `requestTimestamp` | string | The timestamp, in iso8601 standard, the SMS request was received by our systems. |\n| `lastStatusUpdatedTimestamp` | string | The timestamp of the last status update. |\n\n### Signature of the Callback Request\n\n1. Take the signature key that you have set up in the Application Settings.\n2. If the callback request is a `POST` request, take the `Content-Type` header value from the request. Otherwise,\nconsider the content type equal to a blank string `\"\"`, even if it might have a value.\n3. Take the request path.\n4. Take the payload. For `POST` requests it is the body of the request. For `GET` requests it is the\nquery string.\n5. Take the value of the request header `Date`.\n6. Create a comma-separated list of the values for:\n   - request method lower cased, i.e. `get` or `post`\n   - content type\n   - request path\n   - payload\n   - date header value\n7. Using the string you created in the previous step and the signing secret create a SHA256 hex digest,\nwhere the signing secret is used as a key and the string as the data.\n8. Compare the resulting SHA256 hex digest to the incoming signature. They should match.\n",
        "operationId": "receiveDeliveryStatusUpdateByGet",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/CallbackSignature"
          },
          {
            "$ref": "#/components/parameters/CallbackDate"
          },
          {
            "$ref": "#/components/parameters/CallbackSmsServerRequestId"
          },
          {
            "$ref": "#/components/parameters/CallbackClientRequestId"
          },
          {
            "$ref": "#/components/parameters/CallbackInternalSmsOutDeliveryId"
          },
          {
            "$ref": "#/components/parameters/CallbackSenderId"
          },
          {
            "$ref": "#/components/parameters/CallbackMobileNumber"
          },
          {
            "$ref": "#/components/parameters/CallbackStatus"
          },
          {
            "$ref": "#/components/parameters/CallbackErrorDescription"
          },
          {
            "$ref": "#/components/parameters/CallbackRequestTimestamp"
          },
          {
            "$ref": "#/components/parameters/CallbackLastStatusUpdatedTimestamp"
          }
        ],
        "responses": {
          "default": {
            "description": "Response returned by the customer callback endpoint."
          }
        }
      },
      "post": {
        "summary": "Delivery Updates via a Callback Webhook (POST)",
        "description": "You can set up your own endpoint which Rayo SMS API will call every time there is an update\non the status of an outgoing SMS. However, in order for this to take place, you need to have set the value\nof parameter `callbackWhenProcessedFlag` to `true` when sending an SMS.\n\nGo to `Actions -> Settings` and locate the section `Callbacks API`. The Callback URL is a service offered by\nRayo SMS. It gives you the ability to receive delivery reports via a specific URL.\nYou specify the URL, as well as whether you want the HTTP request to be a `GET` or a `POST` request.\n\nMoreover, each call the Rayo SMS API does to your service as a callback, it will have\na signature that you can check to make sure that the request is legitimate and it is coming from our\nservers. This signature is delivered in the HTTP Request Header `Rayo-SMS-Signature`.\n\nWhenever we need to update the status of a message, we will be calling your callback endpoint.\nIf you specify the HTTP Verb to be `POST` then the parameters will be delivered to you\nin the body of the request encoded as a JSON object.\n\n### Parameters/Attributes of payload\n\nThe status of the message will be sent back to your endpoint alongside the following parameters:\n\n| Parameter Name | Type | Description |\n| --- | --- | --- |\n| `smsServerRequestId` | string | This is the unique identifier that matches the initial request to send an SMS. Note that each one request, may be corresponding to more than one SMS sent out. For example, if your request refers to a group with more than one member |\n| `clientRequestId` | string | This is the identifier that you have provided when you sent your initial request. Since this parameter is optional on requests, then it may not be present on the delivery reports. |\n| `internalSmsOutDeliveryId` | string | This is unique identifier for each SMS sent out. It is internally generated. |\n| `senderId` | string | This is the Sender Identifier that has been used to send the SMS out. |\n| `mobileNumber` | string | This is the mobile number that the SMS has been sent out to. |\n| `status` | string | This is the delivery status of the outgoing SMS. Read about the possible values above. |\n| `errorDescription` | string | Usually it contains `no error` but it may contain an error description if the status implies an error. |\n| `requestTimestamp` | string | The timestamp, in iso8601 standard, the SMS request was received by our systems. |\n| `lastStatusUpdatedTimestamp` | string | The timestamp of the last status update. |\n\n### Signature of the Callback Request\n\n1. Take the signature key that you have set up in the Application Settings.\n2. If the callback request is a `POST` request, take the `Content-Type` header value from the request. Otherwise,\nconsider the content type equal to a blank string `\"\"`, even if it might have a value.\n3. Take the request path.\n4. Take the payload. For `POST` requests it is the body of the request. For `GET` requests it is the\nquery string.\n5. Take the value of the request header `Date`.\n6. Create a comma-separated list of the values for:\n   - request method lower cased, i.e. `get` or `post`\n   - content type\n   - request path\n   - payload\n   - date header value\n7. Using the string you created in the previous step and the signing secret create a SHA256 hex digest,\nwhere the signing secret is used as a key and the string as the data.\n8. Compare the resulting SHA256 hex digest to the incoming signature. They should match.\n",
        "operationId": "receiveDeliveryStatusUpdateByPost",
        "security": [],
        "x-codeSamples": [
          {
            "lang": "Ruby",
            "label": "Rails signature verification for GET and POST callbacks",
            "source": "require 'openssl'\n\nclass CallbacksController < ApplicationController\n  skip_before_action :verify_authenticity_token\n\n  def callback\n    incoming_signature = request.headers['Rayo-SMS-Signature']\n    signing_secret = ENV.fetch('SIGNATURE_KEY')\n\n    if valid_signature?(incoming_signature, signing_secret)\n      render json: { message: 'Signature valid' }, status: :ok\n    else\n      render json: { message: 'Invalid signature' }, status: :unauthorized\n    end\n  end\n\n  private\n\n  def valid_signature?(incoming_signature, signing_secret)\n    request_method = request.method.downcase\n    content_type = request.post? ? request.headers['Content-Type'].to_s : ''\n    request_path = request.path\n    payload = request.post? ? request.body.read : request.query_string\n    date_header = request.headers['Date']\n\n    string_to_sign = [\n      request_method,\n      content_type,\n      request_path,\n      payload,\n      date_header\n    ].join(',')\n\n    digest = OpenSSL::HMAC.hexdigest(\n      'SHA256',\n      signing_secret,\n      string_to_sign\n    )\n\n    ActiveSupport::SecurityUtils.secure_compare(\n      digest,\n      incoming_signature\n    )\n  end\nend\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/CallbackSignature"
          },
          {
            "$ref": "#/components/parameters/CallbackDate"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeliveryStatusCallback"
              }
            }
          }
        },
        "responses": {
          "default": {
            "description": "Response returned by the customer callback endpoint."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "An active API key managed in **Actions -> Settings**. Multiple keys can\nremain active during key rotation. Treat API keys as confidential.\n"
      }
    },
    "parameters": {
      "ClientRequestId": {
        "name": "clientRequestId",
        "in": "query",
        "required": false,
        "description": "Business identifier assigned to the SMS request by the client. Supply\nthis parameter or `smsServerRequestId`, but not both.\n",
        "schema": {
          "type": "string"
        },
        "example": "20240316203045"
      },
      "SmsServerRequestId": {
        "name": "smsServerRequestId",
        "in": "query",
        "required": false,
        "description": "Unique SMS request identifier returned by the server. Supply this\nparameter or `clientRequestId`, but not both.\n",
        "schema": {
          "type": "string"
        },
        "example": "cc479845-0f15-4ae7-b645-6ef6489868c1"
      },
      "CallbackSignature": {
        "name": "Rayo-SMS-Signature",
        "in": "header",
        "required": true,
        "description": "HMAC-SHA256 hex digest used to verify that the callback came from Rayo SMS.",
        "schema": {
          "type": "string"
        }
      },
      "CallbackDate": {
        "name": "Date",
        "in": "header",
        "required": true,
        "description": "Date header included as the final value in the callback signing string.",
        "schema": {
          "type": "string"
        }
      },
      "CallbackSmsServerRequestId": {
        "name": "smsServerRequestId",
        "in": "query",
        "required": true,
        "description": "This is the unique identifier that matches the initial request to send an SMS. Note that each one request, may be corresponding to more than one SMS sent out. For example, if your request refers to a group with more than one member",
        "schema": {
          "type": "string"
        }
      },
      "CallbackClientRequestId": {
        "name": "clientRequestId",
        "in": "query",
        "required": false,
        "description": "This is the identifier that you have provided when you sent your initial request. Since this parameter is optional on requests, then it may not be present on the delivery reports.",
        "schema": {
          "type": "string"
        }
      },
      "CallbackInternalSmsOutDeliveryId": {
        "name": "internalSmsOutDeliveryId",
        "in": "query",
        "required": true,
        "description": "This is unique identifier for each SMS sent out. It is internally generated.",
        "schema": {
          "type": "string"
        }
      },
      "CallbackSenderId": {
        "name": "senderId",
        "in": "query",
        "required": true,
        "description": "This is the Sender Identifier that has been used to send the SMS out.",
        "schema": {
          "type": "string"
        }
      },
      "CallbackMobileNumber": {
        "name": "mobileNumber",
        "in": "query",
        "required": true,
        "description": "This is the mobile number that the SMS has been sent out to.",
        "schema": {
          "type": "string"
        }
      },
      "CallbackStatus": {
        "name": "status",
        "in": "query",
        "required": true,
        "description": "This is the delivery status of the outgoing SMS. Read about the possible values above.",
        "schema": {
          "$ref": "#/components/schemas/DeliveryStatus"
        }
      },
      "CallbackErrorDescription": {
        "name": "errorDescription",
        "in": "query",
        "required": true,
        "description": "Usually it contains `no error` but it may contain an error description if the status implies an error.",
        "schema": {
          "type": "string"
        }
      },
      "CallbackRequestTimestamp": {
        "name": "requestTimestamp",
        "in": "query",
        "required": true,
        "description": "The timestamp, in iso8601 standard, the SMS request was received by our systems.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "CallbackLastStatusUpdatedTimestamp": {
        "name": "lastStatusUpdatedTimestamp",
        "in": "query",
        "required": true,
        "description": "The timestamp of the last status update.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "You have provided a non-existing or inactive API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "When the data in the request are invalid. For example, for an SMS request, the `fromLabel` does not belong to you.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServerError": {
        "description": "Indicates an error that took place on the server side. Rayo SMS developers are automatically notified for such errors and will immediately try to remedy this situation. If your problem persists, use the contact form on [Rayo SMS Web site](https://www.rayo.gr) to report the problem.\n\nIn case you get an error in the range `500-599`, we are suggesting that you retry your request. Maybe with an increasing wait time in-between the retries. You can retry up to a certain amount of times before you give up.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "SendSmsRequest": {
        "type": "object",
        "description": "SMS request payload.",
        "required": [
          "fromLabel",
          "smsBody"
        ],
        "properties": {
          "toMobileNumber": {
            "type": "string",
            "description": "The mobile number this sms will be sent to. It can be a comma-separated or semi-colon separated list of mobile numbers.",
            "examples": [
              "306972669766",
              "306972669766;306972669764"
            ]
          },
          "toGroup": {
            "type": "string",
            "description": "The name of the Group this sms will be sent to. Group is one of your groups registered in the application. You can specify multiple groups separated using `;`",
            "example": "High Valued Customers;Promotion Customers"
          },
          "fromLabel": {
            "type": "string",
            "description": "The sender identifier. One of the sender ids that you have registered in the application.",
            "example": "BOXNOW"
          },
          "smsBody": {
            "type": "string",
            "description": "The SMS content.",
            "example": "Hello! You have just won 5 Euro Gift Card!"
          },
          "clientRequestId": {
            "type": "string",
            "description": "The client request id that will be attached to the sms request. This is optional. It can be used for searching/reporting. It's a business-level value that makes sense to your own business. The application does not process it at all, other than for indexing the message.",
            "example": "9543212"
          },
          "callbackWhenProcessedFlag": {
            "type": "boolean",
            "default": false,
            "description": "Default `false`. When `true`, SMS server will call the callback api endpoint to report back the status of delivery. You must have set up a callback api in the application settings."
          },
          "simulateSendFlag": {
            "type": "boolean",
            "default": false,
            "description": "Default `false`. When `true`, the SMS will not actually be delivered. This can be used to test the integration without consuming credits."
          },
          "scheduledAt": {
            "type": "string",
            "format": "date-time",
            "description": "You can schedule a delivery to take place in the future. **Important:** It should not be earlier than 5 minutes in the future. It needs to be ISO8601 with Time Zone representation of a date and time",
            "example": "2024-12-13T11:34:29+02:00"
          }
        }
      },
      "SendSmsSuccessResponse": {
        "type": "object",
        "required": [
          "result"
        ],
        "properties": {
          "result": {
            "type": "object",
            "description": "JSON root level object. All the other properties, below, they are properties of this object.",
            "required": [
              "username",
              "resultCode",
              "resultDescription",
              "clientRequestId",
              "smsServerRequestId",
              "smsRequestScheduleId"
            ],
            "properties": {
              "username": {
                "type": "string",
                "description": "The username identified by the API key used in the incoming SMS request."
              },
              "resultCode": {
                "type": "string",
                "const": "1",
                "description": "It will have the value \"1\" on success. Different from \"1\" on failure."
              },
              "resultDescription": {
                "type": "string",
                "const": "SUCCESS",
                "description": "It will have the value \"SUCCESS\" on success. Different from \"SUCCESS\" on failure."
              },
              "clientRequestId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "It will be either `null` or it will have the value of the `clientRequestId` sent in the incoming SMS request."
              },
              "smsServerRequestId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A unique identifier from the SMS server side. This uniquely identifies your SMS request. It will value `null` if you schedule the SMS in the future."
              },
              "smsRequestScheduleId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "A unique identifier of the schedule created when you schedule an SMS to be delivered in the future. It will have value `null` if you don't schedule."
              }
            }
          }
        }
      },
      "BalanceResponse": {
        "type": "object",
        "required": [
          "request_id",
          "balance"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Unique identifier of your request."
          },
          "balance": {
            "type": "object",
            "description": "Object with details about your balance.",
            "required": [
              "credits"
            ],
            "properties": {
              "credits": {
                "type": "number",
                "description": "The credits remaining in your balance."
              }
            }
          }
        }
      },
      "SmsDeliveryStatus": {
        "type": "object",
        "required": [
          "smsServerRequestId",
          "clientRequestId",
          "internalSmsOutDeliveryId",
          "mobileNumber",
          "status"
        ],
        "properties": {
          "smsServerRequestId": {
            "type": "string",
            "description": "The SMS Server Request Id of the original SMS Request"
          },
          "clientRequestId": {
            "type": "string",
            "description": "The Client Request Id that you have assigned to the SMS Request"
          },
          "internalSmsOutDeliveryId": {
            "type": "string",
            "description": "Unique identifier of the outgoing SMS"
          },
          "mobileNumber": {
            "type": "string",
            "description": "The destination mobile number for the specific outgoing SMS"
          },
          "status": {
            "$ref": "#/components/schemas/DeliveryStatus"
          }
        }
      },
      "DeliveryStatus": {
        "type": "string",
        "description": "The delivery status of the outgoing SMS:\n\n- `new`: Initial Status.\n- `temp_locked`: Internal Status.\n- `processing_error`: Failed to Process the Request. Message was not sent out. We will not retry to send it out.\n- `failure`: We tried to send the message out multiple times, but we failed all of them.\n- `sent`: The message was sent out.\n- `error`: There is a temporary error. We will try to send the message again.\n- `delivered`: Message was delivered to the handset.\n- `not_delivered`: Message was sent out, but it was not delivered to the handset.\n- `unknown_delivery`: Message was sent out, but we don't know whether it was delivered or not.\n",
        "enum": [
          "new",
          "temp_locked",
          "processing_error",
          "failure",
          "sent",
          "error",
          "delivered",
          "not_delivered",
          "unknown_delivery"
        ]
      },
      "DeliveryStatusCallback": {
        "type": "object",
        "required": [
          "smsServerRequestId",
          "internalSmsOutDeliveryId",
          "senderId",
          "mobileNumber",
          "status",
          "errorDescription",
          "requestTimestamp",
          "lastStatusUpdatedTimestamp"
        ],
        "properties": {
          "smsServerRequestId": {
            "type": "string",
            "description": "This is the unique identifier that matches the initial request to send an SMS. Note that each one request, may be corresponding to more than one SMS sent out. For example, if your request refers to a group with more than one member"
          },
          "clientRequestId": {
            "type": "string",
            "description": "This is the identifier that you have provided when you sent your initial request. Since this parameter is optional on requests, then it may not be present on the delivery reports."
          },
          "internalSmsOutDeliveryId": {
            "type": "string",
            "description": "This is unique identifier for each SMS sent out. It is internally generated."
          },
          "senderId": {
            "type": "string",
            "description": "This is the Sender Identifier that has been used to send the SMS out."
          },
          "mobileNumber": {
            "type": "string",
            "description": "This is the mobile number that the SMS has been sent out to."
          },
          "status": {
            "$ref": "#/components/schemas/DeliveryStatus"
          },
          "errorDescription": {
            "type": "string",
            "description": "Usually it contains `no error` but it may contain an error description if the status implies an error."
          },
          "requestTimestamp": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp, in iso8601 standard, the SMS request was received by our systems."
          },
          "lastStatusUpdatedTimestamp": {
            "type": "string",
            "format": "date-time",
            "description": "The timestamp of the last status update."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Error responses can include further details in their body. Fields may\nbe null when the request could not be associated with an account or SMS\nrequest.\n",
        "properties": {
          "result": {
            "type": "object",
            "properties": {
              "username": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "resultCode": {
                "type": "string",
                "description": "A value other than `1` indicates failure."
              },
              "resultDescription": {
                "type": "string",
                "description": "Description of the failure."
              },
              "clientRequestId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "smsServerRequestId": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "error": {
            "type": "string"
          }
        }
      },
      "NotFoundResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}