Download APKs from:

An SMS gateway for Android. Send and receive SMS from your webapp via an Android phone.

+--------+                 +-----------+
|  web   |                 |  medic-   | <-------- SMS
| server | <---- HTTP ---- |  gateway  |
|        |                 | (android) | --------> SMS
+--------+                 +-----------+



Install the latest APK from


Medic Mobile

If you're configuring medic-gateway for use with hosted medic-webapp, with a URL of e.g. and a username of gateway and a password of topSecret, fill in the settings as follows:

Medic-branded gateway

Please note that in the medic-branded build, the username is hard-coded as gateway, and cannot be changed.

Instance name: myproject [dev]
Password: topSecret

Generic-branded gateway

WebappUrl: https://gateway:[email protected]


If you're configuring medic-gateway for use with other services, you will need to use the generic build of medic-gateway, and find out the value for webapp URL from your tech support.

CDMA Compatibility Mode

Some CDMA networks have limited support for multipart SMS messages. This can occur within the same network, or only when sending SMS from a GSM network to a CDMA network. Check this box if medic-gateway is running on a GSM network and:


When using HTTP Basic Auth with gateway, all characters in the password must be chosen from the ISO-8859-1 characterset, excluding #, /, ?, @.


This is the API specification for communications between medic-gateway and a web server. Messages in both directions are application/json.

Where a list of values is expected but there are no values provided, it is acceptable to:

Bar array behaviour specified above, medic-gateway must include fields specified in this document, and the web server must include all expected fields in its responses. Either party may include extra fields as they see fit.


N.B. messages are cosidered duplicate by medic-gateway if they have identical values for id. The webapp is expected to do the same.

medic-gateway will not re-process duplicate webapp-originating messages.

medic-gateway may forward a webapp-terminating message to the webapp multiple times.

medic-gateway may forward a delivery status report to the webapp multiple times for the same message. This should indicate a change of state, but duplicate delivery reports may be delivered in some circumstances, including:


medic-gateway supports HTTP Basic Auth. Just include the username and password for your web endpoint when configuring medic-gateway, e.g.:

https://username:[email protected]/medic-gateway-api-endpoint


The entire API should be implemented by a webapp at a single endpoint, e.g.


Expected response:

    "medic-gateway": true


medic-gateway will accept and process any relevant data received in a response. However, it may choose to only send certain types of information in a particular request (e.g. only provide a webapp-terminating SMS), and will also poll the web service periodically for webapp-originating messages, even if it has no new data to pass to the web service.



The following headers will be set by requests:

header value
Accept application/json
Accept-Charset utf-8
Accept-Encoding gzip
Cache-Control no-cache
Content-Type application/json

Requests and responses may be sent with Content-Encoding set to gzip.


    "messages": [
            "id": <String: uuid, generated by `medic-gateway`>,
            "from": <String: international phone number>,
            "content": <String: message content>,
            "sms_sent": <long: ms since unix epoch that message was sent>,
            "sms_received": <long: ms since unix epoch that message was received>
    "updates": [
            "id": <String: uuid, generated by webapp>,
            "status": <String: PENDING|SENT|DELIVERED|FAILED>,
            "reason": <String: failure reason (optional - only present for status:FAILED)>

The status field is defined as follows.

Status Description
PENDING The message has been sent to the gateway's network
SENT The message has been sent to the recipient's network
DELIVERED The message has been received by the recipient's phone
FAILED The delivery has failed and will not be retried



HTTP Status: 2xx

Clients may respond with any status code in the 200-299 range, as they feel is appropriate. medic-gateway will treat all of these statuses the same.

    "messages": [
            "id": <String: uuid, generated by webapp>,
            "to": <String: local or international phone number>,
            "content": <String: message content>

HTTP Status 400+

Response codes of 400 and above will be treated as errors.

If the response's Content-Type header is set to application/json, medic-gateway will attempt to parse the body as JSON. The following structure is expected:

    "error": true,
    "message": <String: error message>

The message property may be logged and/or displayed to users in the medic-gateway UI.

Other response codes

Treatment of response codes below 200 and between 300 and 399 will probably be handled sensibly by Android.





Building locally

To build locally and install to an attached android device:


To run unit tests and static analysis tools locally:

make test

To run end to end tests, first either connect a physical device, or start an emulated android device, and then:

make e2e


There is a demonstration implementation of a server included for medic-gateway to communicate with. You can add messages to this server, and query it to see the interactions that it has with medic-gateway.


To start the demo server locally:

make demo-server

To list the data stored on the server:

curl http://localhost:8000

To make the next good request to /app return an error:

curl --data '"Something failed!"' http://localhost:8000/error

To add a webapp-originating message (to be send by medic-gateway):

curl -vvv --data '{ "id": "3E105262-070C-4913-949B-E7ACA4F42B71", "to": "+447123555888", "content": "hi" }' http://localhost:8000

To simulate a request from medic-gateway:

curl http://localhost:8000/app -H "Accept: application/json" -H "Accept-Charset: utf-8" -H "Accept-Encoding: gzip" -H "Cache-Control: no-cache" -H "Content-Type: application/json" --data '{}'

To clear the data stored on the server:

curl -X DELETE http://localhost:8000

To set a username and password on the demo server:

curl --data '{"username":"alice", "password":"secret"}' http://localhost:8000/auth


It's simple to deploy the demo server to remote NodeJS hosts.


TODO walkthrough


TODO walkthrough

Android Version Support

"Default SMS/Messaging app"

Some changes were made to the Android SMS APIs in 4.4 (KitkatĀ®). The significant change was this:

from android 4.4 onwards, apps cannot delete messages from the device inbox unless they are set, by the user, as the default messageing app for the device

Some reading on this can be found at:

Adding support for kitkatĀ® means that there is some extra code in medic-gateway whose purpose is not obvious:

Non-existent activities in AndroidManifest.xml

Activities HeadlessSmsSendService and ComposeSmsActivity are declared in AndroidManifest.xml, but are not implemented in the code.

Unwanted permissions

The BROADCAST_WAP_PUSH permission is requested in AndroidManifest.xml, and an extra BroadcastReceiver, MmsIntentProcessor is declared. When medic-gateway is the default messaging app on a device, incoming MMS messages will be ignored. Actual WAP Push messages are probably ignored too.

Extra intents

To support being the default messaging app, medic-gateway listens for SMS_DELIVER as well as SMS_RECEIVED. If the default SMS app, we need to ignore SMS_RECEIVED.

Runtime Permissions

Since Android 6.0 (marshmallow), permissions for sending and receiving SMS must be requested both in AndroidManifest.xml and also at runtime. Read more at


Copyright 2013-2020 Medic Mobile, Inc. [email protected]


The software is provided under AGPL-3.0. Contributions to this project are accepted under the same license.