UNPKG

openapi-directory

Version:

Building & bundling https://github.com/APIs-guru/openapi-directory for easy use from JS

1 lines 65.2 kB
{"openapi":"3.0.0","servers":[{"url":"https://api.bulksms.com/v1"}],"info":{"description":"## Overview\n\nThe JSON REST API allows you to submit and receive [BulkSMS](https://www.bulksms.com/) messages. You can also get access to past messages and see your account profile.\n\nThe base URL to use for this service is `https://api.bulksms.com/v1`. The base URL cannot be used on its own; you must append a path that identifies an operation and you may have to specify some path parameters as well.\n\n[Click here](/developer/) to go to the main BulkSMS developer site.\n\nIn order to give you an idea on how the API can be used, some JSON snippets are provided below. Have a look at the [messages section](#tag/Message) for more information.\n\nProbably the most simple example\n\n```\n{\n \"to\": \"+27001234567\",\n \"body\": \"Hello World!\"\n}\n```\n\n\nYou can send unicode automatically using the `auto-unicode` query parameter. \nAlternatively, you can specify `UNICODE` for the `encoding` property in the request body. \nPlease note: when `auto-unicode` is specified and the value of the `encoding` property is `UNICODE`, the message will always be sent as `UNICODE`.\n\nHere is an example that sets the `encoding` explicitly\n\n```\n{\n \"to\": \"+27001234567\",\n \"body\": \"Dobrá práce! Jak se máš?\",\n \"encoding\": \"UNICODE\"\n}\n```\n\nYou can also specify a from number\n\n```\n{\n \"from\": \"+27007654321\",\n \"to\": \"+27001234567\",\n \"body\": \"Hello World!\"\n}\n```\n\nSimilar to above, but repliable\n\n```\n{\n \"from\": { \"type\": \"REPLIABLE\" },\n \"to\": \"+27001234567\",\n \"body\": \"Hello World!\"\n}\n```\n\nA message to a group called Everyone\n\n```\n{\n \"to\": { \"type\": \"GROUP\", \"name\": \"Everyone\" },\n \"body\": \"Hello World!\"\n}\n```\n\nA message to multiple recipients\n\n```\n{\n \"to\": [\"+27001234567\", \"+27002345678\", \"+27003456789\"],\n \"body\": \"Happy Holidays!\"\n}\n```\n\nSending more than one message in the same request\n\n```\n[\n {\n \"to\": \"+27001234567\",\n \"body\": \"Hello World!\"\n },\n {\n \"to\": \"+27002345678\",\n \"body\": \"Hello Universe!\"\n }\n]\n```\n\n**The insecure base URL `http://api.bulksms.com/v1` is deprecated** and may in future result in a `301` redirect response, or insecure requests may be rejected outright. Please use the secure (`https`) URI above.\n\n### HTTP Content Type\n\nAll API methods expect requests to supply a `Content-Type` header with the value `application/json`. All responses will have the `Content-Type` header set to `application/json`.\n\n### JSON Formatting\n\nYou are advised to format your JSON resources according to strict JSON format rules. While the API does attempt to parse strictly invalid JSON documents, doing so may lead to incorrect interpretation and unexpected results.\n\nGood JSON libraries will produce valid JSON suitable for submission, but if you are manually generating the JSON text, be careful to follow the JSON format. This include correct escaping of control characters and double quoting of property names.\n\nSee the [JSON specification](https://tools.ietf.org/html/rfc4627) for further information.\n\n### Date Formatting\n\nDates are formatted according to ISO-8601, such as `1970-01-01T10:00:00+01:00` for 1st January 1970, 10AM UTC+1.\n\nSee the [Wikipedia ISO 8601 reference](https://en.wikipedia.org/wiki/ISO_8601) for further information.\n\nSpecifically, calendar dates are formatted with the 'extended' format `YYYY-MM-DD`. Basic format, week dates and ordinal dates are not supported. Times are also formatted in the 'extended' format `hh:mm:ss`. Hours, minutes and seconds are mandatory. Offset from UTC must be provided; this is to ensure that there is no misunderstanding regarding times provided to the API.\n\nThe format we look for is `yyyy-MM-ddThh:mm:ss[Z|[+-]hh:mm]`\n\nExamples of valid date/times are`2011-12-31T12:00:00Z` `2011-12-31T12:00:00+02:00`\n\n### Entity Format Modifications\n\nIt is expected that over time some changes will be made to the request and response formats of various methods available in the API.\nWhere possible, these will be implemented in a backwards compatible way.\nTo make this possible you are required to ignore unknown properties.\nThis enables the addition of information in response documents while maintaining compatibility with older clients.\n\n### Optional Request Entity Properties\n\nThere are many instances where requests can be made without having to specify every single property allowable in the request format.\nAny such optional properties are noted as such in the documentation and their default value is noted.\n","title":"BulkSMS JSON REST API","version":"1.0.0","x-apisguru-categories":["telecom"],"x-logo":{"url":"/developer/images/bulksms.png"},"x-origin":[{"format":"openapi","url":"http://developer.bulksms.com/json/v1/swagger.yaml","version":"3.0"}],"x-providerName":"bulksms.com"},"security":[{"basicAuth":[]}],"tags":[{"name":"Message","x-displayName":"Messages"},{"name":"Profile","x-displayName":"Profile"}],"paths":{"/blocked-numbers":{"get":{"parameters":[{"description":"Records with an `id` that is greater or equal to min-id will be returned. The default value is `0`. You can add 1 to an id that you previously retrieved, to return subsequent records.","in":"query","name":"min-id","schema":{"format":"int32","type":"integer"}},{"description":"The maximum number of records to return. The default value is `10000`. The value cannot be greater than 10000.","in":"query","name":"limit","schema":{"format":"int32","type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockedNumber"}}},"description":"A list of BlockedNumber objects"}},"security":[{"basicAuth":[]}],"summary":"List blocked numbers","tags":["Blocked Numbers"]},"post":{"description":"Blocked numbers are phone numbers to which your account is not permitted to send messages.\nThe numbers can be created via this API, by a recipient replying with a STOP message to one\nof your previous SENT messages, or by a BulkSMS administrator.\n\nSending a message to a blocked number will result in the message being assigned a status of\n`FAILED.BLOCKED`. Messages sent to blocked numbers are billed to your account.\n","requestBody":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PhoneNumber"},"type":"array"}}},"description":"Maximum size: `1000` items","required":true},"responses":{"200":{"description":"Empty body upon success"}},"security":[{"basicAuth":[]}],"summary":"Create a blocked number","tags":["Blocked Numbers"]}},"/credit/transfer":{"post":{"description":"Before you can use the transfer credits endpoint, the _credit-transfer facility_ must be activated for your account. You can request activation from `support@bulksms.com`. \n\nThe recipient must be an enabled account that uses the same currency as your account.\n","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferEntry"}}},"description":"Contains details of the transfer request.\n","required":true},"responses":{"200":{"description":"An empty body when the credits were transferred OK."},"400":{"description":"When the request fails validation checks."},"403":{"description":"When there are not enough credits in your account or the credit transfer facility is not activated."}},"security":[{"basicAuth":[]}],"summary":"Transfer credits to another account","tags":["Credits"]}},"/messages":{"get":{"description":"Retrieve the messages you have sent or received. \n\nScheduled messages are available for retrieval only after the delivery date.\n\nAll the parameters are optional. If a value is not supplied for `filter`, the messages are not filtered.\n\nMessages can be filtered by supplying query clauses in the `filter` parameter. Each clause has the form `name=value` where `name` is the name of a filter field and `value` is a valid value for that field. A value for a field is optional. Include a clause for a field in the filter only when there is a need to fetch messages that match some value for that field.\nFor a numeric filter field, you can also use the less than operator (`<`).\n\nIf present, the filter value must have at least one clause, but it can contain a combination of clauses. Multiple clauses are separated with the `&` symbol. Semantically, multiple clauses form a [logical conjunction](https://en.wikipedia.org/wiki/Logical_conjunction).\n\nFor example, if you want to list all messages that were sent as part of a particular submission, your filter contains two clauses and will look something like this\n```\ntype%3DSENT&submission.id%3D1-00000000000522347562\n```\nBecause `filter` is a request parameter, it is important to note that the value for this parameter must be *URL encoded*. In particular, the `=` encodes to `%3D` and the `&` encodes to `%26`. Note that you do not have to encode the `<` character.\n\nUsing the previous example to illustrate; after encoding and encasing it, the clauses are transformed into a request that looks like this\n```\nGET /v1/messages?filter=type%3DSENT%26submission.id%3D1-00000000000522347562\n```\nIf the field name or the field value of a clause is not valid, a [bad_request error](errors#bad-request) is returned instead of the usual result. The `detail` field of this error provides more information about the problem.\n\nThe table below lists the fields available for filtering\n\n| Field | Type | Values | Note and example |\n|-------|------|--------------------|------|\n| id | Integer | Positive integer | Use the `id` field with `<` (or with `>`) to fetch messages that are older (or newer) than those that are already fetched. <br/>`filter=id<123456` |\n| type | String | SENT, RECEIVED | SENT are Mobile Terminating (MT) SMSs; RECEIVED are Mobile Originating (MO) SMSs.<br/>`filter=type%3DSENT` |\n| submission.id | String | | `filter=submission.id%3D1-00000000000522347562` |\n| status.type | String | ACCEPTED, SENT, DELIVERED, FAILED | See the message `status.type` field for more information. <br/>`filter=status.type%3DDELIVERED` |\n| status.id| String | | See the message `status.id` field for more information. `filter=status.id%3DFAILED.EXPIRED`|\n| submission.date | String | Formatted Date | A fully specified date (e.g. 2017-01-01T10:00:00+01:00). Use this field with `<=`, `<`, `>` or `>=` to limit the values. <br/>`filter=submission.date%3E%3D2017-01-01T10%3A00%3A00%2B01%3A00` |\n| userSuppliedId | String | | Use a string value you specified in the `userSuppliedId` property when you sent the message. Only `SENT` messages will be retrieved. <br/>`filter=userSuppliedId%3Dacc009876` |\n","parameters":[{"description":"The maximum number of messages that are returned. The default is 1000.\nThe value of `limit` is not a guarantee that a specific number of messages will be in the response, even if there are more messages available. Consider the case where you have 150 messages and you specify `limit=50`. It is possible that only 49 messages will be returned. The way to make sure that there are no more messages is to submit a new call using the `id` filter field with the `<` operator (described below).","in":"query","name":"limit","required":false,"schema":{"format":"int","type":"number"}},{"description":"See the message filtering for more information.","in":"query","name":"filter","schema":{"type":"string"}},{"description":"The default value is DESCENDING\n\nIf the `sortOrder` is DESCENDING, the newest messages be first in the result. ASCENDING places the oldest messages on top of the response.\n","in":"query","name":"sortOrder","schema":{"enum":["ASCENDING"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Message"},"type":"array"}}},"description":"Contains the requested array of messages"},"400":{"$ref":"#/components/responses/bad-request"}},"security":[{"basicAuth":[]}],"summary":"Retrieve Messages","tags":["Message"],"x-code-samples":[{"lang":"C#","source":"using System;\nusing System.IO;\nusing System.Net;\n\n class MainClass\n {\n\n public static void Main(string[] args)\n {\n /** \n Note in the query string \n we have a filter to get only the \n SENT messages\n */\n string myURI = \"https://api.bulksms.com/v1/messages?filter=type%3DSENT\";\n string myUsername = \"username\";\n string myPassword = \"yourPassword\";\n var request = WebRequest.Create(myURI);\n request.Credentials = new NetworkCredential(myUsername, myPassword);\n request.PreAuthenticate = true;\n request.Method = \"GET\";\n request.ContentType = \"application/json\";\n try\n {\n // make the call to the API\n var response = request.GetResponse();\n\n // read the response and print it to the console\n var reader = new StreamReader(response.GetResponseStream());\n Console.WriteLine(reader.ReadToEnd());\n\n } catch (WebException ex) {\n // show the general message\n Console.WriteLine(\"An error occurred:\" + ex.Message);\n\n // print the detail that come with the HTTP error \n var reader = new StreamReader(ex.Response.GetResponseStream());\n Console.WriteLine(\"Error details:\" + reader.ReadToEnd());\n }\n }\n}\n"}]},"post":{"description":"Send messages to one or more recipients.\n\nYou can post up to `30 000` messages in a batch. \nBut note that the `deduplication-id` is set per submission, so it is recommended that you use a smaller number, like `4000` per submission in order to make resubmissions on network failures more practical.\n\n#### Repliability\n\nWhen a sent message is _repliable_, the BulkSMS system can process an SMS response sent by your recipient.\n\nThe message sent by your customer is called a mobile originating (MO) message and would be available under `RECEIVED` messages. \nYou can obtain a list of MOs using the [retrieve messages API call](#tag/Message%2Fpaths%2F~1messages%2Fget).\nIn addition you can also get a list of the MOs that are associated with a specific sent message (see the [list related messages API call](#tag/Message%2Fpaths%2F~1messages~1%7Bid%7D~1relatedReceivedMessages%2Fget)).\n\nIf you use a specific _sender id_ in the `from` property of the send message, the message will not be repliable.\nIf you want a message to be repliable, you need to specify `REPLIABLE` in the `from.type` property.\n\nIf you do not set the `from` property, your account settings are considered to determine whether or not the message is repliable.\nIf the _default repliable_ setting on your account is _yes_ then the message will be repliable. \nIf this setting is _no_, the message will not be repliable.\n\n\n#### Body templates\n\nWhen sending a message you can use template fields to customise the message text.\n\n*Field based templates* allow you to create a message with place-holders for custom fields. Fields are identified by a zero based index; the first field is `F0`, the second is `F1` and so on. \n\nFor example, let's say you want to send a daily SMS message to all your clients that tell them what their current balance is. The `body` of the message could look something like this \n\n```\nGood morning {F0######}, your balance is {F1######}\n```\n\nIn this message, the first field, `F0`, is the name of the customer and he second field `F1` is the balance for that customer. The `#` used to specify the maximum length of the field. Note that the maximum length allowed for the value includes the space taken by the braces, template name and hash symbol. For example, the value `{F0#}` specifies a maximum length of `5`. If the data is longer than this length, the data will be truncated when the message body is constructed.\n\nThe data fields are provided in the property named `fields` in the `to` element. Here is a complete example of how this might look\n\n```\n{\n \"body\": \"Good morning {F0######}, your balance is {F1######}\",\n \"to\": [\n {\"address\": \"27456789\",\"fields\": [\"Harry\", \"$1345.23\"] },\n {\"address\": \"27456785\",\"fields\": [\"Sally\", \"$2345.58\"] }\n ]\n}\n```\n\nIf you are sending to contacts (or to groups) in your phonebook, you can use the *Phonebook based templates*. These are similar to the templates described above, but they have specific names. The template for the contact's first name is identified by `fn` and the template for the contact's surname is identified by `sn`. Below in an example that will work if the numbers are registered in your phonebook. \n\n```\n{\n \"body\": \"Hi {fn######} {sn######}, have a great day!\",\n \"to\": [\n {\"address\": \"27456789\" },\n {\"address\": \"27456785\" }\n ]\n}\n```\n","parameters":[{"description":"Safeguards against the possibility of sending the same messages more than once.\n\nIf a communication failure occurs during a submission, you cannot be sure that the submission was processed; therefore you would have to submit it again. When you post the retry, you must use the `deduplication-id` of the original post. The BulkSMS system uses this ID to check that the request was not previously processed. (If it was previously processed, the submission will succeed, and the behaviour will be indistinguishable to you from a non-duplicated submission). The ID expires after about 12 hours.\n","in":"query","name":"deduplication-id","schema":{"format":"int32","type":"integer"}},{"description":"Specifies how to deal with message text that contains characters not present in the GSM 03.38 character set.\n\nMessages that contain only GSM 03.38 characters are not affected by this setting. \nIf the value is `true` then a message containing non-GSM 03.38 characters will be transmitted as a Unicode SMS (which is most likely more costly). \n\nPlease note: when `auto-unicode` is `true` and the value of the `encoding` property is specified as `UNICODE`, the message will always be sent as `UNICODE`.\n\nIf the value is `false` and the `encoding` property is `TEXT` then non-GSM 03.38 characters will be replaced by the `?` character.\n\nWhen using this setting on the API, you should take case to ensure that your message is _clean_. \n\nInvisible unicode and unexpected characters could unintentionally convert an message to `UNICODE`. A common mistake is to use the backtick character (\\`) which is unicode and will turn your `TEXT` message into a `UNICODE` message.\n","in":"query","name":"auto-unicode","schema":{"default":false,"type":"boolean"}},{"description":"Allows you to send a message in the future.\n\nAn example value is `2019-02-18T13:00:00+02:00`. It encodes to `2019-02-18T13%3A00%3A00%2B02%3A00`.\nCredits are deducted from your account immediately. Once submitted, scheduled messages cannot be changed or cancelled.\nThe date can be a maximum of two years in the future. If the value is in the past, the message will be sent immediately.\nThe date format requires you to supply an offset from UTC. You can decide to use the offset of your timezone, or maybe the zone of the recipient's location is more appropriate.\nIf the destination is a group, the group members are determined at the time that you submit the message; not the time the message is scheduled to be sent.\n","in":"query","name":"schedule-date","schema":{"format":"date-time","type":"string"}},{"description":"A note that is stored together with a scheduled submission, which could be used to more easily identify the scheduled submission at a later date.\n\nThe value of this field is ignored if the `schedule-date` is not provided.\nA value that is longer than 256 characters is truncated.\n","in":"query","name":"schedule-description","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SubmissionEntry"},"type":"array"}}},"description":"Contains details of the message (or messages) that you want to send.\n\nOne `SubmissionEntry` can produce many messages, and your request may contain multiple such entries.\n","required":true},"responses":{"201":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Message"},"type":"array"}}},"description":"An array of the messages that were created from the request"},"400":{"$ref":"#/components/responses/bad-request"},"403":{"$ref":"#/components/responses/credits"}},"security":[{"basicAuth":[]}],"summary":"Send Messages","tags":["Message"],"x-code-samples":[{"lang":"PHP","source":"<?\n// Your PHP installation needs cUrl support, which not all PHP installations\n// include by default.\n// To run under docker:\n// docker run -v $PWD:/code php:7.3.2-alpine php /code/code_sample.php\n\n$username = 'your_username';\n$password = 'your_password';\n$messages = array(\n array('to'=>'+1233454567', 'body'=>'Hello World!'),\n array('to'=>'+1233454568', 'body'=>'Hello World!')\n); \n\n$result = send_message( json_encode($messages), 'https://api.bulksms.com/v1/messages?auto-unicode=true&longMessageMaxParts=30', $username, $password );\n\nif ($result['http_status'] != 201) {\n print \"Error sending: \" . ($result['error'] ? $result['error'] : \"HTTP status \".$result['http_status'].\"; Response was \" .$result['server_response']);\n} else {\n print \"Response \" . $result['server_response'];\n // Use json_decode($result['server_response']) to work with the response further\n}\n\nfunction send_message ( $post_body, $url, $username, $password) {\n $ch = curl_init( );\n $headers = array(\n 'Content-Type:application/json',\n 'Authorization:Basic '. base64_encode(\"$username:$password\")\n );\n curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);\n curl_setopt ( $ch, CURLOPT_URL, $url );\n curl_setopt ( $ch, CURLOPT_POST, 1 );\n curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );\n curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_body );\n // Allow cUrl functions 20 seconds to execute\n curl_setopt ( $ch, CURLOPT_TIMEOUT, 20 );\n // Wait 10 seconds while trying to connect\n curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT, 10 );\n $output = array();\n $output['server_response'] = curl_exec( $ch );\n $curl_info = curl_getinfo( $ch );\n $output['http_status'] = $curl_info[ 'http_code' ];\n $output['error'] = curl_error($ch);\n curl_close( $ch );\n return $output;\n} \n?> \n"},{"lang":"C#","source":"using System;\nusing System.IO;\nusing System.Net;\nusing System.Text;\n\nclass MainClass\n{\n public static void Main(string[] args)\n {\n // This URL is used for sending messages\n string myURI = \"https://api.bulksms.com/v1/messages\";\n\n // change these values to match your own account\n string myUsername = \"username\";\n string myPassword = \"password\";\n\n // the details of the message we want to send\n string myData = \"{to: \\\"1111111\\\", body:\\\"Hello Mr. Smith!\\\"}\";\n\n // build the request based on the supplied settings\n var request = WebRequest.Create(myURI);\n\n // supply the credentials\n request.Credentials = new NetworkCredential(myUsername, myPassword);\n request.PreAuthenticate = true;\n // we want to use HTTP POST\n request.Method = \"POST\";\n // for this API, the type must always be JSON\n request.ContentType = \"application/json\";\n\n // Here we use Unicode encoding, but ASCIIEncoding would also work\n var encoding = new UnicodeEncoding();\n var encodedData = encoding.GetBytes(myData);\n\n // Write the data to the request stream\n var stream = request.GetRequestStream();\n stream.Write(encodedData, 0, encodedData.Length);\n stream.Close();\n\n // try ... catch to handle errors nicely\n try\n {\n // make the call to the API\n var response = request.GetResponse();\n\n // read the response and print it to the console\n var reader = new StreamReader(response.GetResponseStream());\n Console.WriteLine(reader.ReadToEnd());\n }\n catch (WebException ex)\n {\n // show the general message\n Console.WriteLine(\"An error occurred:\" + ex.Message);\n\n // print the detail that comes with the error\n var reader = new StreamReader(ex.Response.GetResponseStream());\n Console.WriteLine(\"Error details:\" + reader.ReadToEnd());\n }\n }\n}\n"},{"lang":"Java","source":"import java.net.*;\nimport java.util.Base64;\nimport java.io.*;\n\npublic class MainClass {\n\n static public void main(String[] args) throws Exception {\n\n // This URL is used for sending messages\n String myURI = \"https://api.bulksms.com/v1/messages\";\n\n // change these values to match your own account\n String myUsername = \"username\";\n String myPassword = \"password\";\n\n // the details of the message we want to send\n String myData = \"{to: \\\"1111111\\\", encoding: \\\"UNICODE\\\", body: \\\"Dobrá práce! Jak se máš?\\\"}\";\n\n // if your message does not contain unicode, the \"encoding\" is not required:\n // String myData = \"{to: \\\"1111111\\\", body: \\\"Hello Mr. Smith!\\\"}\";\n\n // build the request based on the supplied settings\n URL url = new URL(myURI);\n HttpURLConnection request = (HttpURLConnection) url.openConnection();\n request.setDoOutput(true);\n\n // supply the credentials\n String authStr = myUsername + \":\" + myPassword;\n String authEncoded = Base64.getEncoder().encodeToString(authStr.getBytes());\n request.setRequestProperty(\"Authorization\", \"Basic \" + authEncoded);\n\n // we want to use HTTP POST\n request.setRequestMethod(\"POST\");\n request.setRequestProperty( \"Content-Type\", \"application/json\");\n\n // write the data to the request\n OutputStreamWriter out = new OutputStreamWriter(request.getOutputStream());\n out.write(myData);\n out.close();\n\n // try ... catch to handle errors nicely\n try {\n // make the call to the API\n InputStream response = request.getInputStream();\n BufferedReader in = new BufferedReader(new InputStreamReader(response));\n String replyText;\n while ((replyText = in.readLine()) != null) {\n System.out.println(replyText);\n }\n in.close();\n } catch (IOException ex) {\n System.out.println(\"An error occurred:\" + ex.getMessage());\n BufferedReader in = new BufferedReader(new InputStreamReader(request.getErrorStream()));\n // print the detail that comes with the error\n String replyText;\n while ((replyText = in.readLine()) != null) {\n System.out.println(replyText);\n }\n in.close();\n }\n request.disconnect();\n }\n}\n"},{"lang":"Node.js","source":"const https = require('https');\n\nlet username = 'your_username';\nlet password = 'your_password';\n\nlet postData = JSON.stringify({\n 'to' : ['+111111123', '+111111124'],\n 'body': 'Hello World!'\n});\n\nlet options = {\n hostname: 'api.bulksms.com',\n port: 443,\n path: '/v1/messages',\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': postData.length,\n 'Authorization': 'Basic ' + Buffer.from(username + ':' + password).toString('base64')\n }\n};\n\nlet req = https.request(options, (resp) => {\n console.log('statusCode:', resp.statusCode);\n let data = '';\n resp.on('data', (chunk) => {\n data += chunk;\n });\n resp.on('end', () => {\n console.log(\"Response:\", data);\n });\n});\n\nreq.on('error', (e) => {\n console.error(e);\n});\n\nreq.write(postData);\nreq.end();\n"}]}},"/messages/send":{"get":{"description":"A really simple interface for people who require a GET mechanism to submit a single message.\n\nThe URI is interpreted as UTF-8. HTTP Basic Auth is used for authentication.\n\n__Note__ BulkSMS recommends that you use the more flexible Send Messages Operation when submitting SMS messages from your application.\n\nHere is an example of a GET\n```http\nGET /v1/messages/send?to=%2b270000000&body=Hello%20World\n```\n\nYou can also use the same parameters to POST form encoded fields to `/messages`.\nHere is an example of a POST\n```http\nPOST /v1/messages\nContent-Type: application/x-www-form-urlencoded\n\nto=%2b27000000000&body=Hello+World\n```\n","parameters":[{"description":"The phone number of the recipient.","in":"query","name":"to","required":true,"schema":{"type":"string"}},{"description":"The text you want to send.","in":"query","name":"body","required":true,"schema":{"type":"string"}},{"description":"Refer to the `deduplication-id` parameter.","in":"query","name":"deduplication-id","schema":{"format":"int-32","type":"integer"}}],"responses":{"201":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Message"},"type":"array"}}},"description":"An array of messages"},"400":{"$ref":"#/components/responses/bad-request"},"403":{"$ref":"#/components/responses/credits"}},"security":[{"basicAuth":[]}],"summary":"Send message by simple GET or POST","tags":["Message"]}},"/messages/{id}":{"get":{"description":"Get a the message by `id`.\n```http\nGET /v1/messages/4023457654\n```\n","parameters":[{"description":"The `id` of the message you want to retrieve","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}},"description":"The message detail"},"400":{"$ref":"#/components/responses/bad-request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"A [not-found error](errors/#not-found) if the message cannot be found."}},"summary":"Show Message","tags":["Message"]}},"/messages/{id}/relatedReceivedMessages":{"get":{"description":"Get the messages related to a sent message identified by `id`.\n\nFor more information how this work, see the `relatedSentMessageId` field in the message.\n","parameters":[{"description":"The `id` of the sent message","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Message"},"type":"array"}}},"description":"An array of related messages. If the `id` is not a sent message, the array will be empty."},"400":{"$ref":"#/components/responses/bad-request"}},"security":[{"basicAuth":[]}],"summary":"List Related Messages","tags":["Message"]}},"/profile":{"get":{"description":"Returns information about your user profile","responses":{"200":{"content":{"application/json":{"examples":{"response":{"value":null}},"schema":{"$ref":"#/components/schemas/Profile"}}},"description":"A Profile object"}},"security":[{"basicAuth":[]}],"summary":"Get profile","tags":["Profile"]}},"/rmm/pre-sign-attachment":{"post":{"description":"When composing an SMS, you can add SMS attachments by adding a URL to your text. When the recipient clicks on the URL, the attached file will be downloaded and opened on their mobile device. \n\nThe best way to do this is to store the file on a web server you own and use that URL in the SMS text. This URL will be easily recognisable to your message recipient and ties your message back to your brand or company. \n\nIf that’s not possible, you can use BulkSMS storage to keep the files that you want to attach to your SMS. These files will be deleted after 30 days as per our fair use policy. \n\nWe recommend you keep this file size below 20 MB, as larger files may be deleted without warning. \n\nTo use the BulkSMS storage, follow these three steps:\n\n**Step 1**: Use your BulkSMS credentials (or your API Token) to request a pre-signed URL. This is what this `pre-sign-attachment` method is for. It returns a PreSignInfo object that you will use in the other two steps.\n\n**Step 2**: Upload the file using a standard HTTP `PUT` request. For your `PUT` request, use the value of `putURL` from the PreSignInfo object as the request address. You also have to add the entries from the `fields` property (of the PreSignInfo object) to the headers of your 'PUT' request. You send the file content as the body of the `PUT` request.\n\n**Step 3**: Now you can use the value of `fetchURL` from the PreSignInfo object in the body of your SMS messages and send those using the usual messaging API (described elsewhere in this document). If you send the same file to many recipients, it is safe to use the same URL for all of them.\n\nIf you need to, take a closer look at the example program (on the right-hand side) to get a better idea of how to implement this process.\n","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreSignRequest"}}},"description":"Describes the file to upload","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreSignInfo"}}},"description":"A PreSignInfo object"}},"security":[{"basicAuth":[]}],"summary":"Upload an attachment via a signed URL","tags":["Attachments"],"x-code-samples":[{"lang":"C#","source":"using System;\nusing System.IO;\nusing System.Net;\nusing System.Text;\nusing System.Text.Json;\n\nnamespace AttachmentUpload\n{\n class MainClass\n {\n // IMPORTANT: change these constants to match your environment\n const string myUsername = \"username\";\n const string myPassword = \"password\";\n const string myPhoneNumber = \"1111111\";\n const string myFilePath = \"path/to/file.pdf\";\n const string myMediaType = \"application/pdf\";\n const string myFileExtension = \"pdf\";\n\n public static void Main(string[] args)\n {\n try\n {\n // get authorisation (pre-signed URL)\n var signDetails = getSignedDetails(myFileExtension, myMediaType);\n // upload and send the file to the signed URL\n sendFile(signDetails, myFilePath);\n // send your messages using the provided URL\n sendMessage(myPhoneNumber, \"Attachment test`: \" + signDetails.fetchUrl);\n Console.WriteLine($\"Message sent that contains URL to file: {signDetails.fetchUrl}\");\n }\n catch (Exception ex)\n {\n Console.WriteLine(\"An error occurred:\\n\" + ex.Message);\n }\n }\n\n public static void sendFile(PreSignInfo signDetails, string filePath)\n {\n using (WebClient client = new WebClient())\n {\n foreach (var f in signDetails.fields)\n {\n client.Headers.Add(f.name, f.value);\n }\n using (Stream fileStream = File.OpenRead(filePath))\n using (Stream requestStream = client.OpenWrite(new Uri(signDetails.putUrl), \"PUT\"))\n {\n fileStream.CopyTo(requestStream);\n }\n }\n }\n\n public static PreSignInfo getSignedDetails(string extension, string mediaType)\n {\n string postMessageUrl = \"https://api.bulksms.com/v1/rmm/pre-sign-attachment\";\n string requestBody = $\"{{fileExtension: '{extension}', mediaType: '{mediaType}'}}\";\n var result = postJson(postMessageUrl, requestBody);\n return JsonSerializer.Deserialize<PreSignInfo>(result);\n }\n\n public static string sendMessage(string phoneNumber, string messageText)\n {\n string postMessageUrl = \"https://api.bulksms.com/v1/messages?auto-unicode=true\";\n string requestBody = $\"{{to: '{myPhoneNumber}', body: '{messageText}'}}\";\n return postJson(postMessageUrl, requestBody);\n }\n\n\n public static string postJson(string url, string jsonBody)\n {\n var request = WebRequest.Create(url);\n var encoding = ASCIIEncoding.UTF8;\n var auth = $\"{myUsername}:{myPassword}\";\n var authBase64 = Convert.ToBase64String(encoding.GetBytes(auth));\n request.Headers.Add(\"Authorization\", \"Basic \" + authBase64);\n request.Method = \"POST\";\n request.ContentType = \"application/json\";\n var encodedData = encoding.GetBytes(jsonBody);\n var stream = request.GetRequestStream();\n stream.Write(encodedData, 0, encodedData.Length);\n stream.Close();\n try\n {\n var response = request.GetResponse();\n var reader = new StreamReader(response.GetResponseStream());\n return reader.ReadToEnd();\n }\n catch (WebException ex)\n {\n var reader = new StreamReader(ex.Response.GetResponseStream());\n throw new Exception(reader.ReadToEnd());\n }\n\n }\n\n }\n\n class NameValue\n {\n public string name { get; set; }\n public string value { get; set; }\n }\n\n class PreSignInfo\n {\n public string putUrl { get; set; }\n public string fetchUrl { get; set; }\n public NameValue[] fields {get;set;}\n\n }\n}\n"}]}},"/webhooks":{"get":{"description":"Contains a list of your webhooks","responses":{"200":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Webhook"},"type":"array"}}},"description":"Array of Webhooks"}},"security":[{"basicAuth":[]}],"summary":"List webhooks","tags":["Webhooks"]},"post":{"description":"A webhook is an URL that you can register when you want the BulkSMS system to notify you about your messages.\nYou can register multiple webhooks, and each one will be called. (Note: you can also use our [Web App](https://www.bulksms.com/account/#!/advanced-settings/webhooks) to manage your webhooks interactively.) \nIf you want to be notified of `SENT` messages and `RECEIVED` messages you need to create two webhooks.\n\n\n### Implementing your webhook\n\nCode samples of Webhook implementations:\n* [PHP](samples/webhook-php.html)\n\nWhen you implement your webhook, there are a few rules to be aware of:\n- Your webhook must process `POST` requests that contains an array of messages in the post body. This input given to your webhook has the same structure as the output produced when you call [Retrieve Messages](#tag/Message%2Fpaths%2F~1messages%2Fget).\n- When you register or update your webhook, the URL will be tested by invoking it with an empty array (`[]`). \n- It is possible for your webhook to receive multiple updates for the same message and status. It happens from time to time that the mobile network duplicates status updates.\n- The order by which the webhook is invoked can be unexpected. For example, if sender A replies before sender B, your webhook might get the reply from B first.\n- The webhook is expected to comply with good practices with regard to the status code it responds with.\n - A status code in the `1xx` and `2xx` range is taken as an acknowledgement that the invocation was received and that the webhook host is ready to receive another.\n - A status code in the `4xx` range is taken as a permanent problem and indicates that the webhook cannot process the message. The specific message that caused the error will be discarded, but your webhook will be invoked again when another message becomes available.\n - Any other status code will be taken as a temporary problem; and indicates that the BulkSMS system should retry. The specific message that caused the error will not be discarded and your webhook will be invoked again with this message (see the subsequent section for more details on retry processing).\n- Your webhook has to respond within `30` seconds. If no response is given in this time, the invocation will be retried.\n- It is good idea to add a secret to your URL in order to make it more secure. Here is an example:\n`https://www.example.com/hook.php?secret=pass763265word`\n- You can use a non-standard port if necessary, for example: `https://www.example.com:8321/hook.php?secret=pass763265word`\n- Your webhook can be called from a dynamic range of IP addresses, and you should be prepared to accept that the source IP can change in the future, without notice. This practice has become common with cloud-hosted solutions. If this is an insurmountable problem for your organisation, please contact support.\n\n### Testing and troubleshooting \n\nUse `curl` to test your webhook. The command below is a template that shows how the BulkSMS system invokes your code. It must return `200` for your URL before you can register it as a webhook. \n\n```\ncurl -i -X POST 'YOUR_URL_HERE' --header 'Content-Type: application/json' --header 'User-Agent: BulkSMS Invoker' --data-raw '[]'\n```\n\nWhen a `200` is returned for an empty array, modify the template to post multiple messages by adding JSON between the square brackets ('[]').\n\nAfter your webhook is successfully registered, you can send a message to `1111111` for an end-to-end test. The delivery to this test number will fail, but your webhook will be invoked (and there are no charges). \n\n### The retry process\n\nThe process the BulkSMS systems follow to handle retries is roughly the following:\n- The first retry is scheduled for 90 seconds into the future.\n- After the first retry, subsequent failures will have longer delays, following this sequence - 3 minutes, 6 minutes, 12 minutes thereafter the message will be retried every 15 minutes for a 2 day period.\n- When all retries fail, the message will be discarded.\n\n### Problem reports via email\n\nYour are strongly advised to provide an email address when you register your webhook.\nA notice will be sent to this email address to keep you in the loop whenever there are problems with your webhook.\nIn order to prevent your inbox from being flooded, the system sends a notice about an observed error no more than once in a 24 hour period.\n\nThe following emails can be expected\n - A __message retrying__ email is sent after an invocation has failed with a retry-able error. This email is an early warning, allowing you to investigate your systems.\n - A __message discarded__ email is sent after failure email is send when a message is discarded as a consequence of a non-retry-able error.\n","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEntry"}}},"description":"Contains the property values for your new webhook\n","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}},"description":"Contains the webhook you created"},"400":{"$ref":"#/components/responses/bad-webhook-url"}},"security":[{"basicAuth":[]}],"summary":"Create a webhook","tags":["Webhooks"]}},"/webhooks/{id}":{"delete":{"responses":{"200":{"description":"The webhook was deleted successfully"},"404":{"$ref":"#/components/responses/bad-webhook-id"}},"summary":"Delete a webhook","tags":["Webhooks"]},"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}},"description":"The properties of a specific webhook"},"400":{"$ref":"#/components/responses/bad-webhook-url"},"404":{"$ref":"#/components/responses/bad-webhook-id"}},"summary":"Read a webhook","tags":["Webhooks"]},"parameters":[{"description":"The `id` of the webhook","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEntry"}}},"description":"Contains the new property values for the webhook\n","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}},"description":"The properties of the updated webhook"},"404":{"$ref":"#/components/responses/bad-webhook-id"}},"summary":"Update a webhook","tags":["Webhooks"]}}},"components":{"responses":{"bad-request":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad Request. The content or structure of your submission, or a parameter, was found to be invalid."},"bad-webhook-id":{"content":{"application/json":{"examples":{"response":{"value":{"detail":"Webhook with id '1' does not exist\n","status":404,"title":"Not Found","type":"https://developer.bulksms.com/json/v1/errors/#not-found"}}},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"A webhook with the given id does not exit"},"bad-webhook-url":{"content":{"application/json":{"examples":{"response":{"value":{"detail":"Invoking the Webhook URL caused an error: 403 - Forbidden\n","status":400,"title":"Bad Request","type":"https://developer.bulksms.com/json/v1/errors/#bad-request"}}},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The url given for the webhook is not callable"},"credits":{"content":{"application/json":{"examples":{"response":{"value":{"status":403,"title":"Insufficient Credits","type":"https://developer.bulksms.com/json/v1/errors#insufficient-credits"}}},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Forbidden. Inspect the body of the response for further details - for example, you may have insufficient credits remaining"}},"schemas":{"BlockedNumber":{"properties":{"id":{"description":"A unique identifier that is assigned when the BlockedNumber is created.","example":234,"format":"int32","type":"number"},"phoneNumber":{"allOf":[{"$ref":"#/components/schemas/PhoneNumber"}]}},"required":["id","phoneNumber"],"type":"object"},"Error":{"description":"See the [errors page](errors/) for more detail on what kind of errors you can get.","properties":{"detail":{"description":"More information about why the error occurred.","type":"string"},"status":{"description":"The HTTP status code","format":"int32","type":"integer"},"title":{"description":"A short description of the type","type":"string"},"type":{"description":"A URL to one of the [error types](errors/).","type":"string"}},"required":["type","title","status"],"type":"object"},"Message":{"properties":{"body":{"description":"The content of the message"},"creditCost":{"description":"The cost of the message (in credits). Note that this field does not have a value in the submission response.","format":"float","type":"number"},"encoding":{"description":"The type of the content. See the `encoding` field for more information.","enum":["TEXT","UNICODE","BINARY"],"type":"string"},"from":{"description":"The address part of the sender id","type":"string"},"id":{"description":"A unique identifier that is assigned when the message is created.","type":"string"},"messageClass":{"description":"See the `messageClass` field for more information.","format":"int32","type":"integer"},"numberOfParts":{"description":"The number of parts. If this is a concatenated message, the number of parts will be more than 1. Note that this field does not have a value in the submission response.","format":"int32","type":"integer"},"protocolId":{"description":"See the `protocolId` field for more information.","format":"int32","type":"integer"},"relatedSentMessageId":{"description":"This field has a value only if the type is RECEIVED.\nWith SMS messages, it is not possible to link a reply directly with a specific sent message. However, if you specified `REPLIABLE` in the `from` property, BulkSMS will link any reply to the most recent message sent to a given phone number.\n\nThe `relatedSentMessageId` property keeps the information about this link.\n\nYou can use this property to derive an implicit conversation from a set of messages.\n - If a received reply message has a `relatedSentMessageId`, you can use it to retrieve the last message that was sent before the reply was received.\n - If you have the `id` of the sent message and you want all the received messages that relate to it, you can use the List Related Messages Operation.\n","type":"string"},"status":{"description":"The status of the message","properties":{"id":{"description":"A concatenated value A.B where A is the `status.type` and B is the `status.subtype`. \nIt there is no value for `subtype` then B takes string value `\"null\"` (e.g. `\"SENT.null\"`). \n","type":"string"},"subtype":{"description":"Has a value only if the `type` is FAILED.\n\nEXPIRED Delivery failed because message expired before delivery was possible.\n\nHANDSET_ERROR Delivery failed because of a problem related to the phone (e.g. message storage area full).\n\nBLOCKED Your account has been blocked from sending to this phone (e.g. recipient replied STOP to block communication).\n\nNOT_SENT Message delivery was not attempted (e.g. because we were not able to find a route for the supplied phone number).\n","enum":["EXPIRED","HANDSET_ERROR","BLOCKED","NOT_SENT"],"type":"string"},"type":{"description":"\nACCEPTED Message accepted for delivery. Only returned for initial message submissions.\n\nSCHEDULED Message accepted for delivery at a later date. Only returned for initial message submissions.\n\nSENT Message has been relayed away from our systems.\n\nDELIVERED Successfully delivered to phone.\n\nUNKNOWN Message is in an unknown state.\n\nFAILED Delivery failed.\n","enum":["ACCEPTED","SCHEDULED","SENT","DELIVERED","UNKNOWN","FAILED"],"type":"string"}},"required":["id","type"],"type":"object"},"submission":{"description":"Identifies the submission.\n","properties":{"date":{"description":"The date and time the submission was processed. If