diff --git a/errors.go b/errors.go
index 691a209d0b34f8332a5f04b83656ba1864b3913d..97639d873f99d01450e95eb268a73817b1003eb9 100644
--- a/errors.go
+++ b/errors.go
@@ -100,6 +100,8 @@ func (v *validationError) JSON() []byte {
 	return data
 }
 
+// orNil solves the problem with nil-wrapping interfaces by returning
+// an unwrapped nil if the validationError is nil.
 func (v *validationError) orNil() error {
 	if v == nil {
 		return nil
diff --git a/server/server.go b/server/server.go
index 3cb32aaf7e6eee7ed86e14e9e6a7c854e8d473c2..8e0e7c7780541c053149ea8b12b9afa6b1c4f181 100644
--- a/server/server.go
+++ b/server/server.go
@@ -70,6 +70,10 @@ func New(service *as.AccountService, backend as.Backend) *APIServer {
 
 var emptyResponse struct{}
 
+type jsonError interface {
+	JSON() []byte
+}
+
 func (s *APIServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 	// Create a new empty request object based on the request
 	// path, then decode the HTTP request JSON body onto it.
@@ -85,7 +89,15 @@ func (s *APIServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 
 	resp, err := s.service.Handle(req.Context(), r)
 	if err != nil {
-		http.Error(w, err.Error(), errToStatus(err))
+		// Handle structured errors, serve a JSON response.
+		status := errToStatus(err)
+		if jerr, ok := err.(jsonError); ok {
+			w.Header().Set("Content-Type", "application/json")
+			w.WriteHeader(status)
+			w.Write(jerr.JSON()) // nolint
+		} else {
+			http.Error(w, err.Error(), status)
+		}
 	} else {
 		// Don't send nulls, send empty dicts instead.
 		if resp == nil {