Dealing with API and Error Messages – Best Practices

apicerror messageswcf

We are in the process of constructing an API (using WCF).

So far I noticed 2 ways in which methods could go wrong due to problems with the parameters sent.

  1. wrong format, for example we have a string date parameter which should be in a certain format, if it's in a different format the method cannot continue.
  2. if a method role is to do something identified by an ID, but that ID does not exist in the application (DB)

First we thought throwing an exception, but I realize now that this is not truly an "exceptional" situation, these kind of things is pretty common.

Right now we deal with it in the following way:

We have an abstract class which is called APIResponse.
it has a boolean success variable, and an array of messages for the API's client.
Each group of methods has a corresponding implementation of this class and that will be the returned object.

is this kind of approach ok?

Best Answer

I do like this approach, it is totally acceptable.

Take a look at the Flickr API. They are using error codes and error messages in their api response too.

http://www.flickr.com/services/api/

http://www.flickr.com/services/api/flickr.activity.userComments.html (example api method)

Serving error codes and error messages instead of exceptions is imho much better when dealing with multiple (unknown) client frameworks (.net, java, etc..) If an client api-implementation is wrong because it is using a wrong format, it's much better to display the error message from the server ("Invalid date format. Must be ddMMyyy.") instead of getting an weird "FormatException" (+stacktrace).

Having error ids and error messages:

  • improves api usability
  • improves maintainability
  • improves user / developer experience

API User(Developer) could reference easily to their problem and that will save your time. It would be much easier for you to track down a possible bug/taskswith a specific errorId/errorMessage instead of having "Hey, I'm getting those weird Exceptions when calling XYZ. What am I doing wrong?"

Edit based upon request:

Let's say we have a "BaseResponse" (similar to your APIResponse, comments are stripped out for better readability)

public class BaseResponse
{
  public int ErrorId { get; set; }

  public string ErrorMessage { get; set; }

  public bool Successful { get; set; }
}

And we're having an GetDocumentResponse (implemented by DocumentService, see below)

public sealed class GetDocumentsResponse : BaseResponse
{
   public IList<Document> Documents { get; set; }
}

DocumentService Contract

[ServiceContract]
public interface IDocumentService
{
    [OperationContract]
    [WebInvoke(
         Method = "POST",
         BodyStyle = WebMessageBodyStyle.WrappedRequest,
         ResponseFormat = WebMessageFormat.Json,
         RequestFormat = WebMessageFormat.Json)]
    GetDocumentsResponse GetDocuments(string date);
}

DocumentService Implementation (simplified)

public GetDocumentsResponse GetDocuments(string date)
{
     bool isFormatValid = // parse Date
     if (!isFormatValid)
     {
        // Response = static class, provides generic responses and sets properties of response
        return Response.ProvideFault<GetDocumentsResponse>(100, "The date-format is not valid. Valid: mmddyyyy");
        // return new GetDocumentsResponse { Successful = false, ErrorId: 100, ErrorMessage = "The date-format is not valid. Valid: mmddyyyy"};
     }

     var documents = this.documentRepository.GetDocuments(...)
     return new GetDocumentsResponse { Successful = true, Documents = documents };
}

So, let's say I'm a developer and I want to use this api.

1. - Making an valid api call & getting an valid response from server (JSON Response)

{
   "ErrorId":0,
   "ErrorMessage":null,
   "Successful":true,
   "Documents":[
      {
         "DocumentId":13,
         "Name":"xyz"
      }
   ]
}

2. - Making an invalid api call & getting an invalid response from server

{
   "ErrorId":100,
   "ErrorMessage":"The date-format is invalid. Valid: mmddyyyy",
   "Successful":false,
   "Documents":[

   ]
}

So, for the first call I've done everything right.
The second call says clearly what is wrong, I do not have to research some .NET specific exceptions (or better: wcf faults) if I'm a java developer. In a few seconds after getting the response I do know what went wrong and why it went wrong. I do not have to research documentation or much worse to ask YOU about the current implementation of GetDocuments and why my date format is invalid. It saves you and me a lot of time.