diff --git a/app/build.gradle b/app/build.gradle
index 027d93daafacb3fecbcc0d36f3fc6073a5eeb215..742d781f311bc64d8087b7db300892313e22c6af 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,6 +7,7 @@ buildscript {
 
     dependencies {
         classpath 'io.fabric.tools:gradle:1.21.6'
+        classpath 'io.realm:realm-gradle-plugin:2.3.1'
         classpath 'org.ajoberstar:grgit:1.5.0'
     }
 }
@@ -154,11 +155,16 @@ dependencies {
     compile 'org.apache.commons:commons-lang3:3.4'
     compile 'com.mikepenz:google-material-typeface:2.2.0.1.original@aar'
     compile 'uk.co.chrisjenx:calligraphy:2.2.0'
-    compile 'com.bugfender.sdk:android:0.6.2'
+    compile 'com.bugfender.sdk:android:0.7.2'
     compile 'com.jjoe64:graphview:4.2.1'
     compile 'com.android.support:support-v4:23.4.0'
     compile 'com.google.code.gson:gson:2.7'
     compile 'com.squareup.retrofit2:retrofit:2.1.0'
     compile 'com.squareup.retrofit2:converter-gson:2.1.0'
+    compile 'com.squareup.okhttp3:okhttp:3.3.1'
+    compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
     compile 'com.google.android.gms:play-services-appindexing:8.4.0'
+
+
+
 }
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4f075c37ba2f7387d322e3ed95c22c04eb2b6368..2ea896197d19abb365b6bbd2baaa8357cdd3692d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -82,6 +82,11 @@
         <receiver android:name=".upload.nightscout.NightscoutUploadReceiver" />
         <receiver android:name=".xdrip_plus.XDripPlusUploadReceiver" />
 
+
+        <receiver android:name=".medtronic.service.MedtronicCnlAlarmReceiver"></receiver>
+
+
+
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
index cfe52c2cf6dd3ea601171455a3b5ca1adf67b851..87adfa0667c404458262d91ce4f503e29dc9e0a1 100644
--- a/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
+++ b/app/src/main/java/info/nightscout/android/model/medtronicNg/PumpStatusEvent.java
@@ -81,6 +81,10 @@ public class PumpStatusEvent extends RealmObject  {
         return CGM_TREND.valueOf(cgmTrend);
     }
 
+    public String getCgmTrendString() {
+        return cgmTrend;
+    }
+
     public void setCgmTrend(CGM_TREND cgmTrend) {
         if (cgmTrend != null)
             this.cgmTrend = cgmTrend.name();
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java b/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java
new file mode 100644
index 0000000000000000000000000000000000000000..55a2120df7189c2faa87076382db1906fdd93f91
--- /dev/null
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightScoutUpload.java
@@ -0,0 +1,169 @@
+package info.nightscout.android.upload.nightscout;
+
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
+import info.nightscout.android.upload.nightscout.serializer.EntriesSerializer;
+
+import android.support.annotation.NonNull;
+import info.nightscout.api.UploadApi;
+import info.nightscout.api.GlucoseEndpoints;
+import info.nightscout.api.BolusEndpoints.BolusEntry;
+import info.nightscout.api.GlucoseEndpoints.GlucoseEntry;
+import info.nightscout.api.BolusEndpoints;
+import info.nightscout.api.DeviceEndpoints;
+import info.nightscout.api.DeviceEndpoints.Iob;
+import info.nightscout.api.DeviceEndpoints.Battery;
+import info.nightscout.api.DeviceEndpoints.PumpStatus;
+import info.nightscout.api.DeviceEndpoints.PumpInfo;
+import info.nightscout.api.DeviceEndpoints.DeviceStatus;
+
+public class NightScoutUpload {
+
+    private static final String TAG = NightscoutUploadIntentService.class.getSimpleName();
+    private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
+
+    public NightScoutUpload () {
+
+    }
+
+    public Boolean doRESTUpload(String url,
+                                String secret,
+                                int uploaderBatteryLevel,
+                                List<PumpStatusEvent> records) {
+        Boolean success = false;
+        try {
+            success = isUploaded(records, url, secret, uploaderBatteryLevel);
+        } catch (Exception e) {
+            Log.e(TAG, "Unable to do REST API Upload to: " + url, e);
+        }
+        return success;
+    }
+
+
+    private boolean isUploaded(List<PumpStatusEvent> records,
+                                 String baseURL,
+                                 String secret,
+                                 int uploaderBatteryLevel) throws Exception {
+
+        UploadApi uploadApi = new UploadApi(baseURL, formToken(secret));
+
+        boolean eventsUploaded = uploadEvents(uploadApi.getGlucoseEndpoints(),
+                 uploadApi.getBolusApi(),
+                 records );
+
+        boolean deviceStatusUploaded = uploadDeviceStatus(uploadApi.getDeviceEndpoints(),
+                uploaderBatteryLevel, records);
+
+        return eventsUploaded && deviceStatusUploaded;
+    }
+
+    private boolean uploadEvents(GlucoseEndpoints glucoseEndpoints,
+                                 BolusEndpoints bolusEndpoints,
+                                 List<PumpStatusEvent> records ) throws Exception {
+
+
+        List<GlucoseEntry> glucoseEntries = new ArrayList<>();
+        List<BolusEntry> bolusEntries = new ArrayList<>();
+
+        for (PumpStatusEvent record : records) {
+
+            GlucoseEntry  glucoseEntry = new GlucoseEntry();
+
+            glucoseEntry.setType("sgv");
+            glucoseEntry.setDirection(EntriesSerializer.getDirectionStringStatus(record.getCgmTrend()));
+            glucoseEntry.setDevice(record.getDeviceName());
+            glucoseEntry.setSgv(record.getSgv());
+            glucoseEntry.setDate(record.getEventDate().getTime());
+            glucoseEntry.setDateString(record.getEventDate().toString());
+
+            glucoseEntries.add(glucoseEntry);
+
+            BolusEntry  bolusEntry = new BolusEntry();
+
+            bolusEntry.setType("mbg");
+            bolusEntry.setDate(record.getEventDate().getTime());
+            bolusEntry.setDateString(record.getEventDate().toString());
+            bolusEntry.setDevice(record.getDeviceName());
+            bolusEntry.setMbg(record.getBolusWizardBGL());
+
+            bolusEntries.add(bolusEntry);
+
+        }
+
+        glucoseEndpoints.sendEntries(glucoseEntries).execute();
+        bolusEndpoints.sendEntries(bolusEntries).execute();
+
+
+
+         return true;
+    }
+
+    private boolean uploadDeviceStatus(DeviceEndpoints deviceEndpoints,
+                                       int uploaderBatteryLevel,
+                                       List<PumpStatusEvent> records) throws Exception {
+
+
+        List<DeviceStatus> deviceEntries = new ArrayList<>();
+        for (PumpStatusEvent record : records) {
+
+            Iob iob = new Iob(record.getPumpDate(), record.getActiveInsulin());
+            Battery battery = new Battery(record.getBatteryPercentage());
+            PumpStatus pumpstatus;
+            if (record.isBolusing()) {
+                pumpstatus = new PumpStatus(true, false, "");
+
+            } else if (record.isSuspended()) {
+                pumpstatus = new PumpStatus(false, true, "");
+            } else {
+                pumpstatus = new PumpStatus(false, false, "normal");
+            }
+
+            PumpInfo pumpInfo = new PumpInfo(
+                    ISO8601_DATE_FORMAT.format(record.getPumpDate()),
+                    new BigDecimal(record.getReservoirAmount()).setScale(3, BigDecimal.ROUND_HALF_UP),
+                    iob,
+                    battery,
+                    pumpstatus
+                    );
+
+            DeviceStatus deviceStatus = new DeviceStatus(
+                    uploaderBatteryLevel,
+                    record.getDeviceName(),
+                    ISO8601_DATE_FORMAT.format(record.getPumpDate()),
+                    pumpInfo
+            );
+
+            deviceEntries.add(deviceStatus);
+        }
+
+        for (DeviceStatus status: deviceEntries) {
+            deviceEndpoints.sendDeviceStatus(status).execute();
+        }
+
+        return true ;
+    }
+
+     @NonNull
+    private String formToken(String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException {
+        MessageDigest digest = MessageDigest.getInstance("SHA-1");
+        byte[] bytes = secret.getBytes("UTF-8");
+        digest.update(bytes, 0, bytes.length);
+        bytes = digest.digest();
+        StringBuilder sb = new StringBuilder(bytes.length * 2);
+        for (byte b : bytes) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
+}
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java
index c613dfbb5112dad61676c85cd04ebe520c9b56af..07cba2e8fdbe2f7bc0ae100d436fdb619b78d910 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutApi.java
@@ -2,7 +2,6 @@ package info.nightscout.android.upload.nightscout;
 
 import retrofit2.Call;
 import retrofit2.http.GET;
-
 /**
  * Created by lgoedhart on 26/06/2016.
  */
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
index 596c6a480293b6aa6ea555085fcf3bb4905c1688..51174e3cfe59108f0b24fc827e0f620f6363e424 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/NightscoutUploadIntentService.java
@@ -10,40 +10,19 @@ import android.preference.PreferenceManager;
 import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 
-import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.BasicResponseHandler;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpParams;
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import java.math.BigDecimal;
-import java.net.URL;
-import java.security.MessageDigest;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 import info.nightscout.android.R;
 import info.nightscout.android.medtronic.MainActivity;
 import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
-import info.nightscout.android.upload.nightscout.serializer.EntriesSerializer;
 import io.realm.Realm;
 import io.realm.RealmResults;
 
 public class NightscoutUploadIntentService extends IntentService {
 
     private static final String TAG = NightscoutUploadIntentService.class.getSimpleName();
-    private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
-    private static final int SOCKET_TIMEOUT = 60 * 1000;
-    private static final int CONNECTION_TIMEOUT = 30 * 1000;
+
     private Context mContext;
     private Realm mRealm;
+    private NightScoutUpload mNightScoutUpload;
 
     public NightscoutUploadIntentService() {
         super(NightscoutUploadIntentService.class.getName());
@@ -63,6 +42,8 @@ public class NightscoutUploadIntentService extends IntentService {
         Log.i(TAG, "onCreate called");
         mContext = this.getBaseContext();
 
+        mNightScoutUpload = new NightScoutUpload();
+
     }
 
     @Override
@@ -84,7 +65,18 @@ public class NightscoutUploadIntentService extends IntentService {
                 if (enableRESTUpload) {
                     long start = System.currentTimeMillis();
                     Log.i(TAG, String.format("Starting upload of %s record using a REST API", records.size()));
-                    doRESTUpload(prefs, records);
+                    String urlSetting = prefs.getString(mContext.getString(R.string.preference_nightscout_url), "");
+                    String secretSetting = prefs.getString(mContext.getString(R.string.preference_api_secret), "YOURAPISECRET");
+                    int uploaderBatteryLevel = MainActivity.batLevel;
+                    Boolean uploadSuccess = mNightScoutUpload.doRESTUpload(urlSetting,
+                            secretSetting, uploaderBatteryLevel, records);
+                    if (uploadSuccess) {
+                        mRealm.beginTransaction();
+                        for (PumpStatusEvent updateRecord : records) {
+                            updateRecord.setUploaded(true);
+                        }
+                        mRealm.commitTransaction();
+                    }
                     Log.i(TAG, String.format("Finished upload of %s record using a REST API in %s ms", records.size(), System.currentTimeMillis() - start));
                 }
             } catch (Exception e) {
@@ -98,217 +90,6 @@ public class NightscoutUploadIntentService extends IntentService {
         NightscoutUploadReceiver.completeWakefulIntent(intent);
     }
 
-    private void doRESTUpload(SharedPreferences prefs, RealmResults<PumpStatusEvent> records) {
-        String apiScheme = "https://";
-        String apiUrl = "";
-        String apiSecret = prefs.getString(mContext.getString(R.string.preference_api_secret), "YOURAPISECRET");
-
-        // TODO - this code needs to go to the Settings Activity.
-        // Add the extra match for "KEY@" to support the previous single field
-        Pattern p = Pattern.compile("(.*\\/\\/)?(.*@)?([^\\/]*)(.*)");
-        Matcher m = p.matcher(prefs.getString(mContext.getString(R.string.preference_nightscout_url), ""));
-
-        if (m.find()) {
-            apiUrl = m.group(3);
-
-            // Only override apiSecret from URL (the "old" way), if the API secret preference is empty
-            if (apiSecret.equals("YOURAPISECRET") || apiSecret.equals("")) {
-                apiSecret = (m.group(2) == null) ? "" : m.group(2).replace("@", "");
-            }
-
-            // Override the URI scheme if it's been provided in the preference)
-            if (m.group(1) != null && !m.group(1).equals("")) {
-                apiScheme = m.group(1);
-            }
-        }
-
-        // Update the preferences to match what we expect. Only really used from converting from the
-        // old format to the new format. Aren't we nice for managing backward compatibility?
-        prefs.edit().putString(mContext.getString(R.string.preference_api_secret), apiSecret).apply();
-        prefs.edit().putString(mContext.getString(R.string.preference_nightscout_url), String.format("%s%s", apiScheme, apiUrl)).apply();
-
-        String uploadUrl = String.format("%s%s@%s/api/v1/", apiScheme, apiSecret, apiUrl);
-
-        try {
-            doRESTUploadTo(uploadUrl, records);
-        } catch (Exception e) {
-            Log.e(TAG, "Unable to do REST API Upload to: " + uploadUrl, e);
-        }
-    }
-
-    private void doRESTUploadTo(String baseURI, RealmResults<PumpStatusEvent> records) {
-        try {
-            String baseURL;
-            String secret = null;
-            String[] uriParts = baseURI.split("@");
-
-            if (uriParts.length == 1) {
-                throw new Exception("Starting with API v1, a pass phase is required");
-            } else if (uriParts.length == 2) {
-                secret = uriParts[0];
-                baseURL = uriParts[1];
-
-                // new format URL!
-                if (secret.contains("http")) {
-                    if (secret.contains("https")) {
-                        baseURL = "https://" + baseURL;
-                    } else {
-                        baseURL = "http://" + baseURL;
-                    }
-                    String[] uriParts2 = secret.split("//");
-                    secret = uriParts2[1];
-                }
-            } else {
-                throw new Exception(String.format("Unexpected baseURI: %s, uriParts.length: %s", baseURI, uriParts.length));
-            }
-
-            JSONArray devicestatusBody = new JSONArray();
-            JSONArray entriesBody = new JSONArray();
-
-            for (PumpStatusEvent record : records) {
-                addDeviceStatus(devicestatusBody, record);
-                addSgvEntry(entriesBody, record);
-                addMbgEntry(entriesBody, record);
-            }
-
-            boolean isUploaded = uploadToNightscout(new URL(baseURL + "/entries"), secret, entriesBody);
-
-            for(int i = 0; isUploaded && i < devicestatusBody.length(); i++) {
-                isUploaded &= uploadToNightscout(new URL(baseURL + "/devicestatus"), secret, devicestatusBody.getJSONObject(i));
-            }
-
-            if (isUploaded) {
-                // Yay! We uploaded. Tell Realm
-                // FIXME - check the upload succeeded!
-                mRealm.beginTransaction();
-                for (PumpStatusEvent updateRecord : records) {
-                    updateRecord.setUploaded(true);
-                }
-                mRealm.commitTransaction();
-            }
-
-        } catch (Exception e) {
-            Log.e(TAG, "Unable to post data", e);
-        }
-    }
-
-    private boolean uploadToNightscout(URL endpoint, String secret, JSONObject httpBody) throws Exception {
-        return uploadToNightscout(endpoint, secret, httpBody.toString());
-    }
-
-    private boolean uploadToNightscout(URL endpoint, String secret, JSONArray httpBody) throws Exception {
-        return uploadToNightscout(endpoint, secret, httpBody.toString());
-    }
-
-    private boolean uploadToNightscout(URL endpoint, String secret, String httpBody) throws Exception {
-        Log.i(TAG, "postURL: " + endpoint.toString());
-
-        HttpPost post = new HttpPost(endpoint.toString());
-
-        if (secret == null || secret.isEmpty()) {
-            throw new Exception("Starting with API v1, a pass phase is required");
-        } else {
-            MessageDigest digest = MessageDigest.getInstance("SHA-1");
-            byte[] bytes = secret.getBytes("UTF-8");
-            digest.update(bytes, 0, bytes.length);
-            bytes = digest.digest();
-            StringBuilder sb = new StringBuilder(bytes.length * 2);
-            for (byte b : bytes) {
-                sb.append(String.format("%02x", b & 0xff));
-            }
-            String token = sb.toString();
-            post.setHeader("api-secret", token);
-        }
-
-        HttpParams params = new BasicHttpParams();
-        HttpConnectionParams.setSoTimeout(params, SOCKET_TIMEOUT);
-        HttpConnectionParams.setConnectionTimeout(params, CONNECTION_TIMEOUT);
-
-        DefaultHttpClient httpclient = new DefaultHttpClient(params);
-
-        Log.i(TAG, "Upload JSON: " + httpBody);
-
-        try {
-            StringEntity se = new StringEntity(httpBody);
-            post.setEntity(se);
-            post.setHeader("Accept", "application/json");
-            post.setHeader("Content-type", "application/json");
-
-            ResponseHandler responseHandler = new BasicResponseHandler();
-            httpclient.execute(post, responseHandler);
-        } catch (Exception e) {
-            Log.w(TAG, "Unable to post data to: '" + post.getURI().toString() + "'", e);
-            return false;
-        }
-
-        return true;
-    }
-
-    private void addDeviceStatus(JSONArray devicestatusArray, PumpStatusEvent record) throws Exception {
-        JSONObject json = new JSONObject();
-        json.put("uploaderBattery", MainActivity.batLevel);
-        json.put("device", record.getDeviceName());
-        json.put("created_at", ISO8601_DATE_FORMAT.format(record.getPumpDate()));
-
-        JSONObject pumpInfo = new JSONObject();
-        pumpInfo.put("clock", ISO8601_DATE_FORMAT.format(record.getPumpDate()));
-        pumpInfo.put("reservoir", new BigDecimal(record.getReservoirAmount()).setScale(3, BigDecimal.ROUND_HALF_UP));
-
-        JSONObject iob = new JSONObject();
-        iob.put("timestamp", record.getPumpDate());
-        iob.put("bolusiob", record.getActiveInsulin());
-
-        JSONObject status = new JSONObject();
-        if (record.isBolusing()) {
-            status.put("bolusing", true);
-        } else if (record.isSuspended()) {
-            status.put("suspended", true);
-        } else {
-            status.put("status", "normal");
-        }
-
-        JSONObject battery = new JSONObject();
-        battery.put("percent", record.getBatteryPercentage());
-
-        pumpInfo.put("iob", iob);
-        pumpInfo.put("battery", battery);
-        pumpInfo.put("status", status);
-
-        json.put("pump", pumpInfo);
-        String jsonString = json.toString();
-        Log.i(TAG, "Device Status JSON: " + jsonString);
-
-        devicestatusArray.put(json);
-    }
-
-    private void addSgvEntry(JSONArray entriesArray, PumpStatusEvent pumpRecord) throws Exception {
-        JSONObject json = new JSONObject();
-        // TODO replace with Retrofit/EntriesSerializer
-        json.put("sgv", pumpRecord.getSgv());
-        json.put("direction", EntriesSerializer.getDirectionString(pumpRecord.getCgmTrend()));
-        json.put("device", pumpRecord.getDeviceName());
-        json.put("type", "sgv");
-        json.put("date", pumpRecord.getEventDate().getTime());
-        json.put("dateString", pumpRecord.getEventDate());
-
-        entriesArray.put(json);
-    }
-
-    private void addMbgEntry(JSONArray entriesArray, PumpStatusEvent pumpRecord) throws Exception {
-        if (pumpRecord.hasRecentBolusWizard()) {
-            JSONObject json = new JSONObject();
-
-            // TODO replace with Retrofit/EntriesSerializer
-            json.put("type", "mbg");
-            json.put("mbg", pumpRecord.getBolusWizardBGL());
-            json.put("device", pumpRecord.getDeviceName());
-            json.put("date", pumpRecord.getEventDate().getTime());
-            json.put("dateString", pumpRecord.getEventDate());
-
-            entriesArray.put(json);
-        }
-    }
-
     private boolean isOnline() {
         ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo netInfo = cm.getActiveNetworkInfo();
@@ -320,4 +101,6 @@ public class NightscoutUploadIntentService extends IntentService {
 
         public static final String EXTENDED_DATA = "info.nightscout.android.upload.nightscout.DATA";
     }
+
+
 }
diff --git a/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java b/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
index 260b8c3b2acab0a24e81dd6c35dee9f9872f4e21..ce79ab7900ef741ecb3c8f35550eebd019f34d69 100644
--- a/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
+++ b/app/src/main/java/info/nightscout/android/upload/nightscout/serializer/EntriesSerializer.java
@@ -42,6 +42,35 @@ public class EntriesSerializer implements JsonSerializer<PumpStatusEvent> {
         }
     }
 
+    public static String getDirectionStringStatus(PumpStatusEvent.CGM_TREND trend) {
+        switch( trend ) {
+            case NONE:
+                return "NONE";
+            case DOUBLE_UP:
+                return "DoubleUp";
+            case SINGLE_UP:
+                return "SingleUp";
+            case FOURTY_FIVE_UP:
+                return "FortyFiveUp";
+            case FLAT:
+                return "Flat";
+            case FOURTY_FIVE_DOWN:
+                return "FortyFiveDown";
+            case SINGLE_DOWN:
+                return "SingleDown";
+            case DOUBLE_DOWN:
+                return "DoubleDown";
+            case NOT_COMPUTABLE:
+                return "NOT COMPUTABLE";
+            case RATE_OUT_OF_RANGE:
+                return "RATE OUT OF RANGE";
+            case NOT_SET:
+                return "NONE";
+            default:
+                return "NOT COMPUTABLE"; // TODO - should this be something else?
+        }
+    }
+
     @Override
     public JsonElement serialize(PumpStatusEvent src, Type typeOfSrc, JsonSerializationContext context) {
         final JsonObject jsonObject = new JsonObject();
diff --git a/app/src/main/java/info/nightscout/api/BolusEndpoints.java b/app/src/main/java/info/nightscout/api/BolusEndpoints.java
new file mode 100644
index 0000000000000000000000000000000000000000..67d2291198532976c64d25eae16718087cb28f43
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/BolusEndpoints.java
@@ -0,0 +1,76 @@
+package info.nightscout.api;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.Headers;
+import retrofit2.http.POST;
+
+public interface BolusEndpoints {
+
+    class BolusEntry {
+        String type;
+        String dateString;
+        float date;
+        float mbg;
+        String device;
+
+        public BolusEntry() {  }
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        public String getDateString() {
+            return dateString;
+        }
+
+        public void setDateString(String dateString) {
+            this.dateString = dateString;
+        }
+
+        public float getDate() {
+            return date;
+        }
+
+        public void setDate(float date) {
+            this.date = date;
+        }
+
+        public float getMbg() {
+            return mbg;
+        }
+
+        public void setMbg(float mbg) {
+            this.mbg = mbg;
+        }
+
+        public String getDevice() {
+            return device;
+        }
+
+        public void setDevice(String device) {
+            this.device = device;
+        }
+
+    }
+
+    @Headers({
+            "Accept: application/json",
+            "Content-type: application/json"
+    })
+    @POST("/api/v1/entries")
+    Call<ResponseBody> sendEntries(@Body List<BolusEntry> entries);
+
+}
+
+
+
diff --git a/app/src/main/java/info/nightscout/api/DeviceEndpoints.java b/app/src/main/java/info/nightscout/api/DeviceEndpoints.java
new file mode 100644
index 0000000000000000000000000000000000000000..1bf66b24336e790d69c464ed1acb419c029d433d
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/DeviceEndpoints.java
@@ -0,0 +1,97 @@
+package info.nightscout.api;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.Header;
+import retrofit2.http.Headers;
+import retrofit2.http.POST;
+
+public interface DeviceEndpoints {
+
+    class Iob {
+        final Date timestamp;
+        final float bolusiob;
+        public Iob (Date timestamp,
+             float bolusiob) {
+            this.timestamp = timestamp;
+            this.bolusiob = bolusiob;
+        }
+    }
+
+    class Battery {
+        final short percent;
+        public Battery(short percent) {
+            this.percent = percent;
+        }
+    }
+
+    class PumpStatus {
+        final Boolean bolusing;
+        final Boolean suspended;
+        final String status;
+        public PumpStatus(
+                Boolean bolusing,
+                Boolean suspended,
+                String status
+
+        ) {
+            this.bolusing = bolusing;
+            this.suspended = suspended;
+            this.status = status;
+
+        }
+    }
+
+    class PumpInfo {
+        final String clock;
+        final BigDecimal reservoir;
+        final Iob iob;
+        final Battery battery;
+        final PumpStatus status;
+
+        public PumpInfo(String clock,
+                 BigDecimal reservoir,
+                 Iob iob,
+                 Battery battery,
+                 PumpStatus status) {
+            this.clock = clock;
+            this.reservoir = reservoir;
+            this.iob = iob;
+            this.battery = battery;
+            this.status = status;
+
+        }
+    }
+
+    class DeviceStatus {
+        final Integer uploaderBattery;
+        final String device;
+        final String created_at;
+        final PumpInfo pump;
+
+        public DeviceStatus(Integer uploaderBattery,
+                     String device,
+                     String created_at,
+                     PumpInfo pump) {
+            this.uploaderBattery = uploaderBattery;
+            this.device = device;
+            this.created_at = created_at;
+            this.pump = pump;
+        }
+    }
+
+    @Headers({
+            "Accept: application/json",
+            "Content-type: application/json"
+    })
+    @POST("/api/v1/devicestatus")
+    Call<ResponseBody> sendDeviceStatus(@Body DeviceStatus deviceStatus);
+
+}
+
+
+
diff --git a/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java b/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java
new file mode 100644
index 0000000000000000000000000000000000000000..07c1c10a8c2e60705ba348d7c9a0758216f74b1a
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/GlucoseEndpoints.java
@@ -0,0 +1,89 @@
+package info.nightscout.api;
+
+
+
+import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.GET;
+import retrofit2.http.Headers;
+import retrofit2.http.POST;
+
+public interface GlucoseEndpoints {
+
+    class GlucoseEntry {
+
+        String type;
+        String dateString;
+        float date;
+        float sgv;
+        String direction;
+        String device;
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        public String getDateString() {
+            return dateString;
+        }
+
+        public void setDateString(String dateString) {
+            this.dateString = dateString;
+        }
+
+        public float getDate() {
+            return date;
+        }
+
+        public void setDate(float date) {
+            this.date = date;
+        }
+
+        public float getSgv() {
+            return sgv;
+        }
+
+        public void setSgv(float sgv) {
+            this.sgv = sgv;
+        }
+
+        public String getDirection() {
+            return direction;
+        }
+
+        public void setDirection(String direction) {
+            this.direction = direction;
+        }
+
+        public String getDevice() {
+            return device;
+        }
+
+        public void setDevice(String device) {
+            this.device = device;
+        }
+
+        public GlucoseEntry() {  }
+    }
+
+    @Headers({
+            "Accept: application/json",
+            "Content-type: application/json"
+    })
+    @POST("/api/v1/entries")
+    Call<ResponseBody> sendEntries(@Body List<GlucoseEntry> entries);
+
+}
+
+
+
diff --git a/app/src/main/java/info/nightscout/api/UploadApi.java b/app/src/main/java/info/nightscout/api/UploadApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c429b7379d21f7342a199b7c50d1ff87aebe043
--- /dev/null
+++ b/app/src/main/java/info/nightscout/api/UploadApi.java
@@ -0,0 +1,78 @@
+package info.nightscout.api;
+
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.logging.HttpLoggingInterceptor;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class UploadApi {
+    private Retrofit retrofit;
+    private GlucoseEndpoints glucoseEndpoints;
+    private BolusEndpoints bolusApi;
+    private DeviceEndpoints deviceEndpoints;
+
+    public GlucoseEndpoints getGlucoseEndpoints() {
+        return glucoseEndpoints;
+    }
+
+    public BolusEndpoints getBolusApi() {
+        return bolusApi;
+    }
+
+    public DeviceEndpoints getDeviceEndpoints() {
+        return deviceEndpoints;
+    }
+
+    public UploadApi(String baseURL, String token) {
+
+        class AddAuthHeader implements Interceptor {
+
+            private String token;
+
+            public AddAuthHeader(String token) {
+                this.token = token;
+            }
+
+            @Override
+            public Response intercept(Interceptor.Chain chain) throws IOException {
+                Request original = chain.request();
+
+                Request.Builder requestBuilder = original.newBuilder()
+                        .header("api-secret", token)
+                        .method( original.method(), original.body());
+
+                Request request = requestBuilder.build();
+                return chain.proceed(request);
+            }
+        };
+
+        OkHttpClient.Builder okHttpClient = new OkHttpClient().newBuilder()
+                .connectTimeout(30, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS);
+
+        okHttpClient.addInterceptor(new AddAuthHeader(token));
+
+        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
+        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
+        okHttpClient.addInterceptor(logging);
+
+        retrofit = new Retrofit.Builder()
+                .baseUrl(baseURL)
+                .client(okHttpClient.build())
+                .addConverterFactory(GsonConverterFactory.create())
+                .build();
+
+        glucoseEndpoints = retrofit.create(GlucoseEndpoints.class);
+        bolusApi = retrofit.create(BolusEndpoints.class);
+        deviceEndpoints = retrofit.create(DeviceEndpoints.class);
+
+    }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 580e85d04a9bbe67a3b112aa026ec9c260224707..b403419f414cf3f94125d7f47ae87e0e7f14e5b7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -25,9 +25,11 @@
     <string name="action_sign_in_short">Retrieve keys</string>
     <string name="error_invalid_password">Password is required</string>
     <string name="error_incorrect_password">The Username or password is incorrect</string>
+    <string name="error_client_protocol_exception">Could not communicate with server.</string>
+    <string name="error_io_exception">Could not connect to server.</string>
+    <string name="error_class_not_found_exception">Application code error.</string>
+    <string name="error_http_response">Server responded with error. Could be username or password problem.</string>
     <string name="error_field_required">This field is required</string>
-    <string name="preference_nightscout_url">Nightscout URL</string>
-    <string name="preference_api_secret">API SECRET</string>
     <string name="prompt_carelink_username_password">Please enter your CareLink details.\nThey will not be stored.</string>
     <string name="close">Close</string>
     <string name="register_contour_next_link">Registered Devices</string>
@@ -51,6 +53,8 @@
     <string name="dummy_content">DUMMY\nCONTENT</string>
     <string name="menu_name_status">Status</string>
     <string name="menu_name_battery_status">unknown</string>
+    <string name="preference_api_secret">YOUR.API.SECRET</string>
+    <string name="preference_nightscout_url">YOUR.NIGHTSCOUT.URL</string>
 
     <string name="preferences_poll_interval">Poll interval</string>
     <string name="preferences_low_battery_poll_interval">Poll interval on low pump battery</string>
@@ -58,4 +62,5 @@
     <string name="to_register_a_contour_next_link_you_must_first_plug_it_in_and_get_a_reading_from_the_pump">To register a Contour Next Link you must first plug it in, and get a reading from the pump.</string>
     <string name="serial_number">Serial number</string>
     <string name="preferences_chart_interval">Chart Zoom</string>
+
 </resources>