change api specs
diff --git a/api.go b/api.go
index 98c7e16..c1c7643 100644
--- a/api.go
+++ b/api.go
@@ -56,7 +56,7 @@
 
 const (
 	sqlTimeFormat    = "2006-01-02 15:04:05.999 -0700 MST"
-	iso8601          = "2006-01-02T15:04:05.999Z07:00"
+	iso8601          = "2 mnn006-01-02T15:04:05.999Z07:00"
 	sqliteTimeFormat = "2006-01-02 15:04:05.999-07:00"
 	changeTimeFormat = "2006-01-02 15:04:05.999"
 )
@@ -136,7 +136,7 @@
 	services.API().HandleFunc(a.blobEndpoint, a.apiReturnBlobData).Methods("GET")
 	services.API().HandleFunc(a.configStatusEndpoint, a.apiPutConfigStatus).Methods("PUT")
 	services.API().HandleFunc(a.heartbeatEndpoint, a.apiPutHeartbeat).Methods("PUT")
-	services.API().HandleFunc(a.registerEndpoint, a.apiPostRegister).Methods("POST")
+	services.API().HandleFunc(a.registerEndpoint, a.apiPutRegister).Methods("POST")
 	a.apiInitialized = true
 	log.Debug("API endpoints initialized")
 }
@@ -365,68 +365,79 @@
 	w.Write(b)
 }
 
-func (a *apiManager) apiPostRegister(w http.ResponseWriter, r *http.Request) {
+func (a *apiManager) apiPutRegister(w http.ResponseWriter, r *http.Request) {
 	vars := mux.Vars(r)
 	uuid := vars["uuid"]
-	if !isValidUuid(uuid) {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing gateway uuid")
-		return
-	}
-	created := r.Header.Get("created")
-	if created == "" {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing created")
-		return
-	}
-	name := r.Header.Get("name")
-	if name == "" {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing name")
+
+	// parse body
+
+	body := r.Body
+	defer body.Close()
+	bodyBytes, err := ioutil.ReadAll(body)
+	if err != nil {
+		log.Errorf("apiPutRegister error: %v", err)
+		a.writeError(w, http.StatusInternalServerError, API_ERR_INTERNAL, "Failed to read request body.")
 		return
 	}
 
-	pod := r.Header.Get("pod")
-	podType := r.Header.Get("podtype")
-	serviceType := r.Header.Get("type")
+	reqBody := &registerBody{}
+	err = json.Unmarshal(bodyBytes, reqBody)
+	if err != nil {
+		log.Errorf("apiPutRegister error: %v", err)
+		a.writeError(w, http.StatusInternalServerError, API_ERR_INTERNAL, "Failed to read request body.")
+		return
+	}
 
-	trackerResp := a.trackerCl.postRegister(uuid, pod, created, name, podType, serviceType)
+	isValid, reason := reqBody.validateBody(uuid)
+	if !isValid {
+		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, reason)
+		return
+	}
+
+	trackerResp := a.trackerCl.putRegister(uuid, reqBody)
 	switch trackerResp.code {
 	case http.StatusOK:
-		a.writePostRegisterResp(w, trackerResp)
+		a.writePutRegisterResp(w, trackerResp)
 	default:
-		log.Infof("putConfigStatus code: %v Reason: %v", trackerResp.code, trackerResp.errString)
-		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, trackerResp.errString)
+		log.Infof("apiPutRegister code: %v Reason: %v", trackerResp.code, trackerResp.body)
+		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, string(trackerResp.body))
 	}
 
 }
 
 func (a *apiManager) apiPutConfigStatus(w http.ResponseWriter, r *http.Request) {
 
-	configId := r.URL.Query().Get("configid")
-	if configId == "" {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing configId")
+	// parse body
+
+	body := r.Body
+	defer body.Close()
+	bodyBytes, err := ioutil.ReadAll(body)
+	if err != nil {
+		log.Errorf("apiPutConfigStatus error: %v", err)
+		a.writeError(w, http.StatusInternalServerError, API_ERR_INTERNAL, "Failed to read request body.")
 		return
 	}
-	uuid := r.Header.Get("uuid")
-	if !isValidUuid(uuid) {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing gateway uuid")
+
+	reqBody := &configStatusBody{}
+	err = json.Unmarshal(bodyBytes, reqBody)
+	if err != nil {
+		log.Errorf("apiPutConfigStatus error: %v", err)
+		a.writeError(w, http.StatusInternalServerError, API_ERR_INTERNAL, "Failed to read request body.")
 		return
 	}
-	status := r.Header.Get("status")
-	if status == "" {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing status")
+
+	isValid, reason := reqBody.validateBody()
+	if !isValid {
+		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, reason)
 		return
 	}
-	created := r.Header.Get("created")
-	if created == "" {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing created")
-		return
-	}
-	trackerResp := a.trackerCl.putConfigStatus(configId, status, uuid, created)
+	trackerResp := a.trackerCl.putConfigStatus(reqBody)
 	switch trackerResp.code {
 	case http.StatusOK:
 		a.writeConfigStatusResp(w, trackerResp)
 	default:
-		log.Infof("putConfigStatus code: %v Reason: %v", trackerResp.code, trackerResp.errString)
-		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, trackerResp.errString)
+		log.Infof("apiPutConfigStatus code: %v Reason: %v", trackerResp.code, trackerResp.body)
+		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, string(trackerResp.body))
 	}
 }
 
@@ -437,31 +448,46 @@
 		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing gateway uuid")
 		return
 	}
-	updated := r.Header.Get("updated")
-	if updated == "" {
-		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing updated")
+	reported := r.Header.Get("reportedTime")
+	if reported == "" {
+		a.writeError(w, http.StatusBadRequest, API_ERR_INVALID_PARAMETERS, "Bad/Missing reportedTime")
 		return
 	}
-	trackerResp := a.trackerCl.putHeartbeat(uuid, updated)
+	trackerResp := a.trackerCl.putHeartbeat(uuid, reported)
 	switch trackerResp.code {
 	case http.StatusOK:
 		a.writePutHeartbeatResp(w, trackerResp)
 	default:
-		log.Infof("putConfigStatus code: %v Reason: %v", trackerResp.code, trackerResp.errString)
-		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, trackerResp.errString)
+		log.Infof("apiPutHeartbeat code: %v Reason: %v", trackerResp.code, trackerResp.body)
+		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, string(trackerResp.body))
 	}
 }
 
-func (a *apiManager) writeConfigStatusResp(w http.ResponseWriter, tr trackerResponse) {
+func (a *apiManager) writeConfigStatusResp(w http.ResponseWriter, tr *trackerResponse) {
 	w.Header().Add("Content-type", tr.contentType)
+	_, err := w.Write(tr.body)
+	if err != nil {
+		log.Errorf("failed to write response: %v", err)
+		a.writeError(w, http.StatusInternalServerError, API_ERR_INTERNAL, err.Error())
+	}
 }
 
-func (a *apiManager) writePostRegisterResp(w http.ResponseWriter, tr trackerResponse) {
+func (a *apiManager) writePutRegisterResp(w http.ResponseWriter, tr *trackerResponse) {
 	w.Header().Add("Content-type", tr.contentType)
+	_, err := w.Write(tr.body)
+	if err != nil {
+		log.Errorf("failed to write response: %v", err)
+		a.writeError(w, http.StatusInternalServerError, API_ERR_INTERNAL, err.Error())
+	}
 }
 
-func (a *apiManager) writePutHeartbeatResp(w http.ResponseWriter, tr trackerResponse) {
+func (a *apiManager) writePutHeartbeatResp(w http.ResponseWriter, tr *trackerResponse) {
 	w.Header().Add("Content-type", tr.contentType)
+	_, err := w.Write(tr.body)
+	if err != nil {
+		log.Errorf("failed to write response: %v", err)
+		a.writeError(w, http.StatusInternalServerError, API_ERR_INTERNAL, err.Error())
+	}
 }
 
 // call whenever the list of deployments changes
@@ -520,3 +546,56 @@
 	}
 	return r.MatchString(uuid)
 }
+
+type registerBody struct {
+	Uuid         string `json:"uuid"`
+	Pod          string `json:"pod"`
+	PodType      string `json:"podType"`
+	ReportedTime string `json:"reportedTime"`
+	Name         string `json:"name"`
+	Type         string `json:"type"`
+}
+
+func (body *registerBody) validateBody(uuid string) (bool, string) {
+	switch {
+	case uuid != body.Uuid:
+		return false, "UUID in path mismatch UUID in body"
+	case !isValidUuid(body.Uuid):
+		return false, "Bad/Missing gateway UUID"
+	case body.ReportedTime == "":
+		return false, "Bad/Missing gateway ReportedTimeService"
+	}
+	return true, ""
+}
+
+type configStatusBody struct {
+	StatusDetails []statusDetailsJson `json:"statusDetails"`
+	ServiceId     string              `json:"serviceId"`
+	ReportedTime  string              `json:"reportedTime"`
+}
+
+type statusDetailsJson struct {
+	Status          string `json:"status"`
+	ConfigurationId string `json:"configurationId"`
+	ErrorCode       string `json:"errorCode"`
+	Message         string `json:"message"`
+}
+
+func (body *configStatusBody) validateBody() (bool, string) {
+	switch {
+	case !isValidUuid(body.ServiceId):
+		return false, "Bad/Missing gateway ServiceId"
+	case body.ReportedTime == "":
+		return false, "Bad/Missing gateway ReportedTimeService"
+	}
+
+	for _, s := range body.StatusDetails {
+		switch {
+		case s.Status == "":
+			return false, "Bad/Missing configuration Status"
+		case s.ConfigurationId == "":
+			return false, "Bad/Missing configuration ConfigurationId"
+		}
+	}
+	return true, ""
+}
diff --git a/clients.go b/clients.go
index dab68ce..6e47829 100644
--- a/clients.go
+++ b/clients.go
@@ -1,7 +1,8 @@
 package apiGatewayConfDeploy
 
 import (
-	"github.com/30x/apid-core"
+	"bytes"
+	"encoding/json"
 	"io/ioutil"
 	"net/http"
 	"net/url"
@@ -9,6 +10,7 @@
 )
 
 const (
+	configBearerToken           = "apigeesync_bearer_token"
 	trackerConfigStatusEndpoint = "/serviceconfigstatus"
 	trackerHeartbeatEndpoint    = "/serviceheartbeat/{uuid}"
 	trackerRegisterEndpoint     = "/serviceregister/{uuid}"
@@ -16,37 +18,34 @@
 )
 
 type trackerClientInterface interface {
-	putConfigStatus(configId, status, uuid, created string) trackerResponse
-	postRegister(uuid, pod, created, name, podType, serviceType string) trackerResponse
-	putHeartbeat(uuid, updated string) trackerResponse
+	putConfigStatus(body *configStatusBody) *trackerResponse
+	putRegister(uuid string, body *registerBody) *trackerResponse
+	putHeartbeat(uuid, reportedTime string) *trackerResponse
 }
 
 type trackerResponse struct {
 	code        int
 	contentType string
-	errString   string
+	body        []byte
 }
 
 type trackerClient struct {
 	trackerBaseUrl string
 	clusterId      string
 	httpclient     *http.Client
-	handler        *tokenEventHandler
 }
 
-func (t *trackerClient) putConfigStatus(configId, status, uuid, created string) trackerResponse {
-	uri, err := url.Parse(t.trackerBaseUrl + strings.Replace(trackerConfigStatusEndpoint, "{uuid}", uuid, 1))
+func (t *trackerClient) putConfigStatus(reqBody *configStatusBody) *trackerResponse {
+	uri, err := url.Parse(t.trackerBaseUrl + trackerConfigStatusEndpoint)
 	if err != nil {
 		log.Errorf("putConfigStatus failed to parse tracker uri: %v", err)
 		return (internalError(err))
 	}
-	req, err := http.NewRequest("PUT", uri.String(), nil)
-	req.Header.Add("configid", configId)
-	req.Header.Add("Authorization", t.handler.getBearerToken())
-	req.Header.Add("status", status)
-	req.Header.Add("uuid", uuid)
-	req.Header.Add("created", created)
-	req.Header.Add("clusterid", t.clusterId)
+
+	bodyBytes, err := json.Marshal(*reqBody)
+
+	req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(bodyBytes))
+	req.Header.Add("Authorization", getBearerToken())
 
 	r, err := t.httpclient.Do(req)
 	if err != nil {
@@ -54,45 +53,33 @@
 		return (internalError(err))
 	}
 	defer r.Body.Close()
-	res := trackerResponse{}
-	switch r.StatusCode {
-	case http.StatusOK:
-		res.code = r.StatusCode
-		res.contentType = r.Header.Get("Content-type")
-	case http.StatusUnauthorized, http.StatusForbidden:
-		res.code = http.StatusInternalServerError
-		res.errString = "apid token rejected by tracker"
-		return res
-	default:
-		if 400 <= res.code && res.code < 500 {
-			res.code = http.StatusInternalServerError
-		} else {
-			res.code = r.StatusCode
-		}
-		res.contentType = r.Header.Get("Content-type")
-		body, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			return (internalError(err))
-		}
-		res.errString = string(body)
-	}
-	return res
+
+	return parseTrackerResponse(r)
 }
 
-func (t *trackerClient) postRegister(uuid, pod, created, name, podType, serviceType string) trackerResponse {
+func (t *trackerClient) putRegister(uuid string, reqBody *registerBody) *trackerResponse {
 	uri, err := url.Parse(t.trackerBaseUrl + strings.Replace(trackerRegisterEndpoint, "{uuid}", uuid, 1))
 	if err != nil {
 		log.Errorf("postRegister failed to parse tracker uri: %v", err)
 		return (internalError(err))
 	}
-	req, err := http.NewRequest("PUT", uri.String(), nil)
-	req.Header.Add("Authorization", t.handler.getBearerToken())
-	req.Header.Add("pod", pod)
-	req.Header.Add("podtype", podType)
-	req.Header.Add("created", created)
-	req.Header.Add("name", name)
-	req.Header.Add("type", serviceType)
-	req.Header.Add("clusterid", t.clusterId)
+
+	body := serviceRegisterBody{
+		ClusterId:    t.clusterId,
+		Pod:          reqBody.Pod,
+		PodType:      reqBody.Type,
+		ReportedTime: reqBody.ReportedTime,
+		Name:         reqBody.Name,
+		Type:         reqBody.Type,
+	}
+
+	bodyBytes, err := json.Marshal(body)
+	if err != nil {
+		return (internalError(err))
+	}
+
+	req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(bodyBytes))
+	req.Header.Add("Authorization", getBearerToken())
 
 	r, err := t.httpclient.Do(req)
 	if err != nil {
@@ -100,41 +87,18 @@
 		return (internalError(err))
 	}
 	defer r.Body.Close()
-	res := trackerResponse{}
-	switch r.StatusCode {
-	case http.StatusOK:
-		res.code = r.StatusCode
-		res.contentType = r.Header.Get("Content-type")
-	case http.StatusUnauthorized, http.StatusForbidden:
-		res.code = http.StatusInternalServerError
-		res.errString = "apid token rejected by tracker"
-		return res
-	default:
-		if 400 <= res.code && res.code < 500 {
-			res.code = http.StatusInternalServerError
-		} else {
-			res.code = r.StatusCode
-		}
-		res.contentType = r.Header.Get("Content-type")
-		body, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			return (internalError(err))
-		}
-		res.errString = string(body)
-	}
-	return res
+	return parseTrackerResponse(r)
 }
 
-func (t *trackerClient) putHeartbeat(uuid, updated string) trackerResponse {
+func (t *trackerClient) putHeartbeat(uuid, reported string) *trackerResponse {
 	uri, err := url.Parse(t.trackerBaseUrl + strings.Replace(trackerHeartbeatEndpoint, "{uuid}", uuid, 1))
 	if err != nil {
 		log.Errorf("putHeartbeat failed to parse tracker uri: %v", err)
 		return internalError(err)
 	}
 	req, err := http.NewRequest("PUT", uri.String(), nil)
-	req.Header.Add("Authorization", t.handler.getBearerToken())
-	req.Header.Add("updated", updated)
-	req.Header.Add("clusterid", t.clusterId)
+	req.Header.Add("Authorization", getBearerToken())
+	req.Header.Add("reportedTime", reported)
 
 	r, err := t.httpclient.Do(req)
 	if err != nil {
@@ -142,52 +106,54 @@
 		return internalError(err)
 	}
 	defer r.Body.Close()
-	res := trackerResponse{}
+	return parseTrackerResponse(r)
+}
+
+func internalError(err error) *trackerResponse {
+	res := &trackerResponse{}
+	res.code = http.StatusInternalServerError
+	res.body = []byte(err.Error())
+	return res
+}
+
+func getBearerToken() string {
+	return "Bearer " + config.GetString(configBearerToken)
+}
+
+func parseTrackerResponse(r *http.Response) *trackerResponse {
+	trackerBody, err := ioutil.ReadAll(r.Body)
+	if err != nil {
+		log.Errorf("apid failed to read response body: %v", err)
+		return (internalError(err))
+	}
+	res := &trackerResponse{}
 	switch r.StatusCode {
 	case http.StatusOK:
 		res.code = r.StatusCode
+		res.body = trackerBody
 		res.contentType = r.Header.Get("Content-type")
 	case http.StatusUnauthorized, http.StatusForbidden:
 		res.code = http.StatusInternalServerError
-		res.errString = "apid token rejected by tracker"
-		return res
+		res.body = []byte("apid token rejected by tracker")
+		log.Errorf("%v: %v, %v", res.body, r.StatusCode, trackerBody)
+	case http.StatusNotFound:
+		res.code = http.StatusInternalServerError
+		res.body = []byte("apid cannot connect to tracker")
+		log.Errorf("%v: %v, %v", res.body, r.StatusCode, trackerBody)
 	default:
-		if 400 <= res.code && res.code < 500 {
-			res.code = http.StatusInternalServerError
-		} else {
-			res.code = r.StatusCode
-		}
+		log.Infof("Abnormal Response from Tracker: %v, %v", r.StatusCode, trackerBody)
+		res.code = r.StatusCode
+		res.body = trackerBody
 		res.contentType = r.Header.Get("Content-type")
-		body, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			return internalError(err)
-		}
-		res.errString = string(body)
 	}
 	return res
 }
 
-func internalError(err error) (res trackerResponse) {
-	res.code = http.StatusInternalServerError
-	res.errString = err.Error()
-	return res
-}
-
-type tokenEventHandler struct {
-	token string
-}
-
-func (h *tokenEventHandler) Handle(e apid.Event) {
-	if token, ok := e.(string); ok {
-		h.token = token
-	}
-}
-
-func (h *tokenEventHandler) getBearerToken() string {
-	return "Bearer " + h.token
-}
-
-func (h *tokenEventHandler) initListener(services apid.Services) {
-
-	services.Events().Listen(ApigeeSyncTokenSelector, h)
+type serviceRegisterBody struct {
+	ClusterId    string `json:"clusterId"`
+	Pod          string `json:"pod"`
+	PodType      string `json:"podType"`
+	ReportedTime string `json:"reportedTime"`
+	Name         string `json:"name"`
+	Type         string `json:"type"`
 }
diff --git a/init.go b/init.go
index b1d2b7c..4f4bd80 100644
--- a/init.go
+++ b/init.go
@@ -129,11 +129,6 @@
 	}
 	apidClusterId = config.GetString(configApidClusterID)
 
-	// initialize token handler
-
-	tokenHandler := &tokenEventHandler{}
-	tokenHandler.initListener(services)
-
 	// initialize tracker client
 
 	client := &trackerClient{
@@ -145,11 +140,10 @@
 			},
 			Timeout: httpTimeout,
 			CheckRedirect: func(req *http.Request, _ []*http.Request) error {
-				req.Header.Set("Authorization", tokenHandler.getBearerToken())
+				req.Header.Set("Authorization", getBearerToken())
 				return nil
 			},
 		},
-		handler: tokenHandler,
 	}
 
 	// initialize db manager