Merge the repositories of openwhisk-cli and openwhisk/go-whisk-cli
diff --git a/commands/action.go b/commands/action.go
index d269377..2393a51 100644
--- a/commands/action.go
+++ b/commands/action.go
@@ -144,6 +144,7 @@
                 return getJSONFromStringsParamError(paramArgs, false, err)
             }
         }
+        if flags.action.result {flags.common.blocking = true}
 
         res, _, err := client.Actions.Invoke(
             qualifiedName.entityName,
@@ -592,8 +593,9 @@
     whisk.Debug(whisk.DbgError, "client.Actions.Insert(%#v, false) error: %s\n", action, err)
 
     errMsg := wski18n.T(
-        "Unable to create action: {{.err}}",
+        "Unable to create action '{{.name}}': {{.err}}",
         map[string]interface{}{
+            "name": action.Name,
             "err": err,
         })
 
@@ -653,8 +655,9 @@
     whisk.Debug(whisk.DbgError, "client.Actions.Delete(%s) error: %s\n", entityName, err)
 
     errMsg := wski18n.T(
-        "Unable to delete action: {{.err}}",
+        "Unable to delete action '{{.name}}': {{.err}}",
         map[string]interface{}{
+            "name": entityName,
             "err": err,
         })
 
@@ -665,7 +668,7 @@
     whisk.Debug(whisk.DbgError, "client.Actions.Get(%s) error: %s\n", entityName, err)
 
     errMsg := wski18n.T(
-        "Unable to obtain action '{{.name}}' to copy: {{.err}}",
+        "Unable to get action '{{.name}}': {{.err}}",
         map[string]interface{}{
             "name": entityName,
             "err": err,
@@ -833,6 +836,42 @@
             }))
 }
 
+// Check if the specified action is a web-action
+func isWebAction(client *whisk.Client, qname QualifiedName) error {
+    var err error = nil
+
+    savedNs := client.Namespace
+    client.Namespace = qname.namespace
+    fullActionName := "/" + qname.namespace + "/" + qname.entityName
+
+    action, _, err := client.Actions.Get(qname.entityName)
+    if err != nil {
+        whisk.Debug(whisk.DbgError, "client.Actions.Get(%s) error: %s\n", fullActionName, err)
+        whisk.Debug(whisk.DbgError, "Unable to obtain action '%s' for web action validation\n", fullActionName)
+        err = errors.New(wski18n.T("API action does not exist"))
+    } else {
+        err = errors.New(wski18n.T("API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
+            map[string]interface{}{"name": fullActionName}))
+        weVal := getValue(action.Annotations, "web-export")
+        if (weVal == nil) {
+            whisk.Debug(whisk.DbgError, "getValue(annotations, web-export) for action %s found no value\n", fullActionName)
+        } else {
+            var webExport bool
+            var ok bool
+            if webExport, ok = weVal.(bool); !ok {
+                whisk.Debug(whisk.DbgError, "web-export annotation value (%v) is not a boolean\n", weVal)
+            } else if !webExport {
+                whisk.Debug(whisk.DbgError, "web-export annotation value is false\n", weVal)
+            } else {
+                err = nil
+            }
+        }
+    }
+
+    client.Namespace = savedNs
+    return err
+}
+
 func init() {
     actionCreateCmd.Flags().BoolVar(&flags.action.docker, "docker", false, wski18n.T("treat ACTION as docker image path on dockerhub"))
     actionCreateCmd.Flags().BoolVar(&flags.action.copy, "copy", false, wski18n.T("treat ACTION as the name of an existing action"))
@@ -865,7 +904,7 @@
     actionInvokeCmd.Flags().StringSliceVarP(&flags.common.param, "param", "p", []string{}, wski18n.T("parameter values in `KEY VALUE` format"))
     actionInvokeCmd.Flags().StringVarP(&flags.common.paramFile, "param-file", "P", "", wski18n.T("`FILE` containing parameter values in JSON format"))
     actionInvokeCmd.Flags().BoolVarP(&flags.common.blocking, "blocking", "b", false, wski18n.T("blocking invoke"))
-    actionInvokeCmd.Flags().BoolVarP(&flags.action.result, "result", "r", false, wski18n.T("show only activation result if a blocking activation (unless there is a failure)"))
+    actionInvokeCmd.Flags().BoolVarP(&flags.action.result, "result", "r", false, wski18n.T("blocking invoke; show only activation result (unless there is a failure)"))
 
     actionGetCmd.Flags().BoolVarP(&flags.common.summary, "summary", "s", false, wski18n.T("summarize action details"))
 
diff --git a/commands/activation.go b/commands/activation.go
index 575de2e..df0b2d5 100644
--- a/commands/activation.go
+++ b/commands/activation.go
@@ -135,7 +135,7 @@
         activation, _, err := client.Activations.Get(id)
         if err != nil {
             whisk.Debug(whisk.DbgError, "client.Activations.Get(%s) failed: %s\n", id, err)
-            errStr := wski18n.T("Unable to obtain activation record for '{{.id}}': {{.err}}",
+            errStr := wski18n.T("Unable to get activation '{{.id}}': {{.err}}",
                     map[string]interface{}{"id": id, "err": err})
             werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
             return werr
@@ -186,7 +186,7 @@
         activation, _, err := client.Activations.Logs(id)
         if err != nil {
             whisk.Debug(whisk.DbgError, "client.Activations.Logs(%s) failed: %s\n", id, err)
-            errStr := wski18n.T("Unable to obtain logs for activation '{{.id}}': {{.err}}",
+            errStr := wski18n.T("Unable to get logs for activation '{{.id}}': {{.err}}",
                 map[string]interface{}{"id": id, "err": err})
             werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
             return werr
@@ -214,7 +214,7 @@
         result, _, err := client.Activations.Result(id)
         if err != nil {
             whisk.Debug(whisk.DbgError, "client.Activations.result(%s) failed: %s\n", id, err)
-            errStr := wski18n.T("Unable to obtain result information for activation '{{.id}}': {{.err}}",
+            errStr := wski18n.T("Unable to get result for activation '{{.id}}': {{.err}}",
                     map[string]interface{}{"id": id, "err": err})
             werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
             return werr
diff --git a/commands/api.go b/commands/api.go
index 3fa1a79..430dc38 100644
--- a/commands/api.go
+++ b/commands/api.go
@@ -40,6 +40,11 @@
     Short: wski18n.T("work with APIs (experimental)"),
 }
 
+var apiCmd = &cobra.Command{
+    Use:   "api",
+    Short: wski18n.T("work with APIs"),
+}
+
 var apiCreateCmd = &cobra.Command{
     Use:           "create ([BASE_PATH] API_PATH API_VERB ACTION] | --config-file CFG_FILE) ",
     Short:         wski18n.T("create a new API"),
@@ -82,10 +87,10 @@
             }
         }
 
-        sendApi := new(whisk.SendApi)
-        sendApi.ApiDoc = api
-
-        retApi, _, err := client.Apis.Insert(sendApi, false)
+        apiCreateReq := new(whisk.ApiCreateRequest)
+        apiCreateReq.ApiDoc = api
+        apiCreateReqOptions := new(whisk.ApiCreateRequestOptions)
+        retApi, _, err := client.Apis.Insert(apiCreateReq, apiCreateReqOptions, whisk.DoNotOverwrite)
         if err != nil {
             whisk.Debug(whisk.DbgError, "client.Apis.Insert(%#v, false) error: %s\n", api, err)
             errMsg := wski18n.T("Unable to create API: {{.err}}", map[string]interface{}{"err": err})
@@ -111,7 +116,7 @@
             for path, _ := range retApi.Swagger.Paths {
                 managedUrl := strings.TrimSuffix(baseUrl, "/")+path
                 whisk.Debug(whisk.DbgInfo, "Managed path: %s\n",managedUrl)
-                for op, _  := range retApi.Swagger.Paths[path] {
+                for op, opv  := range retApi.Swagger.Paths[path] {
                     whisk.Debug(whisk.DbgInfo, "Path operation: %s\n", op)
                     fmt.Fprintf(color.Output,
                         wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
@@ -119,7 +124,7 @@
                                 "ok": color.GreenString("ok:"),
                                 "path": path,
                                 "verb": op,
-                                "name": boldString(retApi.Swagger.Paths[path][op]["x-ibm-op-ext"]["actionName"]),
+                                "name": boldString(opv.XOpenWhisk.ActionName),
                                 "fullpath": managedUrl,
                             }))
                 }
@@ -131,51 +136,51 @@
     },
 }
 
-var apiUpdateCmd = &cobra.Command{
-    Use:           "update API_PATH API_VERB ACTION",
-    Short:         wski18n.T("update an existing API"),
-    SilenceUsage:  true,
-    SilenceErrors: true,
-    PreRunE:       setupClientConfig,
-    RunE: func(cmd *cobra.Command, args []string) error {
-
-        if whiskErr := checkArgs(args, 3, 3, "Api update",
-            wski18n.T("An API path, an API verb, and an action name are required.")); whiskErr != nil {
-            return whiskErr
-        }
-
-        api, err := parseApi(cmd, args)
-        if err != nil {
-            whisk.Debug(whisk.DbgError, "parseApi(%s, %s) error: %s\n", cmd, args, err)
-            errMsg := wski18n.T("Unable to parse API command arguments: {{.err}}", map[string]interface{}{"err": err})
-            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
-                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
-            return whiskErr
-        }
-        sendApi := new(whisk.SendApi)
-        sendApi.ApiDoc = api
-
-        retApi, _, err := client.Apis.Insert(sendApi, true)
-        if err != nil {
-            whisk.Debug(whisk.DbgError, "client.Apis.Insert(%#v, %t, false) error: %s\n", api, err)
-            errMsg := wski18n.T("Unable to update API: {{.err}}", map[string]interface{}{"err": err})
-            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_NETWORK,
-                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
-            return whiskErr
-        }
-
-        fmt.Fprintf(color.Output,
-            wski18n.T("{{.ok}} updated API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
-                map[string]interface{}{
-                    "ok": color.GreenString("ok:"),
-                    "path": api.GatewayRelPath,
-                    "verb": api.GatewayMethod,
-                    "name": boldString("/"+api.Action.Name),
-                    "fullpath": getManagedUrl(retApi, api.GatewayRelPath, api.GatewayMethod),
-                }))
-        return nil
-    },
-}
+//var apiUpdateCmd = &cobra.Command{
+//    Use:           "update API_PATH API_VERB ACTION",
+//    Short:         wski18n.T("update an existing API"),
+//    SilenceUsage:  true,
+//    SilenceErrors: true,
+//    PreRunE:       setupClientConfig,
+//    RunE: func(cmd *cobra.Command, args []string) error {
+//
+//        if whiskErr := checkArgs(args, 3, 3, "Api update",
+//            wski18n.T("An API path, an API verb, and an action name are required.")); whiskErr != nil {
+//            return whiskErr
+//        }
+//
+//        api, err := parseApi(cmd, args)
+//        if err != nil {
+//            whisk.Debug(whisk.DbgError, "parseApi(%s, %s) error: %s\n", cmd, args, err)
+//            errMsg := wski18n.T("Unable to parse API command arguments: {{.err}}", map[string]interface{}{"err": err})
+//            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+//                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+//            return whiskErr
+//        }
+//        sendApi := new(whisk.ApiCreateRequest)
+//        sendApi.ApiDoc = api
+//
+//        retApi, _, err := client.Apis.Insert(sendApi, true)
+//        if err != nil {
+//            whisk.Debug(whisk.DbgError, "client.Apis.Insert(%#v, %t, false) error: %s\n", api, err)
+//            errMsg := wski18n.T("Unable to update API: {{.err}}", map[string]interface{}{"err": err})
+//            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_NETWORK,
+//                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+//            return whiskErr
+//        }
+//
+//        fmt.Fprintf(color.Output,
+//            wski18n.T("{{.ok}} updated API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+//                map[string]interface{}{
+//                    "ok": color.GreenString("ok:"),
+//                    "path": api.GatewayRelPath,
+//                    "verb": api.GatewayMethod,
+//                    "name": boldString("/"+api.Action.Name),
+//                    "fullpath": getManagedUrl(retApi, api.GatewayRelPath, api.GatewayMethod),
+//                }))
+//        return nil
+//    },
+//}
 
 var apiGetCmd = &cobra.Command{
     Use:           "get BASE_PATH | API_NAME",
@@ -192,15 +197,13 @@
             return whiskErr
         }
 
-        api := new(whisk.Api)
-        options := new(whisk.ApiListOptions)
-
-        options.ApiBasePath = args[0]
-
-        retApi, _, err := client.Apis.Get(api, options)
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+        apiGetReqOptions.ApiBasePath = args[0]
+        retApi, _, err := client.Apis.Get(apiGetReq, apiGetReqOptions)
         if err != nil {
-            whisk.Debug(whisk.DbgError, "client.Apis.Get(%s) error: %s\n", api.Id, err)
-            errMsg := wski18n.T("Unable to get API: {{.err}}", map[string]interface{}{"err": err})
+            whisk.Debug(whisk.DbgError, "client.Apis.Get(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
+            errMsg := wski18n.T("Unable to get API '{{.name}}': {{.err}}", map[string]interface{}{"name": args[0], "err": err})
             whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
                 whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
             return whiskErr
@@ -256,16 +259,14 @@
             return whiskErr
         }
 
-        api := new(whisk.Api)
-        options := new(whisk.ApiOptions)
-        options.Force = true
-
+        apiDeleteReq := new(whisk.ApiDeleteRequest)
+        apiDeleteReqOptions := new(whisk.ApiDeleteRequestOptions)
         // Is the argument a basepath (must start with /) or an API name
         if _, ok := isValidBasepath(args[0]); !ok {
             whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
-            options.ApiBasePath = args[0]
+            apiDeleteReqOptions.ApiBasePath = args[0]
         } else {
-            options.ApiBasePath = args[0]
+            apiDeleteReqOptions.ApiBasePath = args[0]
         }
 
         if (len(args) > 1) {
@@ -273,20 +274,20 @@
             if whiskErr, ok := isValidRelpath(args[1]); !ok {
                 return whiskErr
             }
-            options.ApiRelPath = args[1]
+            apiDeleteReqOptions.ApiRelPath = args[1]
         }
         if (len(args) > 2) {
             // Is the API verb valid?
             if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
                 return whiskErr
             }
-            options.ApiVerb = strings.ToUpper(args[2])
+            apiDeleteReqOptions.ApiVerb = strings.ToUpper(args[2])
         }
 
-        _, err := client.Apis.Delete(api, options)
+        _, err := client.Apis.Delete(apiDeleteReq, apiDeleteReqOptions)
         if err != nil {
-            whisk.Debug(whisk.DbgError, "client.Apis.Delete(%s) error: %s\n", api.Id, err)
-            errMsg := wski18n.T("Unable to delete action: {{.err}}", map[string]interface{}{"err": err})
+            whisk.Debug(whisk.DbgError, "client.Apis.Delete(%#v, %#v) error: %s\n", apiDeleteReq, apiDeleteReqOptions, err)
+            errMsg := wski18n.T("Unable to delete API: {{.err}}", map[string]interface{}{"err": err})
             whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
                 whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
             return whiskErr
@@ -297,24 +298,24 @@
                 wski18n.T("{{.ok}} deleted API {{.basepath}}\n",
                     map[string]interface{}{
                         "ok": color.GreenString("ok:"),
-                        "basepath": options.ApiBasePath,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
                     }))
         } else if (len(args) == 2 ) {
             fmt.Fprintf(color.Output,
                 wski18n.T("{{.ok}} deleted {{.path}} from {{.basepath}}\n",
                     map[string]interface{}{
                         "ok": color.GreenString("ok:"),
-                        "path": options.ApiRelPath,
-                        "basepath": options.ApiBasePath,
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
                     }))
         } else {
             fmt.Fprintf(color.Output,
                 wski18n.T("{{.ok}} deleted {{.path}} {{.verb}} from {{.basepath}}\n",
                     map[string]interface{}{
                         "ok": color.GreenString("ok:"),
-                        "path": options.ApiRelPath,
-                        "verb": options.ApiVerb,
-                        "basepath": options.ApiBasePath,
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "verb": apiDeleteReqOptions.ApiVerb,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
                     }))
         }
 
@@ -331,6 +332,8 @@
     PreRunE:       setupClientConfig,
     RunE: func(cmd *cobra.Command, args []string) error {
         var err error
+        var retApiList *whisk.ApiListResponse
+        var retApi *whisk.ApiGetResponse
         var retApiArray *whisk.RetApiArray
 
         if whiskErr := checkArgs(args, 0, 3, "Api list",
@@ -338,50 +341,59 @@
             return whiskErr
         }
 
-        api := new(whisk.Api)
-        api.Namespace = client.Config.Namespace
+        // Get API request body
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReq.Namespace = client.Config.Namespace
 
-        options := new(whisk.ApiListOptions)
-        options.Limit = flags.common.limit
-        options.Skip = flags.common.skip
+        // Get API request options
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+
+        // List API request query parameters
+        apiListReqOptions := new(whisk.ApiListRequestOptions)
+        apiListReqOptions.Limit = flags.common.limit
+        apiListReqOptions.Skip = flags.common.skip
 
         if (len(args) == 0) {
-            retApiArray, _, err = client.Apis.List(options)
+            retApiList, _, err = client.Apis.List(apiListReqOptions)
             if err != nil {
-                whisk.Debug(whisk.DbgError, "client.Apis.List(%s) error: %s\n", options, err)
-                errMsg := wski18n.T("Unable to get API: {{.err}}", map[string]interface{}{"err": err})
+                whisk.Debug(whisk.DbgError, "client.Apis.List(%#v) error: %s\n", apiListReqOptions, err)
+                errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
                 whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
                     whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
                 return whiskErr
             }
-            whisk.Debug(whisk.DbgInfo, "client.Apis.List returned: %#v (%+v)\n", retApiArray, retApiArray)
+            whisk.Debug(whisk.DbgInfo, "client.Apis.List returned: %#v (%+v)\n", retApiList, retApiList)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArray)(retApiList)
         } else {
             // The first argument is either a basepath (must start with /) or an API name
-            options.ApiBasePath = args[0]
+            apiGetReqOptions.ApiBasePath = args[0]
             if (len(args) > 1) {
                 // Is the API path valid?
                 if whiskErr, ok := isValidRelpath(args[1]); !ok {
                     return whiskErr
                 }
-                options.ApiRelPath = args[1]
+                apiGetReqOptions.ApiRelPath = args[1]
             }
             if (len(args) > 2) {
                 // Is the API verb valid?
                 if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
                     return whiskErr
                 }
-                options.ApiVerb = strings.ToUpper(args[2])
+                apiGetReqOptions.ApiVerb = strings.ToUpper(args[2])
             }
 
-            retApiArray, _, err = client.Apis.Get(api, options)
+            retApi, _, err = client.Apis.Get(apiGetReq, apiGetReqOptions)
             if err != nil {
-                whisk.Debug(whisk.DbgError, "client.Apis.Get(%s) error: %s\n", api.Id, err)
+                whisk.Debug(whisk.DbgError, "client.Apis.Get(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
                 errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
                 whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
                     whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
                 return whiskErr
             }
-            whisk.Debug(whisk.DbgInfo, "client.Apis.Get returned: %#v\n", retApiArray)
+            whisk.Debug(whisk.DbgInfo, "client.Apis.Get returned: %#v\n", retApi)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArray)(retApi)
         }
 
         // Display the APIs - applying any specified filtering
@@ -393,13 +405,13 @@
                     }))
 
             for i:=0; i<len(retApiArray.Apis); i++ {
-                printFilteredListApi(retApiArray.Apis[i].ApiValue, api)
+                printFilteredListApi(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions))
             }
         } else {
             // Dynamically create the output format string based on the maximum size of the
             // fully qualified action name and the API Name.
-            maxActionNameSize := min(40, max(len("Action"), getLargestActionNameSize(retApiArray, api)))
-            maxApiNameSize := min(30, max(len("API Name"), getLargestApiNameSize(retApiArray, api)))
+            maxActionNameSize := min(40, max(len("Action"), getLargestActionNameSize(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
+            maxApiNameSize := min(30, max(len("API Name"), getLargestApiNameSize(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
             fmtString = "%-"+strconv.Itoa(maxActionNameSize)+"s %7s %"+strconv.Itoa(maxApiNameSize+1)+"s  %s\n"
 
             fmt.Fprintf(color.Output,
@@ -410,7 +422,7 @@
             fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
 
             for i:=0; i<len(retApiArray.Apis); i++ {
-                printFilteredListRow(retApiArray.Apis[i].ApiValue, api, maxActionNameSize, maxApiNameSize)
+                printFilteredListRow(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions), maxActionNameSize, maxApiNameSize)
             }
         }
 
@@ -423,20 +435,20 @@
  * and some filtering configuration.  For each API endpoint matching the filtering criteria, display
  * each endpoint's configuration - one line per configuration property (action name, verb, api name, api gw url)
  */
-func printFilteredListApi(resultApi *whisk.RetApi, api *whisk.Api) {
+func printFilteredListApi(resultApi *whisk.RetApi, api *whisk.ApiOptions) {
     baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
     apiName := resultApi.Swagger.Info.Title
     basePath := resultApi.Swagger.BasePath
     if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
         for path, _ := range resultApi.Swagger.Paths {
             whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing api relpath: %s\n", path)
-            if ( len(api.GatewayRelPath) == 0 || path == api.GatewayRelPath) {
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
                 whisk.Debug(whisk.DbgInfo, "apiGetCmd: relpath matches\n")
                 for op, opv  := range resultApi.Swagger.Paths[path] {
                     whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing operation: '%s'\n", op)
-                    if ( len(api.GatewayMethod) == 0 || strings.ToLower(op) == strings.ToLower(api.GatewayMethod)) {
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
                         whisk.Debug(whisk.DbgInfo, "apiGetCmd: operation matches: %#v\n", opv)
-                        var actionName = "/"+opv["x-ibm-op-ext"]["actionNamespace"].(string)+"/"+opv["x-ibm-op-ext"]["actionName"].(string)
+                        var actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
                         fmt.Printf("%s: %s\n", wski18n.T("Action"), actionName)
                         fmt.Printf("  %s: %s\n", wski18n.T("API Name"), apiName)
                         fmt.Printf("  %s: %s\n", wski18n.T("Base path"), basePath)
@@ -457,19 +469,19 @@
  *
  * NOTE: Large action name and api name value will be truncated by their associated max size parameters.
  */
-func printFilteredListRow(resultApi *whisk.RetApi, api *whisk.Api, maxActionNameSize int, maxApiNameSize int) {
+func printFilteredListRow(resultApi *whisk.RetApi, api *whisk.ApiOptions, maxActionNameSize int, maxApiNameSize int) {
     baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
     apiName := resultApi.Swagger.Info.Title
     if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
         for path, _ := range resultApi.Swagger.Paths {
             whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing api relpath: %s\n", path)
-            if ( len(api.GatewayRelPath) == 0 || path == api.GatewayRelPath) {
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
                 whisk.Debug(whisk.DbgInfo, "apiGetCmd: relpath matches\n")
                 for op, opv  := range resultApi.Swagger.Paths[path] {
                     whisk.Debug(whisk.DbgInfo, "apiGetCmd: comparing operation: '%s'\n", op)
-                    if ( len(api.GatewayMethod) == 0 || strings.ToLower(op) == strings.ToLower(api.GatewayMethod)) {
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
                         whisk.Debug(whisk.DbgInfo, "apiGetCmd: operation matches: %#v\n", opv)
-                        var actionName = "/"+opv["x-ibm-op-ext"]["actionNamespace"].(string)+"/"+opv["x-ibm-op-ext"]["actionName"].(string)
+                        var actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
                         fmt.Printf(fmtString,
                             actionName[0 : min(len(actionName), maxActionNameSize)],
                             op,
@@ -482,20 +494,20 @@
     }
 }
 
-func getLargestActionNameSize(retApiArray *whisk.RetApiArray, api *whisk.Api) int {
+func getLargestActionNameSize(retApiArray *whisk.RetApiArray, api *whisk.ApiOptions) int {
     var maxNameSize = 0
     for i:=0; i<len(retApiArray.Apis); i++ {
         var resultApi = retApiArray.Apis[i].ApiValue
         if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
             for path, _ := range resultApi.Swagger.Paths {
                 whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
-                if ( len(api.GatewayRelPath) == 0 || path == api.GatewayRelPath) {
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
                     whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
                     for op, opv  := range resultApi.Swagger.Paths[path] {
                         whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
-                        if ( len(api.GatewayMethod) == 0 || strings.ToLower(op) == strings.ToLower(api.GatewayMethod)) {
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
                             whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
-                            var fullActionName = "/"+opv["x-ibm-op-ext"]["actionNamespace"].(string)+"/"+opv["x-ibm-op-ext"]["actionName"].(string)
+                            var fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
                             if (len(fullActionName) > maxNameSize) {
                                 maxNameSize = len(fullActionName)
                             }
@@ -508,7 +520,7 @@
     return maxNameSize
 }
 
-func getLargestApiNameSize(retApiArray *whisk.RetApiArray, api *whisk.Api) int {
+func getLargestApiNameSize(retApiArray *whisk.RetApiArray, api *whisk.ApiOptions) int {
     var maxNameSize = 0
     for i:=0; i<len(retApiArray.Apis); i++ {
         var resultApi = retApiArray.Apis[i].ApiValue
@@ -516,11 +528,11 @@
         if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
             for path, _ := range resultApi.Swagger.Paths {
                 whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
-                if ( len(api.GatewayRelPath) == 0 || path == api.GatewayRelPath) {
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
                     whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
                     for op, opv  := range resultApi.Swagger.Paths[path] {
                         whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
-                        if ( len(api.GatewayMethod) == 0 || strings.ToLower(op) == strings.ToLower(api.GatewayMethod)) {
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
                             whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
                             if (len(apiName) > maxNameSize) {
                                 maxNameSize = len(apiName)
@@ -727,6 +739,7 @@
     return nil, true
 }
 
+
 /*
  * Pull the managedUrl (external API URL) from the API configuration
  */
@@ -749,6 +762,693 @@
     return url
 }
 
+/////////////
+// V2 Cmds //
+/////////////
+var apiCreateCmdV2 = &cobra.Command{
+    Use:           "create ([BASE_PATH] API_PATH API_VERB ACTION] | --config-file CFG_FILE) ",
+    Short:         wski18n.T("create a new API"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+
+        var api *whisk.Api
+        var err error
+        var qname *QualifiedName
+
+        if (len(args) == 0 && flags.api.configfile == "") {
+            whisk.Debug(whisk.DbgError, "No swagger file and no arguments\n")
+            errMsg := wski18n.T("Invalid argument(s). Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return whiskErr
+        } else if (len(args) == 0 && flags.api.configfile != "") {
+            api, err = parseSwaggerApiV2()
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseSwaggerApi() error: %s\n", err)
+                errMsg := wski18n.T("Unable to parse swagger file: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+        } else {
+            if whiskErr := checkArgs(args, 3, 4, "Api create",
+                wski18n.T("Specify a swagger file or specify an API base path with an API path, an API verb, and an action name.")); whiskErr != nil {
+                return whiskErr
+            }
+            api, qname, err = parseApiV2(cmd, args)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "parseApiV2(%s, %s) error: %s\n", cmd, args, err)
+                errMsg := wski18n.T("Unable to parse api command arguments: {{.err}}",
+                    map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+
+            // Confirm that the specified action is a web-action
+            err = isWebAction(client, *qname)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "isWebAction(%v) is false: %s\n", qname, err)
+                whiskErr := whisk.MakeWskError(err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+                return whiskErr
+            }
+        }
+
+        apiCreateReq := new(whisk.ApiCreateRequest)
+        apiCreateReq.ApiDoc = api
+
+        apiCreateReqOptions := new(whisk.ApiCreateRequestOptions)
+        props, _ := readProps(Properties.PropsFile)
+        apiCreateReqOptions.SpaceGuid = strings.Split(props["AUTH"], ":")[0]
+        apiCreateReqOptions.AccessToken = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            apiCreateReqOptions.AccessToken = props["APIGW_ACCESS_TOKEN"]
+        }
+        apiCreateReqOptions.ResponseType = flags.api.resptype
+        whisk.Debug(whisk.DbgInfo, "AccessToken: %s\nSpaceGuid: %s\nResponsType: %s",
+            apiCreateReqOptions.AccessToken, apiCreateReqOptions.SpaceGuid, apiCreateReqOptions.ResponseType)
+
+        retApi, _, err := client.Apis.InsertV2(apiCreateReq, apiCreateReqOptions, whisk.DoNotOverwrite)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.InsertV2(%#v, false) error: %s\n", api, err)
+            errMsg := wski18n.T("Unable to create API: {{.err}}", map[string]interface{}{"err": err})
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+
+        if (api.Swagger == "") {
+            baseUrl := retApi.BaseUrl
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": strings.TrimSuffix(api.GatewayBasePath, "/")+api.GatewayRelPath,
+                        "verb": api.GatewayMethod,
+                        "name": boldString("/"+api.Action.Namespace+"/"+api.Action.Name),
+                        "fullpath": strings.TrimSuffix(baseUrl, "/")+api.GatewayRelPath,
+                    }))
+        } else {
+            whisk.Debug(whisk.DbgInfo, "Processing swagger based create API response\n")
+            baseUrl := retApi.BaseUrl
+            for path, _ := range retApi.Swagger.Paths {
+                managedUrl := strings.TrimSuffix(baseUrl, "/")+path
+                whisk.Debug(whisk.DbgInfo, "Managed path: %s\n",managedUrl)
+                for op, opv  := range retApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "Path operation: %s\n", op)
+                    var fqActionName string
+                    if (len(opv.XOpenWhisk.Package) > 0) {
+                        fqActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                    } else {
+                        fqActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                    }
+                    whisk.Debug(whisk.DbgInfo, "baseUrl %s  Path %s  Path obj %+v\n", baseUrl, path, opv)
+                    fmt.Fprintf(color.Output,
+                        wski18n.T("{{.ok}} created API {{.path}} {{.verb}} for action {{.name}}\n{{.fullpath}}\n",
+                            map[string]interface{}{
+                                "ok": color.GreenString("ok:"),
+                                "path": strings.TrimSuffix(retApi.Swagger.BasePath, "/") + path,
+                                "verb": op,
+                                "name": boldString(fqActionName),
+                                "fullpath": managedUrl,
+                            }))
+                }
+            }
+        }
+
+
+        return nil
+    },
+}
+
+var apiGetCmdV2 = &cobra.Command{
+    Use:           "get BASE_PATH | API_NAME",
+    Short:         wski18n.T("get API details"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var isBasePathArg bool = true
+
+        if whiskErr := checkArgs(args, 1, 1, "Api get",
+            wski18n.T("An API base path or API name is required.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+        apiGetReqOptions.ApiBasePath = args[0]
+        props, _ := readProps(Properties.PropsFile)
+        apiGetReqOptions.SpaceGuid = strings.Split(props["AUTH"], ":")[0]
+        apiGetReqOptions.AccessToken = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            apiGetReqOptions.AccessToken = props["APIGW_ACCESS_TOKEN"]
+        }
+
+        retApi, _, err := client.Apis.GetV2(apiGetReq, apiGetReqOptions)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.GetV2(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
+            errMsg := wski18n.T("Unable to get API '{{.name}}': {{.err}}", map[string]interface{}{"name": args[0], "err": err})
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+        whisk.Debug(whisk.DbgInfo, "client.Apis.GetV2 returned: %#v\n", retApi)
+
+        var displayResult interface{} = nil
+        if (flags.common.detail) {
+            if (retApi.Apis != nil && len(retApi.Apis) > 0 &&
+            retApi.Apis[0].ApiValue != nil) {
+                displayResult = retApi.Apis[0].ApiValue
+            } else {
+                whisk.Debug(whisk.DbgError, "No result object returned\n")
+            }
+        } else {
+            if (retApi.Apis != nil && len(retApi.Apis) > 0 &&
+            retApi.Apis[0].ApiValue != nil &&
+            retApi.Apis[0].ApiValue.Swagger != nil) {
+                displayResult = retApi.Apis[0].ApiValue.Swagger
+            } else {
+                whisk.Debug(whisk.DbgError, "No swagger returned\n")
+            }
+        }
+        if (displayResult == nil) {
+            var errMsg string
+            if (isBasePathArg) {
+                errMsg = wski18n.T("API does not exist for basepath {{.basepath}}",
+                    map[string]interface{}{"basepath": args[0]})
+            } else {
+                errMsg = wski18n.T("API does not exist for API name {{.apiname}}",
+                    map[string]interface{}{"apiname": args[0]})
+            }
+
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+        printJSON(displayResult)
+
+        return nil
+    },
+}
+
+var apiDeleteCmdV2 = &cobra.Command{
+    Use:           "delete BASE_PATH | API_NAME [API_PATH [API_VERB]]",
+    Short:         wski18n.T("delete an API"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+
+        if whiskErr := checkArgs(args, 1, 3, "Api delete",
+            wski18n.T("An API base path or API name is required.  An optional API relative path and operation may also be provided.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        apiDeleteReq := new(whisk.ApiDeleteRequest)
+        apiDeleteReqOptions := new(whisk.ApiDeleteRequestOptions)
+        props, _ := readProps(Properties.PropsFile)
+        apiDeleteReqOptions.SpaceGuid = strings.Split(props["AUTH"], ":")[0]
+        apiDeleteReqOptions.AccessToken = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            apiDeleteReqOptions.AccessToken = props["APIGW_ACCESS_TOKEN"]
+        }
+
+        // Is the argument a basepath (must start with /) or an API name
+        if _, ok := isValidBasepath(args[0]); !ok {
+            whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
+            apiDeleteReqOptions.ApiBasePath = args[0]
+        } else {
+            apiDeleteReqOptions.ApiBasePath = args[0]
+        }
+
+        if (len(args) > 1) {
+            // Is the API path valid?
+            if whiskErr, ok := isValidRelpath(args[1]); !ok {
+                return whiskErr
+            }
+            apiDeleteReqOptions.ApiRelPath = args[1]
+        }
+        if (len(args) > 2) {
+            // Is the API verb valid?
+            if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
+                return whiskErr
+            }
+            apiDeleteReqOptions.ApiVerb = strings.ToUpper(args[2])
+        }
+
+        _, err := client.Apis.DeleteV2(apiDeleteReq, apiDeleteReqOptions)
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "client.Apis.DeleteV2(%#v, %#v) error: %s\n", apiDeleteReq, apiDeleteReqOptions, err)
+            errMsg := wski18n.T("Unable to delete API: {{.err}}", map[string]interface{}{"err": err})
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+            return whiskErr
+        }
+
+        if (len(args) == 1) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted API {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        } else if (len(args) == 2 ) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted {{.path}} from {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        } else {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} deleted {{.path}} {{.verb}} from {{.basepath}}\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                        "path": apiDeleteReqOptions.ApiRelPath,
+                        "verb": apiDeleteReqOptions.ApiVerb,
+                        "basepath": apiDeleteReqOptions.ApiBasePath,
+                    }))
+        }
+
+        return nil
+    },
+}
+
+var apiListCmdV2 = &cobra.Command{
+    Use:           "list [[BASE_PATH | API_NAME] [API_PATH [API_VERB]]",
+    Short:         wski18n.T("list APIs"),
+    SilenceUsage:  true,
+    SilenceErrors: true,
+    PreRunE:       setupClientConfig,
+    RunE: func(cmd *cobra.Command, args []string) error {
+        var err error
+        var retApiList *whisk.ApiListResponseV2
+        var retApi *whisk.ApiGetResponseV2
+        var retApiArray *whisk.RetApiArrayV2
+
+        if whiskErr := checkArgs(args, 0, 3, "Api list",
+            wski18n.T("Optional parameters are: API base path (or API name), API relative path and operation.")); whiskErr != nil {
+            return whiskErr
+        }
+
+        props, _ := readProps(Properties.PropsFile)
+        spaceguid := strings.Split(props["AUTH"], ":")[0]
+        var accesstoken string = "DUMMY_TOKEN"
+        if len(props["APIGW_ACCESS_TOKEN"]) > 0 {
+            accesstoken = props["APIGW_ACCESS_TOKEN"]
+        }
+
+        // Get API request body
+        apiGetReq := new(whisk.ApiGetRequest)
+        apiGetReq.Namespace = client.Config.Namespace
+        // Get API request options
+        apiGetReqOptions := new(whisk.ApiGetRequestOptions)
+        apiGetReqOptions.AccessToken = accesstoken
+        apiGetReqOptions.SpaceGuid = spaceguid
+
+        // List API request query parameters
+        apiListReqOptions := new(whisk.ApiListRequestOptions)
+        apiListReqOptions.Limit = flags.common.limit
+        apiListReqOptions.Skip = flags.common.skip
+        apiListReqOptions.AccessToken = accesstoken
+        apiListReqOptions.SpaceGuid = spaceguid
+
+        if (len(args) == 0) {
+            retApiList, _, err = client.Apis.ListV2(apiListReqOptions)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Apis.ListV2(%#v) error: %s\n", apiListReqOptions, err)
+                errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+            whisk.Debug(whisk.DbgInfo, "client.Apis.ListV2 returned: %#v (%+v)\n", retApiList, retApiList)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArrayV2)(retApiList)
+        } else {
+            // The first argument is either a basepath (must start with /) or an API name
+            apiGetReqOptions.ApiBasePath = args[0]
+            if (len(args) > 1) {
+                // Is the API path valid?
+                if whiskErr, ok := isValidRelpath(args[1]); !ok {
+                    return whiskErr
+                }
+                apiGetReqOptions.ApiRelPath = args[1]
+            }
+            if (len(args) > 2) {
+                // Is the API verb valid?
+                if whiskErr, ok := IsValidApiVerb(args[2]); !ok {
+                    return whiskErr
+                }
+                apiGetReqOptions.ApiVerb = strings.ToUpper(args[2])
+            }
+
+            retApi, _, err = client.Apis.GetV2(apiGetReq, apiGetReqOptions)
+            if err != nil {
+                whisk.Debug(whisk.DbgError, "client.Apis.GetV2(%#v, %#v) error: %s\n", apiGetReq, apiGetReqOptions, err)
+                errMsg := wski18n.T("Unable to obtain the API list: {{.err}}", map[string]interface{}{"err": err})
+                whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                    whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
+                return whiskErr
+            }
+            whisk.Debug(whisk.DbgInfo, "client.Apis.GetV2 returned: %#v\n", retApi)
+            // Cast to a common type to allow for code to print out apilist response or apiget response
+            retApiArray = (*whisk.RetApiArrayV2)(retApi)
+        }
+
+        // Display the APIs - applying any specified filtering
+        if (flags.common.full) {
+            fmt.Fprintf(color.Output,
+                wski18n.T("{{.ok}} APIs\n",
+                    map[string]interface{}{
+                        "ok": color.GreenString("ok:"),
+                    }))
+
+            for i:=0; i<len(retApiArray.Apis); i++ {
+                printFilteredListApiV2(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions))
+            }
+        } else {
+            if (len(retApiArray.Apis) > 0) {
+                // Dynamically create the output format string based on the maximum size of the
+                // fully qualified action name and the API Name.
+                maxActionNameSize := min(40, max(len("Action"), getLargestActionNameSizeV2(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
+                maxApiNameSize := min(30, max(len("API Name"), getLargestApiNameSizeV2(retApiArray, (*whisk.ApiOptions)(apiGetReqOptions))))
+                fmtString = "%-"+strconv.Itoa(maxActionNameSize)+"s %7s %"+strconv.Itoa(maxApiNameSize+1)+"s  %s\n"
+                fmt.Fprintf(color.Output,
+                    wski18n.T("{{.ok}} APIs\n",
+                        map[string]interface{}{
+                            "ok": color.GreenString("ok:"),
+                        }))
+                fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
+                for i:=0; i<len(retApiArray.Apis); i++ {
+                    printFilteredListRowV2(retApiArray.Apis[i].ApiValue, (*whisk.ApiOptions)(apiGetReqOptions), maxActionNameSize, maxApiNameSize)
+                }
+            } else {
+                fmt.Fprintf(color.Output,
+                    wski18n.T("{{.ok}} APIs\n",
+                        map[string]interface{}{
+                            "ok": color.GreenString("ok:"),
+                        }))
+                fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL")
+            }
+        }
+
+        return nil
+    },
+}
+
+/*
+ * Takes an API object (containing one more more single basepath/relpath/operation triplets)
+ * and some filtering configuration.  For each API endpoint matching the filtering criteria, display
+ * each endpoint's configuration - one line per configuration property (action name, verb, api name, api gw url)
+ */
+func printFilteredListApiV2(resultApi *whisk.RetApiV2, api *whisk.ApiOptions) {
+    baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
+    apiName := resultApi.Swagger.Info.Title
+    basePath := resultApi.Swagger.BasePath
+    if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+        for path, _ := range resultApi.Swagger.Paths {
+            whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: comparing api relpath: %s\n", path)
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: relpath matches\n")
+                for op, opv  := range resultApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: comparing operation: '%s'\n", op)
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                        whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: operation matches: %#v\n", opv)
+                        var actionName string
+                        if (len(opv.XOpenWhisk.Package) > 0) {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                        } else {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                        }
+                        fmt.Printf("%s: %s\n", wski18n.T("Action"), actionName)
+                        fmt.Printf("  %s: %s\n", wski18n.T("API Name"), apiName)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Base path"), basePath)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Path"), path)
+                        fmt.Printf("  %s: %s\n", wski18n.T("Verb"), op)
+                        fmt.Printf("  %s: %s\n", wski18n.T("URL"), baseUrl+path)
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Takes an API object (containing one more more single basepath/relpath/operation triplets)
+ * and some filtering configuration.  For each API matching the filtering criteria, display the API
+ * on a single line (action name, verb, api name, api gw url).
+ *
+ * NOTE: Large action name and api name value will be truncated by their associated max size parameters.
+ */
+func printFilteredListRowV2(resultApi *whisk.RetApiV2, api *whisk.ApiOptions, maxActionNameSize int, maxApiNameSize int) {
+    baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/")
+    apiName := resultApi.Swagger.Info.Title
+    if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+        for path, _ := range resultApi.Swagger.Paths {
+            whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: comparing api relpath: %s\n", path)
+            if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: relpath matches\n")
+                for op, opv  := range resultApi.Swagger.Paths[path] {
+                    whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: comparing operation: '%s'\n", op)
+                    if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                        whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: operation matches: %#v\n", opv)
+                        var actionName string
+                        if (len(opv.XOpenWhisk.Package) > 0) {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                        } else {
+                            actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                        }
+                        fmt.Printf(fmtString,
+                            actionName[0 : min(len(actionName), maxActionNameSize)],
+                            op,
+                            apiName[0 : min(len(apiName), maxApiNameSize)],
+                            baseUrl+path)
+                    }
+                }
+            }
+        }
+    }
+}
+
+func getLargestActionNameSizeV2(retApiArray *whisk.RetApiArrayV2, api *whisk.ApiOptions) int {
+    var maxNameSize = 0
+    for i:=0; i<len(retApiArray.Apis); i++ {
+        var resultApi = retApiArray.Apis[i].ApiValue
+        if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+            for path, _ := range resultApi.Swagger.Paths {
+                whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                    whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
+                    for op, opv  := range resultApi.Swagger.Paths[path] {
+                        whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                            whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
+                            var fullActionName string
+                            if (len(opv.XOpenWhisk.Package) > 0) {
+                                fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName
+                            } else {
+                                fullActionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.ActionName
+                            }
+                            if (len(fullActionName) > maxNameSize) {
+                                maxNameSize = len(fullActionName)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return maxNameSize
+}
+
+func getLargestApiNameSizeV2(retApiArray *whisk.RetApiArrayV2, api *whisk.ApiOptions) int {
+    var maxNameSize = 0
+    for i:=0; i<len(retApiArray.Apis); i++ {
+        var resultApi = retApiArray.Apis[i].ApiValue
+        apiName := resultApi.Swagger.Info.Title
+        if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) {
+            for path, _ := range resultApi.Swagger.Paths {
+                whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing api relpath: %s\n", path)
+                if ( len(api.ApiRelPath) == 0 || path == api.ApiRelPath) {
+                    whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: relpath matches\n")
+                    for op, opv  := range resultApi.Swagger.Paths[path] {
+                        whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: comparing operation: '%s'\n", op)
+                        if ( len(api.ApiVerb) == 0 || strings.ToLower(op) == strings.ToLower(api.ApiVerb)) {
+                            whisk.Debug(whisk.DbgInfo, "getLargestActionNameSize: operation matches: %#v\n", opv)
+                            if (len(apiName) > maxNameSize) {
+                                maxNameSize = len(apiName)
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return maxNameSize
+}
+
+/*
+ * if # args = 4
+ * args[0] = API base path
+ * args[0] = API relative path
+ * args[1] = API verb
+ * args[2] = Optional.  Action name (may or may not be qualified with namespace and package name)
+ *
+ * if # args = 3
+ * args[0] = API relative path
+ * args[1] = API verb
+ * args[2] = Optional.  Action name (may or may not be qualified with namespace and package name)
+ */
+func parseApiV2(cmd *cobra.Command, args []string) (*whisk.Api, *QualifiedName, error) {
+    var err error
+    var basepath string = "/"
+    var apiname string
+    var basepathArgIsApiName = false;
+
+    api := new(whisk.Api)
+
+    if (len(args) > 3) {
+        // Is the argument a basepath (must start with /) or an API name
+        if _, ok := isValidBasepath(args[0]); !ok {
+            whisk.Debug(whisk.DbgInfo, "Treating '%s' as an API name; as it does not begin with '/'\n", args[0])
+            basepathArgIsApiName = true;
+        }
+        basepath = args[0]
+
+        // Shift the args so the remaining code works with or without the explicit base path arg
+        args = args[1:]
+    }
+
+    // Is the API path valid?
+    if (len(args) > 0) {
+        if whiskErr, ok := isValidRelpath(args[0]); !ok {
+            return nil, nil, whiskErr
+        }
+        api.GatewayRelPath = args[0]    // Maintain case as URLs may be case-sensitive
+    }
+
+    // Is the API verb valid?
+    if (len(args) > 1) {
+        if whiskErr, ok := IsValidApiVerb(args[1]); !ok {
+            return nil, nil, whiskErr
+        }
+        api.GatewayMethod = strings.ToUpper(args[1])
+    }
+
+    // Is the specified action name valid?
+    var qName QualifiedName
+    if (len(args) == 3) {
+        qName = QualifiedName{}
+        qName, err = parseQualifiedName(args[2])
+        if err != nil {
+            whisk.Debug(whisk.DbgError, "parseQualifiedName(%s) failed: %s\n", args[2], err)
+            errMsg := wski18n.T("'{{.name}}' is not a valid action name: {{.err}}",
+                map[string]interface{}{"name": args[2], "err": err})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, nil, whiskErr
+        }
+        if (qName.entityName == "") {
+            whisk.Debug(whisk.DbgError, "Action name '%s' is invalid\n", args[2])
+            errMsg := wski18n.T("'{{.name}}' is not a valid action name.", map[string]interface{}{"name": args[2]})
+            whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, nil, whiskErr
+        }
+    }
+
+    if ( len(flags.api.apiname) > 0 ) {
+        if (basepathArgIsApiName) {
+            // Specifying API name as argument AND as a --apiname option value is invalid
+            whisk.Debug(whisk.DbgError, "API is specified as an argument '%s' and as a flag '%s'\n", basepath, flags.api.apiname)
+            errMsg := wski18n.T("An API name can only be specified once.")
+            whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+                whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+            return nil, nil, whiskErr
+        }
+        apiname = flags.api.apiname
+    }
+
+    api.Namespace = client.Config.Namespace
+    api.Action = new(whisk.ApiAction)
+    var urlActionPackage string
+    if (len(qName.packageName) > 0) {
+        urlActionPackage = qName.packageName
+    } else {
+        urlActionPackage = "default"
+    }
+    api.Action.BackendUrl = "https://" + client.Config.Host + "/api/v1/web/" + qName.namespace + "/" + urlActionPackage + "/" + qName.entity + ".http"
+    api.Action.BackendMethod = api.GatewayMethod
+    api.Action.Name = qName.entityName
+    api.Action.Namespace = qName.namespace
+    api.Action.Auth = client.Config.AuthToken
+    api.ApiName = apiname
+    api.GatewayBasePath = basepath
+    if (!basepathArgIsApiName) { api.Id = "API:"+api.Namespace+":"+api.GatewayBasePath }
+
+    whisk.Debug(whisk.DbgInfo, "Parsed api struct: %#v\n", api)
+    return api, &qName, nil
+}
+
+func parseSwaggerApiV2() (*whisk.Api, error) {
+    // Test is for completeness, but this situation should only arise due to an internal error
+    if ( len(flags.api.configfile) == 0 ) {
+        whisk.Debug(whisk.DbgError, "No swagger file is specified\n")
+        errMsg := wski18n.T("A configuration file was not specified.")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg),whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    swagger, err:= readFile(flags.api.configfile)
+    if ( err != nil ) {
+        whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Error reading swagger file '{{.name}}': {{.err}}",
+            map[string]interface{}{"name": flags.api.configfile, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    // Parse the JSON into a swagger object
+    swaggerObj := new(whisk.ApiSwaggerV2)
+    err = json.Unmarshal([]byte(swagger), swaggerObj)
+    if ( err != nil ) {
+        whisk.Debug(whisk.DbgError, "JSON parse of `%s' error: %s\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Error parsing swagger file '{{.name}}': {{.err}}",
+            map[string]interface{}{"name": flags.api.configfile, "err": err})
+        whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+    if (swaggerObj.BasePath == "" || swaggerObj.SwaggerName == "" || swaggerObj.Info == nil || swaggerObj.Paths == nil) {
+        whisk.Debug(whisk.DbgError, "Swagger file is invalid.\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Swagger file is invalid (missing basePath, info, paths, or swagger fields)")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+    if _, ok := isValidBasepath(swaggerObj.BasePath); !ok {
+        whisk.Debug(whisk.DbgError, "Swagger file basePath is invalid.\n", flags.api.configfile, err)
+        errMsg := wski18n.T("Swagger file basePath must start with a leading slash (/)")
+        whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXITCODE_ERR_GENERAL,
+            whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
+        return nil, whiskErr
+    }
+
+    api := new(whisk.Api)
+    api.Namespace = client.Config.Namespace
+    api.Swagger = swagger
+
+    return api, nil
+}
+
 ///////////
 // Flags //
 ///////////
@@ -756,17 +1456,13 @@
 func init() {
     apiCreateCmd.Flags().StringVarP(&flags.api.apiname, "apiname", "n", "", wski18n.T("Friendly name of the API; ignored when CFG_FILE is specified (default BASE_PATH)"))
     apiCreateCmd.Flags().StringVarP(&flags.api.configfile, "config-file", "c", "", wski18n.T("`CFG_FILE` containing API configuration in swagger JSON format"))
-
     //apiUpdateCmd.Flags().StringVarP(&flags.api.action, "action", "a", "", wski18n.T("`ACTION` to invoke when API is called"))
     //apiUpdateCmd.Flags().StringVarP(&flags.api.path, "path", "p", "", wski18n.T("relative `PATH` of API"))
     //apiUpdateCmd.Flags().StringVarP(&flags.api.verb, "method", "m", "", wski18n.T("API `VERB`"))
-
     apiGetCmd.Flags().BoolVarP(&flags.common.detail, "full", "f", false, wski18n.T("display full API configuration details"))
-
     apiListCmd.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
     apiListCmd.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
     apiListCmd.Flags().BoolVarP(&flags.common.full, "full", "f", false, wski18n.T("display full description of each API"))
-
     apiExperimentalCmd.AddCommand(
         apiCreateCmd,
         //apiUpdateCmd,
@@ -774,4 +1470,18 @@
         apiDeleteCmd,
         apiListCmd,
     )
+
+    apiCreateCmdV2.Flags().StringVarP(&flags.api.apiname, "apiname", "n", "", wski18n.T("Friendly name of the API; ignored when CFG_FILE is specified (default BASE_PATH)"))
+    apiCreateCmdV2.Flags().StringVarP(&flags.api.configfile, "config-file", "c", "", wski18n.T("`CFG_FILE` containing API configuration in swagger JSON format"))
+    apiCreateCmdV2.Flags().StringVar(&flags.api.resptype, "response-type", "json", wski18n.T("Set the web action response `TYPE`. Possible values are html, http, json, text, svg"))
+    apiGetCmdV2.Flags().BoolVarP(&flags.common.detail, "full", "f", false, wski18n.T("display full API configuration details"))
+    apiListCmdV2.Flags().IntVarP(&flags.common.skip, "skip", "s", 0, wski18n.T("exclude the first `SKIP` number of actions from the result"))
+    apiListCmdV2.Flags().IntVarP(&flags.common.limit, "limit", "l", 30, wski18n.T("only return `LIMIT` number of actions from the collection"))
+    apiListCmdV2.Flags().BoolVarP(&flags.common.full, "full", "f", false, wski18n.T("display full description of each API"))
+    apiCmd.AddCommand(
+        apiCreateCmdV2,
+        apiGetCmdV2,
+        apiDeleteCmdV2,
+        apiListCmdV2,
+    )
 }
diff --git a/commands/flags.go b/commands/flags.go
index 9f632bd..e48ac93 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -117,6 +117,7 @@
         basepath   string
         apiname    string
         configfile string
+        resptype   string
     }
 }
 
diff --git a/commands/package.go b/commands/package.go
index b8eda24..939eff5 100644
--- a/commands/package.go
+++ b/commands/package.go
@@ -192,7 +192,12 @@
     p, _, err = client.Packages.Insert(p, false)
     if err != nil {
       whisk.Debug(whisk.DbgError, "client.Packages.Insert(%#v, false) failed: %s\n", p, err)
-      errStr := wski18n.T("Package creation failed: {{.err}}", map[string]interface{}{"err":err})
+      errStr := wski18n.T(
+        "Unable to create package '{{.name}}': {{.err}}",
+        map[string]interface{}{
+          "name": qName.entityName,
+          "err": err,
+        })
       werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
       return werr
     }
@@ -318,7 +323,12 @@
     xPackage, _, err := client.Packages.Get(qName.entityName)
     if err != nil {
       whisk.Debug(whisk.DbgError, "client.Packages.Get(%s) failed: %s\n", qName.entityName, err)
-      errStr := wski18n.T("Package get failed: {{.err}}", map[string]interface{}{"err":err})
+      errStr := wski18n.T(
+        "Unable to get package '{{.name}}': {{.err}}",
+        map[string]interface{}{
+          "name": qName.entityName,
+          "err":err,
+        })
       werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
       return werr
     }
@@ -370,7 +380,12 @@
     _, err = client.Packages.Delete(qName.entityName)
     if err != nil {
       whisk.Debug(whisk.DbgError, "client.Packages.Delete(%s) failed: %s\n", qName.entityName, err)
-      errStr := wski18n.T("Package delete failed: {{.err}}", map[string]interface{}{"err":err})
+      errStr := wski18n.T(
+        "Unable to delete package '{{.name}}': {{.err}}",
+        map[string]interface{}{
+          "name": qName.entityName,
+          "err": err,
+        })
       werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
       return werr
     }
diff --git a/commands/rule.go b/commands/rule.go
index 8454807..b537aff 100644
--- a/commands/rule.go
+++ b/commands/rule.go
@@ -146,7 +146,7 @@
         rule, _, err := client.Rules.Get(ruleName)
         if err != nil {
             whisk.Debug(whisk.DbgError, "client.Rules.Get(%s) failed: %s\n", ruleName, err)
-            errStr := wski18n.T("Unable to retrieve rule '{{.name}}': {{.err}}",
+            errStr := wski18n.T("Unable to get status of rule '{{.name}}': {{.err}}",
                     map[string]interface{}{"name": ruleName, "err": err})
             werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
             return werr
@@ -305,7 +305,7 @@
         rule, _, err := client.Rules.Get(ruleName)
         if err != nil {
             whisk.Debug(whisk.DbgError, "client.Rules.Get(%s) failed: %s\n", ruleName, err)
-            errStr := wski18n.T("Unable to retrieve rule '{{.name}}': {{.err}}",
+            errStr := wski18n.T("Unable to get rule '{{.name}}': {{.err}}",
                     map[string]interface{}{"name": ruleName, "err": err})
             werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
             return werr
diff --git a/commands/util.go b/commands/util.go
index ad51ac2..ccabcd1 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -42,9 +42,10 @@
 )
 
 type QualifiedName struct {
-    namespace   string
-    packageName string
-    entityName  string
+    namespace   string  // namespace. does not include leading '/'.  may be "" (i.e. default namespace)
+    packageName string  // package.  may be "".  does not include leading/trailing '/'
+    entity      string  // entity.  should not be ""
+    entityName  string  // pkg+entity
 }
 
 func (qName QualifiedName) String() string {
@@ -100,6 +101,10 @@
         }
 
         qualifiedName.entityName = strings.Join(parts[2:], "/")
+        if len(parts) == 4 {
+            qualifiedName.packageName = parts[2]
+        }
+        qualifiedName.entity = parts[len(parts)-1]
     } else {
         if len(name) == 0 || name == "." {
             whisk.Debug(whisk.DbgError, "A valid qualified name was not detected\n")
@@ -108,12 +113,19 @@
             return qualifiedName, err
         }
 
+        parts := strings.Split(name, "/")
+        qualifiedName.entity = parts[len(parts)-1]
+        if len(parts) == 2 {
+            qualifiedName.packageName = parts[0]
+        }
         qualifiedName.entityName = name
         qualifiedName.namespace = getNamespace()
     }
 
-    whisk.Debug(whisk.DbgInfo, "Qualified entityName: %s\n", qualifiedName.entityName)
-    whisk.Debug(whisk.DbgInfo, "Qaulified namespace: %s\n", qualifiedName.namespace)
+    whisk.Debug(whisk.DbgInfo, "Qualified pkg+entity (EntityName): %s\n", qualifiedName.entityName)
+    whisk.Debug(whisk.DbgInfo, "Qualified namespace: %s\n", qualifiedName.namespace)
+    whisk.Debug(whisk.DbgInfo, "Qualified package: %s\n", qualifiedName.packageName)
+    whisk.Debug(whisk.DbgInfo, "Qualified entity: %s\n", qualifiedName.entity)
 
     return qualifiedName, nil
 }
@@ -168,9 +180,11 @@
     whisk.Debug(whisk.DbgInfo, "Convert content to JSON: %#v\n", content)
 
     for i := 0; i < len(content); i++ {
-        if err := json.Unmarshal([]byte(content[i]), &data); err != nil {
-            whisk.Debug(whisk.DbgError, "Invalid JSON detected for '%s'\n", content[i])
-            return whisk.KeyValueArr{}, err
+        dc := json.NewDecoder(strings.NewReader(content[i]))
+        dc.UseNumber()
+        if err := dc.Decode(&data); err!=nil {
+            whisk.Debug(whisk.DbgError, "Invalid JSON detected for '%s' \n", content[i])
+            return whisk.KeyValueArr{} , err
         }
 
         whisk.Debug(whisk.DbgInfo, "Created map '%v' from '%v'\n", data, content[i])
diff --git a/commands/wsk.go b/commands/wsk.go
index 870a510..beca322 100644
--- a/commands/wsk.go
+++ b/commands/wsk.go
@@ -48,6 +48,7 @@
         namespaceCmd,
         listCmd,
         apiExperimentalCmd,
+        apiCmd,
     )
 
     WskCmd.PersistentFlags().BoolVarP(&flags.global.verbose, "verbose", "v", false, wski18n.T("verbose output"))
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 8a60560..2a0deb4 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -120,8 +120,8 @@
     "translation": "create a new package"
   },
   {
-    "id": "Package creation failed: {{.err}}",
-    "translation": "Package creation failed: {{.err}}"
+    "id": "Unable to create package '{{.name}}': {{.err}}",
+    "translation": "Unable to create package '{{.name}}': {{.err}}"
   },
   {
     "id": "{{.ok}} created package {{.name}}\n",
@@ -144,8 +144,8 @@
     "translation": "get package"
   },
   {
-    "id": "Package get failed: {{.err}}",
-    "translation": "Package get failed: {{.err}}"
+    "id": "Unable to get package '{{.name}}': {{.err}}",
+    "translation": "Unable to get package '{{.name}}': {{.err}}"
   },
   {
     "id": "{{.ok}} got package {{.name}}\n",
@@ -156,8 +156,8 @@
     "translation": "delete package"
   },
   {
-    "id": "Package delete failed: {{.err}}",
-    "translation": "Package delete failed: {{.err}}"
+    "id": "Unable to delete package '{{.name}}': {{.err}}",
+    "translation": "Unable to delete package '{{.name}}': {{.err}}"
   },
   {
     "id": "{{.ok}} deleted package {{.name}}\n",
@@ -421,8 +421,12 @@
     "translation": "get rule status"
   },
   {
-    "id": "Unable to retrieve rule '{{.name}}': {{.err}}",
-    "translation": "Unable to retrieve rule '{{.name}}': {{.err}}"
+    "id": "Unable to get rule '{{.name}}': {{.err}}",
+    "translation": "Unable to get rule '{{.name}}': {{.err}}"
+  },
+  {
+    "id": "Unable to get status of rule '{{.name}}': {{.err}}",
+    "translation": "Unable to get status of rule '{{.name}}': {{.err}}"
   },
   {
     "id": "{{.ok}} rule {{.name}} is {{.status}}\n",
@@ -772,8 +776,8 @@
     "translation": "Unable to parse action command arguments: {{.err}}"
   },
   {
-    "id": "Unable to create action: {{.err}}",
-    "translation": "Unable to create action: {{.err}}"
+    "id": "Unable to create action '{{.name}}': {{.err}}",
+    "translation": "Unable to create action '{{.name}}': {{.err}}"
   },
   {
     "id": "{{.ok}} created action {{.name}}\n",
@@ -824,8 +828,8 @@
     "translation": "delete action"
   },
   {
-    "id": "Unable to delete action: {{.err}}",
-    "translation": "Unable to delete action: {{.err}}"
+    "id": "Unable to delete action '{{.name}}': {{.err}}",
+    "translation": "Unable to delete action '{{.name}}': {{.err}}"
   },
   {
     "id": "{{.ok}} deleted action {{.name}}\n",
@@ -844,8 +848,8 @@
     "translation": "Could not find 'main' method in '{{.name}}'"
   },
   {
-    "id": "Unable to obtain action '{{.name}}' to copy: {{.err}}",
-    "translation": "Unable to obtain action '{{.name}}' to copy: {{.err}}"
+    "id": "Unable to get action '{{.name}}': {{.err}}",
+    "translation": "Unable to get action '{{.name}}': {{.err}}"
   },
   {
     "id": "File '{{.name}}' is not a valid file or it does not exist: {{.err}}",
@@ -908,8 +912,8 @@
     "translation": "blocking invoke"
   },
   {
-    "id": "show only activation result if a blocking activation (unless there is a failure)",
-    "translation": "show only activation result if a blocking activation (unless there is a failure)"
+    "id": "blocking invoke; show only activation result (unless there is a failure)",
+    "translation": "blocking invoke; show only activation result (unless there is a failure)"
   },
   {
     "id": "exclude the first `SKIP` number of actions from the result",
@@ -944,8 +948,8 @@
     "translation": "get activation"
   },
   {
-    "id": "Unable to obtain activation record for '{{.id}}': {{.err}}",
-    "translation": "Unable to obtain activation record for '{{.id}}': {{.err}}"
+    "id": "Unable to get activation '{{.id}}': {{.err}}",
+    "translation": "Unable to get activation '{{.id}}': {{.err}}"
   },
   {
     "id": "activation result for /{{.namespace}}/{{.name}} ({{.status}} at {{.time}})\n",
@@ -960,12 +964,12 @@
     "translation": "get the logs of an activation"
   },
   {
-    "id": "Unable to obtain logs for activation '{{.id}}': {{.err}}",
-    "translation": "Unable to obtain logs for activation '{{.id}}': {{.err}}"
+    "id": "Unable to get logs for activation '{{.id}}': {{.err}}",
+    "translation": "Unable to get logs for activation '{{.id}}': {{.err}}"
   },
   {
-    "id": "Unable to obtain result information for activation '{{.id}}': {{.err}}",
-    "translation": "Unable to obtain result information for activation '{{.id}}': {{.err}}"
+    "id": "Unable to get result for activation '{{.id}}': {{.err}}",
+    "translation": "Unable to get result for activation '{{.id}}': {{.err}}"
   },
   {
     "id": "poll continuously for log messages from currently running actions",
@@ -1208,16 +1212,16 @@
     "translation": "get API"
   },
   {
-    "id": "Unable to get API: {{.err}}",
-    "translation": "Unable to get API: {{.err}}"
+    "id": "Unable to get API '{{.name}}': {{.err}}",
+    "translation": "Unable to get API '{{.name}}': {{.err}}"
   },
   {
     "id": "delete an API",
     "translation": "delete an API"
   },
   {
-    "id": "Unable to delete action: {{.err}}",
-    "translation": "Unable to delete action: {{.err}}"
+    "id": "Unable to delete API: {{.err}}",
+    "translation": "Unable to delete API: {{.err}}"
   },
   {
     "id": "{{.ok}} deleted API {{.basepath}}\n",
@@ -1374,5 +1378,69 @@
   {
     "id": "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'.",
     "translation": "Invalid argument '{{.arg}}' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
+  },
+  {
+    "id": "API action does not exist",
+    "translation": "API action does not exist"
+  },
+  {
+    "id": "API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action.",
+    "translation": "API action '{{.name}}' is not a web action. Issue 'wsk action update {{.name}} --web true' to convert the action to a web action."
+  },
+  {
+    "id": "Invalid configuration. The x-openwhisk stanza is missing.",
+    "translation": "Invalid configuration. The x-openwhisk stanza is missing."
+  },
+  {
+    "id": "Internal error. Missing value stanza in API configuration response",
+    "translation": "Internal error. Missing value stanza in API configuration response"
+  },
+  {
+    "id": "Internal error. Missing apidoc stanza in API configuration",
+    "translation": "Internal error. Missing apidoc stanza in API configuration"
+  },
+  {
+    "id": "Missing operationId field in API configuration for operation {{.op}}",
+    "translation": "Missing operationId field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk stanza in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk stanza in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk.namespace field in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk.namespace field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk.action field in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk.action field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "Missing x-openwhisk.url field in API configuration for operation {{.op}}",
+    "translation": "Missing x-openwhisk.url field in API configuration for operation {{.op}}"
+  },
+  {
+    "id": "work with APIs",
+    "translation": "work with APIs"
+  },
+  {
+    "id": "create a new API",
+    "translation": "create a new API"
+  },
+  {
+    "id": "get API details",
+    "translation": "get API details"
+  },
+  {
+    "id": "delete an API",
+    "translation": "delete an API"
+  },
+  {
+    "id": "list APIs",
+    "translation": "list APIs"
+  },
+  {
+    "id": "Set the web action response TYPE. Possible values are html, http, json, text, svg",
+    "translation": "Set the web action response TYPE. Possible values are html, http, json, text, svg"
   }
 ]