Technical Documentation
Overview
The SMS2API is a simple application forwards the received SMS messages to an HTTP REST API. The message data is being transferred as a JSON object via HTTP as a HTTP request. The app only forwards the messages received while the application is running. (in the foreground or at the background). The app doesn't forward previous SMS messages stored on the device. Due to this design, the app IS NOT GOOGLE PLAY COMPATIBLE, but only requests permission for android.permission.RECEIVE_SMS and uses android.permission.INTERNET as part of the normal permissions.
Endpoint requirements
The SMS2API application makes an HTTP POST request on each received message. The content type of the HTTP request is application/json , the encoding is UTF8. The HTTP endpoint is defined by the user on the app's UI. The application assumes an application/json response containing a valid JSON object in the body. This behavior is the same for all HTTP status codes, so in the case of 401 or in the case of 500 the valid JSON body is also required! In the case of HTTP status 200 reply, the "success" counter does increment. In the case of HTTP status 401 or 500 the "failed" counter increment the application UI. UI.
JSON object
The posted JSON object contains all the received SMS data and contains two more extra fields to help to integrate. These fields are the apiKey and the userDefinedId. These are simple string values located at the root level of the JSON object. As the names show, these fields are designed to be used for authentication and device-identification purposes but feel free to use them for different purposes for your use case. The application doesn't check or modify the values of these fields.
Note, these string fields are stored in the application's local storage as plain texts!
{
apiKey: 'weiY7eirrohQu2tiOof9iehe',
messageBody: 'Blablabla',
originalMessage: {
mSubId: 3,
mWrappedSmsMessage: {
mDataCodingScheme: 0,
mEncodingType: 1,
mIsStatusReportMessage: false,
mMti: 0,
mProtocolIdentifier: 0,
mReplyPathPresent: false,
mStatus: 0,
mVoiceMailCount: 0,
messageClass: 'UNKNOWN',
absoluteValidityPeriod: 0,
mIndexOnIcc: -1,
mIsEmail: false,
mIsMwi: false,
mMessageBody: '2',
mMessageRef: 0,
mMwiDontStore: false,
mMwiSense: false,
mOriginatingAddress: [Object],
mPdu: [Array],
mScAddress: '+36709996511',
mScTimeMillis: 1633424319000,
mStatusOnIcc: -1,
mUserData: [Array],
mwiCount: 0,
mwiType: -1,
relativeValidityPeriod: 0
}
},
originatingAddress: '+36705559955',
serviceCenterAddress: '+36709996511',
timestampMillis: 1633424319000,
userDefinedId: 'motoc'
}
As this example JSON object shows, the originalMessage object encapsulates the whole Android-provided SMS object.
You could learn more about the represented data at https://developer.android.com/reference/android/provider/Telephony.Sms.Intents
The outer "wrapper" objects provides the more importants fields at the root level too. These fields are the followings:
- messageBody is the received message
- originatingAddress is the sender's number
- serviceCenterAddress is the number of the SMS center
- timestampMillis shows what was the timestamp when the Android system did recive the message
- apiKey simple extra string value
- userDefinedId simple additional string value
Example server
var http = require('http')
http.createServer( async (req, res) => {
// Set the proper response type
res.setHeader('Content-Type', 'application/json')
try {
// Create a buffer for received chunks
const buff = []
for await (const chunk of req) buff.push(chunk)
// Get the data object & create a JSON
const data = Buffer.concat(buff).toString()
const message = JSON.parse(data)
console.info("Message received: ", message)
// ...
// process the received message, do your business logic
// in case of no error, return with status code 200
res.writeHead(200, {'Content-Type': 'application/json'})
res.write(JSON.stringify({message: `Message has been stored.`}))
} catch (e) {
// in case of any error, we are going to return with 500
res.writeHead(500, {'Content-Type': 'application/json'})
res.write(JSON.stringify({message: `Oops! Something went wrong!`}))
} finally {
res.end()
}
}).listen(8080)
Appendix
The SMS2API app doesn't delete the received messages, just forward them. Due to this design, consider to use some automated message deletation tasks. Some Android phone provides this feature out-of-the box while others do not. We use Textra, a 3rd party texting app allowing a feature to delete old messages. Textra is not perfect for this task because it does not delete unread messages and has to delete them manually! If you find a better solution for this issue, please, let us know!
SMS2API is designed to solve a very specific need. Due to this fact, maybe in your case some features will be missing. We have tested the app for that very specific use-case, so it could be buggy by using differently! Please let us know if you find a bug and we are going to fix it. We are open to add new features, please let us know, what we have to add. You could easily reach us at init@starcat.dev.
🤓 Happy Integration!