diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..d62e35f
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,10 @@
+## What has been done:
+- 
+
+## Checklist
+- [] Updated documentation (i.e., `README.md`)
+- [] Updated tests for added feature
+- [] Created pre-release(s) - `X`
+
+## How to test:
+
diff --git a/README.md b/README.md
index 142dc5b..ac6f5f1 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,111 @@
 # reply
 
-`reply` is a Go library that supports developers with standardising the responses sent from their API service(s). It also allows users to predefine non-successful messages and their corresponding status code based on errors passed to the `replier`.
+`reply` is a Go library that supports developers with standardising the responses sent from their API service(s). It allows users to predefine non-successful messages and their corresponding status code based on errors manifest passed to the `replier`.
 
 ## Installation
 
 ```sh
 go get github.com/ooaklee/reply
 ```
+
+## Examples
+
+There are several ways you can integrate `reply` into your application. Below, you will find an example of how you can get the most out of this package.
+
+### How to create a `replier`
+
+```go
+// (Optional) Create a error manifest, to hold correlating error as string and it's manifest
+// item
+baseManifest := []reply.ErrorManifest{
+                {"example-404-error": reply.ErrorManifestItem{Message: "resource not found", StatusCode: http.StatusNotFound}},
+            }
+
+// Create replier to manage the responses going back to consumer(s)
+replier := reply.NewReplier(baseManifest)
+```
+
+### How to send response(s) 
+
+You can use `reply` for both successful and error based responses.
+
+> `NOTE` - When sending an error response, it is essential to make sure you populate the `replier`'s error manifest with the correct errors. Otherwise, a `500 - Internal Server Error` response will be sent back to the client by default if it cannot match the passed error with on in the manifest.
+
+#### Making use of error manifest
+
+```go
+
+// ExampleHandler handler to demostrate how to use package for error
+// response
+func ExampleHandler(w http.ResponseWriter, r *http.Request) {
+
+    // Create error with value corresponding to one of the manifest's entry's key
+    exampleErr := errors.New("example-404-error")
+
+
+    // Pass error to replier's method to return predefined response, else
+    // 500
+    _ := replier.NewHTTPResponse(&reply.NewResponseRequest{
+        Writer: w,
+        Error:  exampleErr,
+    })
+}
+```
+
+When the endpoint linked to the handler above is called, you should see the following JSON response.
+
+> `NOTE` - The `baseManifest` was initially declared, and its item represents the response shown below. Although the status code is not shown in the response body, it to has been set accordingly and returned to the consumer.
+
+```JSON
+
+{
+    "status": {
+        "message": "resource not found"
+    }
+}
+```
+
+#### Sending client successful response
+
+
+```go
+
+// ExampleGetAllHandler handler to demostrate how to use package for successful 
+// response
+func ExampleGetAllHandler(w http.ResponseWriter, r *http.Request) {
+
+    // building sample user model 
+    type user struct {
+        ID int `json:"id"`
+        Name string `json:"name"`
+    }
+
+    // emulate users pulled from repository
+    mockedQueriedUsers := []user{
+        {ID: 1, Name: "John Doe"},
+        {ID: 2, Name: "Sam Smith"},
+    }
+
+
+    // build and sent default formatted JSON response for consumption
+    // by client 
+    _ := replier.NewHTTPResponse(&reply.NewResponseRequest{
+        Writer: w,
+        Data: mockedUsers
+        StatusCode: htttp.StatusOK
+    })
+}
+```
+
+When the endpoint linked to the handler above is called, you should see the following JSON response.
+
+> `NOTE` - Unlike the error use case, successful requests expect the `StatusCode` to be defined when creating a successful response. If you do not provide a status code, 200 will be assumed.
+
+```JSON
+{
+    "data": [
+        {"id": 1, "name": "John Doe"},
+        {"id": 2, "name": "Sam Smith"}
+    ]
+}
+```
\ No newline at end of file
diff --git a/examples/example_simple_api.go b/examples/example_simple_api.go
new file mode 100644
index 0000000..4baf65f
--- /dev/null
+++ b/examples/example_simple_api.go
@@ -0,0 +1,180 @@
+package main
+
+import (
+	"errors"
+	"log"
+	"net/http"
+
+	"github.com/ooaklee/reply"
+)
+
+/////////////////////////////////////////////////
+/////// Custom Transition Object Example ////////
+// This is an example of how you can create a
+// custom response structure based on your
+// requirements.
+
+type fooReplyTransferObject struct {
+	HTTPWriter http.ResponseWriter `json:"-"`
+	Headers    map[string]string   `json:"-"`
+	StatusCode int                 `json:"-"`
+	Bar        barEmbeddedExample  `json:"bar,omitempty"`
+}
+
+type barEmbeddedExample struct {
+	Status       *reply.TransferObjectStatus `json:"status,omitempty"`
+	Meta         map[string]interface{}      `json:"meta,omitempty"`
+	Data         interface{}                 `json:"data,omitempty"`
+	AccessToken  string                      `json:"access_token,omitempty"`
+	RefreshToken string                      `json:"refresh_token,omitempty"`
+}
+
+func (t *fooReplyTransferObject) SetHeaders(headers map[string]string) {
+	t.Headers = headers
+}
+
+func (t *fooReplyTransferObject) SetStatusCode(code int) {
+	t.StatusCode = code
+}
+
+func (t *fooReplyTransferObject) SetMeta(meta map[string]interface{}) {
+	t.Bar.Meta = meta
+}
+
+func (t *fooReplyTransferObject) SetWriter(writer http.ResponseWriter) {
+	t.HTTPWriter = writer
+}
+
+func (t *fooReplyTransferObject) SetAccessToken(token string) {
+	t.Bar.AccessToken = token
+}
+
+func (t *fooReplyTransferObject) SetRefreshToken(token string) {
+	t.Bar.RefreshToken = token
+}
+
+func (t *fooReplyTransferObject) GetWriter() http.ResponseWriter {
+	return t.HTTPWriter
+}
+
+func (t *fooReplyTransferObject) GetStatusCode() int {
+	return t.StatusCode
+}
+
+func (t *fooReplyTransferObject) SetData(data interface{}) {
+	t.Bar.Data = data
+}
+
+func (t *fooReplyTransferObject) RefreshTransferObject() reply.TransferObject {
+	return &fooReplyTransferObject{}
+}
+
+func (t *fooReplyTransferObject) SetStatus(transferObjectStatus *reply.TransferObjectStatus) {
+	t.Bar.Status = transferObjectStatus
+}
+
+////////////////////
+
+type user struct {
+	ID   int    `json:"id"`
+	Name string `json:"name"`
+}
+
+var baseManifest []reply.ErrorManifest = []reply.ErrorManifest{
+	{"example-404-error": reply.ErrorManifestItem{Message: "resource not found", StatusCode: http.StatusNotFound}},
+}
+
+var replier *reply.Replier = reply.NewReplier(baseManifest)
+
+var replierWithCustomTransitionObj *reply.Replier = reply.NewReplier(baseManifest, reply.WithTransferObject(&fooReplyTransferObject{}))
+
+func simpleUsersAPINotFoundHandler(w http.ResponseWriter, r *http.Request) {
+
+	// Do something with a server
+	serverErr := errors.New("example-404-error")
+
+	replier.NewHTTPResponse(&reply.NewResponseRequest{
+		Writer: w,
+		Error:  serverErr,
+	})
+}
+
+func simpleUsersAPIHandler(w http.ResponseWriter, r *http.Request) {
+
+	mockedQueriedUsers := []user{
+		{ID: 1, Name: "John Doe"},
+		{ID: 2, Name: "Sam Smith"},
+	}
+
+	replier.NewHTTPResponse(&reply.NewResponseRequest{
+		Writer: w,
+		Data:   mockedQueriedUsers,
+	})
+}
+
+func simpleUsersAPINoManifestEntryHandler(w http.ResponseWriter, r *http.Request) {
+
+	// unregisterdErr an error that's  unregistered in manifest
+	// should return 500
+	unregisterdErr := errors.New("unexpected-error")
+
+	// mock passing additional headers in request
+	mockAdditionalHeaders := map[string]string{
+		"correlation-id": "d7c09ac2-fa46-4ece-bcde-1d7ad81d2230",
+	}
+
+	replier.NewHTTPResponse(&reply.NewResponseRequest{
+		Writer:  w,
+		Error:   unregisterdErr,
+		Headers: mockAdditionalHeaders,
+	})
+}
+
+func simpleTokensAPIHandler(w http.ResponseWriter, r *http.Request) {
+
+	mockedAccessToken := "05e42c11-8bdd-423d-a2c1-c3c5c6604a30"
+	mockedRefreshToken := "0e95c426-d373-41a5-bfe1-08db322527bd"
+
+	replier.NewHTTPResponse(&reply.NewResponseRequest{
+		Writer:       w,
+		AccessToken:  mockedAccessToken,
+		RefreshToken: mockedRefreshToken,
+	})
+}
+
+func simpleAPIDefaultResponseHandler(w http.ResponseWriter, r *http.Request) {
+
+	// Do something that only needs an empty response body, and 200 status code
+	replier.NewHTTPResponse(&reply.NewResponseRequest{
+		Writer: w,
+	})
+}
+
+func simpleUsersAPINotFoundCustomReplierHandler(w http.ResponseWriter, r *http.Request) {
+
+	// Do something with a server
+	serverErr := errors.New("example-404-error")
+
+	replierWithCustomTransitionObj.NewHTTPResponse(&reply.NewResponseRequest{
+		Writer: w,
+		Error:  serverErr,
+	})
+}
+
+func handleRequest() {
+	var port string = ":8081"
+
+	http.HandleFunc("/users", simpleUsersAPIHandler)
+	http.HandleFunc("/users/3", simpleUsersAPINotFoundHandler)
+	http.HandleFunc("/users/4", simpleUsersAPINoManifestEntryHandler)
+	http.HandleFunc("/tokens/refresh", simpleTokensAPIHandler)
+	http.HandleFunc("/defaults/1", simpleAPIDefaultResponseHandler)
+	http.HandleFunc("/custom/users/3", simpleUsersAPINotFoundCustomReplierHandler)
+
+	log.Printf("Serving simple API on port %s...", port)
+	log.Fatal(http.ListenAndServe(port, nil))
+}
+
+func main() {
+	handleRequest()
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..3afcd9a
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,11 @@
+module github.com/ooaklee/reply
+
+go 1.17
+
+require github.com/stretchr/testify v1.7.0
+
+require (
+	github.com/davecgh/go-spew v1.1.0 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..acb88a4
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,11 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/model.go b/model.go
new file mode 100644
index 0000000..d99b565
--- /dev/null
+++ b/model.go
@@ -0,0 +1,113 @@
+package reply
+
+import "net/http"
+
+// ErrorManifestItem holds the message and status code for a error response
+type ErrorManifestItem struct {
+
+	// Message holds the text returned in the response's status.message path
+	//
+	// NOTE:
+	//
+	// - The most effective messages are short, sweet and easy to consume
+	//
+	// - This message will be seeing by the consuming client, be mindful of
+	// how much information you divulge
+	Message string
+
+	// StatusCode holds the HTTP status code that best relates to the response.
+	// For more information on status codes, https://httpstatuses.com/.
+	StatusCode int
+}
+
+// ErrorManifest holds error reference (string) with its corresponding
+// manifest item (message & status code) which it returned in the response
+type ErrorManifest map[string]ErrorManifestItem
+
+// TransferObjectStatus holds attributes often used to give additional
+// context in responses
+type TransferObjectStatus struct {
+	Errors  []Error `json:"errors,omitempty"`
+	Message string  `json:"message,omitempty"`
+}
+
+// SetMessage adds message to transfer object status
+func (s *TransferObjectStatus) SetMessage(message string) {
+	s.Message = message
+}
+
+// Error holds the associated code and detail for errors passed
+type Error struct {
+	Code    string `json:"code"`
+	Details string `json:"details"`
+}
+
+// defaultReplyTransferObject handles structing response for client
+// consumption
+type defaultReplyTransferObject struct {
+	HTTPWriter   http.ResponseWriter    `json:"-"`
+	Headers      map[string]string      `json:"-"`
+	StatusCode   int                    `json:"-"`
+	Status       *TransferObjectStatus  `json:"status,omitempty"`
+	Meta         map[string]interface{} `json:"meta,omitempty"`
+	Data         interface{}            `json:"data,omitempty"`
+	AccessToken  string                 `json:"access_token,omitempty"`
+	RefreshToken string                 `json:"refresh_token,omitempty"`
+}
+
+// SetHeaders adds headers to transfer object
+// TODO: Think about any validation that can be added
+func (t *defaultReplyTransferObject) SetHeaders(headers map[string]string) {
+	t.Headers = headers
+}
+
+// SetHeaders adds status code to transfer object
+// TODO: Think about any validation that can be added
+func (t *defaultReplyTransferObject) SetStatusCode(code int) {
+	t.StatusCode = code
+}
+
+// SetMeta adds meta property to transfer object
+func (t *defaultReplyTransferObject) SetMeta(meta map[string]interface{}) {
+	t.Meta = meta
+}
+
+// SetWriter adds writer to transfer object
+func (t *defaultReplyTransferObject) SetWriter(writer http.ResponseWriter) {
+	t.HTTPWriter = writer
+}
+
+// SetAccessToken adds token to access token property on transfer object
+func (t *defaultReplyTransferObject) SetAccessToken(token string) {
+	t.AccessToken = token
+}
+
+// SetRefreshToken adds token to refresh token property on transfer object
+func (t *defaultReplyTransferObject) SetRefreshToken(token string) {
+	t.RefreshToken = token
+}
+
+// GetWriter returns the writer assigned with the transfer object
+func (t *defaultReplyTransferObject) GetWriter() http.ResponseWriter {
+	return t.HTTPWriter
+}
+
+// GetStatusCode returns the status code assigned to the transfer object
+func (t *defaultReplyTransferObject) GetStatusCode() int {
+	return t.StatusCode
+}
+
+// SetData adds passed data to the transfer object
+func (t *defaultReplyTransferObject) SetData(data interface{}) {
+	t.Data = data
+}
+
+// RefreshTransferObject returns an empty instance of transfer object
+func (t *defaultReplyTransferObject) RefreshTransferObject() TransferObject {
+	return &defaultReplyTransferObject{}
+}
+
+// SetStatus assigns the passed transfer object status to the transfer object
+func (t *defaultReplyTransferObject) SetStatus(transferObjectStatus *TransferObjectStatus) {
+	t.Status = transferObjectStatus
+}
diff --git a/release-notes.md b/release-notes.md
new file mode 100644
index 0000000..5a4ed3d
--- /dev/null
+++ b/release-notes.md
@@ -0,0 +1,31 @@
+# Reply Release Notes
+
+## [v0.1.0](https://github.com/ooaklee/reply/releases/tag/v0.1.0)
+2021-08-28
+
+* Refactored code
+* Utilise error returned in `NewHTTPResponse`
+* Added log entry for unfound manifest error item.
+
+## [v0.1.0-alpha.1](https://github.com/ooaklee/reply/releases/tag/v0.1.0-alpha.1)
+2021-08-27
+
+* Updated logic for the setting headers.
+* Added logic to default to JSON `content-type`
+
+## [v0.1.0-alpha](https://github.com/ooaklee/reply/releases/tag/v0.1.0-alpha)
+2021-08-26
+
+* Enforced `response priority`, priority is declared as follows:
+  - *Error response*
+  - *Token response* (access token/ refresh token)
+  - *Data response*
+  - *Default response*
+> Note - *Default response* occurs if none of the attributes expected to satisfy the other response types is satisfied. The JSON response for the default response returned will be:
+```json
+{
+    "data": "{}"
+}
+```
+* Added ability to send responses based on singular error. 
+> NOTE: If the error does not exist in the `error manifest` reply will default to 500 - Internal Server Error
\ No newline at end of file
diff --git a/replier.go b/replier.go
new file mode 100644
index 0000000..f8e7205
--- /dev/null
+++ b/replier.go
@@ -0,0 +1,247 @@
+package reply
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"log"
+	"net/http"
+)
+
+// TransferObject outlines expected methods of a transfer object
+type TransferObject interface {
+	SetHeaders(headers map[string]string)
+	SetStatusCode(code int)
+	SetMeta(meta map[string]interface{})
+	SetAccessToken(token string)
+	SetRefreshToken(token string)
+	GetWriter() http.ResponseWriter
+	GetStatusCode() int
+	SetWriter(writer http.ResponseWriter)
+	SetStatus(transferObjectStatus *TransferObjectStatus)
+	RefreshTransferObject() TransferObject
+	SetData(data interface{})
+}
+
+const (
+	// defaultResponseBody returns default response body
+	defaultResponseBody = "{}"
+
+	// defaultStatusCode returns default response status code
+	defaultStatusCode = http.StatusOK
+)
+
+// Option used to build ontop of default features
+type Option func(*Replier)
+
+// WithTransferObject overwrites the transfer object used for response
+func WithTransferObject(replacementTransferObject TransferObject) Option {
+	return func(r *Replier) {
+		r.transferObject = replacementTransferObject
+	}
+}
+
+// NewResponseRequest holds attributes for response
+type NewResponseRequest struct {
+	Writer       http.ResponseWriter
+	Data         interface{}
+	Meta         map[string]interface{}
+	Headers      map[string]string
+	StatusCode   int
+	Message      string
+	Error        error
+	AccessToken  string
+	RefreshToken string
+}
+
+// Replier handles managing responses
+type Replier struct {
+	errorManifest  ErrorManifest
+	transferObject TransferObject
+}
+
+// NewReplier creates a replier
+func NewReplier(manifests []ErrorManifest, options ...Option) *Replier {
+
+	activeTransferObject := &defaultReplyTransferObject{}
+
+	replier := Replier{
+		errorManifest:  mergeManifestCollections(manifests...),
+		transferObject: activeTransferObject,
+	}
+
+	// Add option add-ons on replier
+	for _, option := range options {
+		option(&replier)
+	}
+
+	return &replier
+}
+
+// NewHTTPResponse handles generating and sending of an appropriate HTTP response body
+// based response attributes.
+//
+// NOTE - Several assumptions have been made to simplify the process
+// of response generation. The assumptions include:
+//
+// - An error passed in the NewResponseRequest will have a corresponding manifest entry,
+// otherwise you are happy for a `500 - Internal Server Error` to be returned
+//
+// - Reply should only return tokens (access & refresh) with each other or by themselves
+//
+// - Data will be JSON encodable
+//
+// - The default response will be to return 200 status code if the NewResponseRequest is
+// solely  passed  with a writer
+func (r *Replier) NewHTTPResponse(response *NewResponseRequest) error {
+
+	if response.Writer == nil {
+		return errors.New("reply/http-response: failed to send response, no writer provided")
+	}
+
+	// Use fresh transfer object
+	r.transferObject = r.transferObject.RefreshTransferObject()
+
+	r.setUniversalAttributes(response.Writer, response.Headers, response.Meta, response.StatusCode)
+
+	// Manage response for error
+	if response.Error != nil {
+		return r.generateErrorResponse(response.Error)
+	}
+
+	// Manage response for token
+	if response.AccessToken != "" || response.RefreshToken != "" {
+		return r.generateTokenResponse(response.AccessToken, response.RefreshToken, response.StatusCode)
+	}
+
+	// Manage response for data
+	if response.Data != nil {
+		return r.generateDataResponse(response.Data, response.StatusCode)
+	}
+
+	return r.generateDefaultResponse()
+}
+
+// generateDefaultResponse generates the default response
+func (r *Replier) generateDefaultResponse() error {
+	r.transferObject.SetStatusCode(defaultStatusCode)
+	r.transferObject.SetData(defaultResponseBody)
+
+	return sendHTTPResponse(r.transferObject.GetWriter(), r.transferObject)
+}
+
+// generateDataResponse generates response based on passed data
+func (r *Replier) generateDataResponse(data interface{}, statusCode int) error {
+	r.transferObject.SetData(data)
+
+	if statusCode == 0 {
+		r.transferObject.SetStatusCode(defaultStatusCode)
+	}
+
+	return sendHTTPResponse(r.transferObject.GetWriter(), r.transferObject)
+}
+
+// generateTokenResponse generates token response on passed tokens information
+func (r *Replier) generateTokenResponse(accessToken, refreshToken string, statusCode int) error {
+	r.transferObject.SetAccessToken(accessToken)
+	r.transferObject.SetRefreshToken(refreshToken)
+
+	if statusCode == 0 {
+		r.transferObject.SetStatusCode(defaultStatusCode)
+	}
+
+	return sendHTTPResponse(r.transferObject.GetWriter(), r.transferObject)
+}
+
+// generateErrorResponse generates correct error response based on passed
+// error
+func (r *Replier) generateErrorResponse(err error) error {
+	manifestItem, ok := r.errorManifest[err.Error()]
+	if !ok {
+		manifestItem = getInternalServertErrorManifestItem()
+		log.Printf("reply/error-response: failed to find error manifest item for %v", err)
+	}
+
+	transferObjectStatus := &TransferObjectStatus{}
+	transferObjectStatus.SetMessage(manifestItem.Message)
+
+	// Overwrite status code
+	r.transferObject.SetStatusCode(manifestItem.StatusCode)
+	r.transferObject.SetStatus(transferObjectStatus)
+
+	return sendHTTPResponse(r.transferObject.GetWriter(), r.transferObject)
+}
+
+// setUniversalAttributes sets the attributes that are common across all
+// response types
+func (r *Replier) setUniversalAttributes(writer http.ResponseWriter, headers map[string]string, meta map[string]interface{}, statusCode int) {
+	r.transferObject.SetWriter(writer)
+	r.setHeaders(headers)
+	r.transferObject.SetMeta(meta)
+	r.transferObject.SetStatusCode(statusCode)
+}
+
+// setDefaultContentType handles setting default content type to JSON if
+// not already set
+func (r *Replier) setDefaultContentType() {
+	if r.transferObject.GetWriter().Header().Get("Content-type") == "" {
+		r.transferObject.GetWriter().Header().Set("Content-type", "application/json")
+	}
+}
+
+// setHeaders handles setting headers on writer. Existing headers hould not
+// be affeted unless they share the header key
+func (r *Replier) setHeaders(h map[string]string) {
+
+	r.setDefaultContentType()
+
+	if h == nil {
+		return
+	}
+
+	for headerKey, headerValue := range h {
+		r.transferObject.GetWriter().Header().Set(headerKey, headerValue)
+	}
+}
+
+// sendHTTPResponse handles sending response based on the transfer object
+func sendHTTPResponse(writer http.ResponseWriter, transferObject TransferObject) error {
+
+	writer.WriteHeader(transferObject.GetStatusCode())
+	err := json.NewEncoder(writer).Encode(transferObject)
+	if err != nil {
+		return fmt.Errorf("reply/http-response: failed to encode transfer object with %v", err)
+	}
+
+	return nil
+}
+
+// mergeManifestCollections handles merges the passed manifests into a singular
+// map
+func mergeManifestCollections(manifests ...ErrorManifest) ErrorManifest {
+
+	mergedManifests := make(ErrorManifest)
+
+	for _, manifest := range manifests {
+		key, value := getManifestAttributes(manifest)
+		mergedManifests[key] = *value
+	}
+
+	return mergedManifests
+}
+
+// getManifestAttributes returns key and value for pass manifest
+func getManifestAttributes(manifest ErrorManifest) (key string, value *ErrorManifestItem) {
+
+	for k, v := range manifest {
+		key = k
+		value = &v
+	}
+
+	return key, value
+}
+
+// getInternalServertErrorManifestItem returns typical 500 error with text and message
+func getInternalServertErrorManifestItem() ErrorManifestItem {
+	return ErrorManifestItem{Message: "Internal Server Error", StatusCode: http.StatusInternalServerError}
+}
diff --git a/replier_test.go b/replier_test.go
new file mode 100644
index 0000000..700cca1
--- /dev/null
+++ b/replier_test.go
@@ -0,0 +1,255 @@
+package reply_test
+
+import (
+	"encoding/json"
+	"errors"
+	"io/ioutil"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	"github.com/ooaklee/reply"
+	"github.com/stretchr/testify/assert"
+)
+
+type baseTestResponse struct {
+	AccessToken  string      `json:"access_token,omitempty"`
+	RefreshToken string      `json:"refresh_token,omitempty"`
+	Data         interface{} `json:"data,omitempty"`
+}
+
+type baseStatusMessageResponse struct {
+	Status struct {
+		Message string `json:"message,omitempty"`
+	} `json:"status,omitempty"`
+}
+
+func TestReplier_NewHTTPResponseForTokens(t *testing.T) {
+
+	tests := []struct {
+		name               string
+		manifests          []reply.ErrorManifest
+		accessToken        string
+		refreshToken       string
+		StatusCode         int
+		assertResponse     func(w *httptest.ResponseRecorder, t *testing.T)
+		expectedStatusCode int
+	}{
+		{
+			name:               "Success - Access Token response",
+			manifests:          []reply.ErrorManifest{},
+			accessToken:        "test-access-token",
+			StatusCode:         200,
+			expectedStatusCode: http.StatusOK,
+			assertResponse: func(w *httptest.ResponseRecorder, t *testing.T) {
+
+				response := baseTestResponse{}
+
+				err := unmarshalResponseBody(w, &response)
+				if err != nil {
+					t.Fatalf("cannot get response content: %v", err)
+				}
+
+				assert.Equal(t, baseTestResponse{AccessToken: "test-access-token"}, response)
+			},
+		},
+		{
+			name:               "Success - Full Token response",
+			manifests:          []reply.ErrorManifest{},
+			accessToken:        "test-access-token",
+			refreshToken:       "test-refresh-token",
+			StatusCode:         200,
+			expectedStatusCode: http.StatusOK,
+			assertResponse: func(w *httptest.ResponseRecorder, t *testing.T) {
+
+				response := baseTestResponse{}
+
+				err := unmarshalResponseBody(w, &response)
+				if err != nil {
+					t.Fatalf("cannot get response content: %v", err)
+				}
+
+				assert.Equal(t, baseTestResponse{AccessToken: "test-access-token", RefreshToken: "test-refresh-token"}, response)
+			},
+		},
+		{
+			name:               "Failed - Default response sent",
+			manifests:          []reply.ErrorManifest{},
+			expectedStatusCode: 200,
+			assertResponse: func(w *httptest.ResponseRecorder, t *testing.T) {
+
+				response := baseTestResponse{}
+
+				err := unmarshalResponseBody(w, &response)
+				if err != nil {
+					t.Fatalf("cannot get response content: %v", err)
+				}
+
+				expectedResponse := baseTestResponse{Data: "{}"}
+
+				assert.Equal(t, expectedResponse, response)
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+
+			w := httptest.NewRecorder()
+
+			replier := reply.NewReplier(test.manifests)
+
+			replier.NewHTTPResponse(&reply.NewResponseRequest{
+				Writer:       w,
+				StatusCode:   test.StatusCode,
+				AccessToken:  test.accessToken,
+				RefreshToken: test.refreshToken,
+			})
+
+			assert.Equal(t, test.expectedStatusCode, w.Code)
+			test.assertResponse(w, t)
+		})
+	}
+}
+
+func TestReplier_NewHTTPResponseForData(t *testing.T) {
+
+	type user struct {
+		ID   string `json:"id,omitempty"`
+		Name string `json:"name,omitempty"`
+	}
+
+	tests := []struct {
+		name               string
+		manifests          []reply.ErrorManifest
+		data               interface{}
+		StatusCode         int
+		assertResponse     func(w *httptest.ResponseRecorder, t *testing.T)
+		expectedStatusCode int
+	}{
+		{
+			name:       "Success - Created Mock user",
+			manifests:  []reply.ErrorManifest{},
+			StatusCode: 201,
+			data: user{
+				ID:   "new-uuid",
+				Name: "Test User",
+			},
+			expectedStatusCode: http.StatusCreated,
+			assertResponse: func(w *httptest.ResponseRecorder, t *testing.T) {
+
+				response := baseTestResponse{}
+
+				err := unmarshalResponseBody(w, &response)
+				if err != nil {
+					t.Fatalf("cannot get response content: %v", err)
+				}
+
+				assert.Equal(t, baseTestResponse{Data: map[string]interface{}{"id": "new-uuid", "name": "Test User"}}, response)
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+
+			w := httptest.NewRecorder()
+
+			replier := reply.NewReplier(test.manifests)
+
+			replier.NewHTTPResponse(&reply.NewResponseRequest{
+				Writer:     w,
+				StatusCode: test.StatusCode,
+				Data:       test.data,
+			})
+
+			assert.Equal(t, test.expectedStatusCode, w.Code)
+			test.assertResponse(w, t)
+		})
+	}
+}
+
+func TestReplier_NewHTTPResponseForError(t *testing.T) {
+
+	tests := []struct {
+		name               string
+		manifests          []reply.ErrorManifest
+		err                error
+		StatusCode         int
+		assertResponse     func(w *httptest.ResponseRecorder, t *testing.T)
+		expectedStatusCode int
+	}{
+		{
+			name: "Success - Resource not found",
+			manifests: []reply.ErrorManifest{
+				{"test-404-error": reply.ErrorManifestItem{Message: "resource not found", StatusCode: http.StatusNotFound}},
+			},
+			err:                errors.New("test-404-error"),
+			expectedStatusCode: http.StatusNotFound,
+			assertResponse: func(w *httptest.ResponseRecorder, t *testing.T) {
+
+				response := baseStatusMessageResponse{}
+
+				err := unmarshalResponseBody(w, &response)
+				if err != nil {
+					t.Fatalf("cannot get response content: %v", err)
+				}
+
+				expectedResponse := baseStatusMessageResponse{}
+				expectedResponse.Status.Message = "resource not found"
+				assert.Equal(t, expectedResponse, response)
+			},
+		},
+		{
+			name:               "Failure - Error not in manifest",
+			manifests:          []reply.ErrorManifest{},
+			err:                errors.New("test-404-error"),
+			expectedStatusCode: http.StatusInternalServerError,
+			assertResponse: func(w *httptest.ResponseRecorder, t *testing.T) {
+
+				response := baseStatusMessageResponse{}
+
+				err := unmarshalResponseBody(w, &response)
+				if err != nil {
+					t.Fatalf("cannot get response content: %v", err)
+				}
+
+				expectedResponse := baseStatusMessageResponse{}
+				expectedResponse.Status.Message = "Internal Server Error"
+				assert.Equal(t, expectedResponse, response)
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+
+			w := httptest.NewRecorder()
+
+			replier := reply.NewReplier(test.manifests)
+
+			replier.NewHTTPResponse(&reply.NewResponseRequest{
+				Writer: w,
+				Error:  test.err,
+			})
+
+			assert.Equal(t, test.expectedStatusCode, w.Code)
+			test.assertResponse(w, t)
+		})
+	}
+}
+
+// unmarshalResponseBody handles unmarshalling recorder's response to specified
+// response body
+func unmarshalResponseBody(w *httptest.ResponseRecorder, responseBody interface{}) error {
+	content, err := ioutil.ReadAll(w.Result().Body)
+	if err != nil {
+		return err
+	}
+
+	if err = json.Unmarshal(content, responseBody); err != nil {
+		return err
+	}
+
+	return nil
+}