Some of the most frequently used Drupal modules derive their popularity not only from the functionality they provide but also through their APIs. For our purposes, an API is, in essence, a set of tools provided by a module that make it easy for developers to extend its functionality via their own code without having to know what's under the hood.
An example of this is the Views module. Views is split into Views and Views UI. Because Views has an API, you can build a different UI on top of Views without modifying it. Another example is Voting API. Voting API makes a wide variety of voting possible since it gives developers access to the voting process at various different points during the voting process. Voting API also provides multiple levels of abstraction so that developers can do basic things like setting a vote or more complex things like voting on multiple parts of some content.
Proving an API also means a module's code does not have to be overcomplicated so that many things are possible even though a given site might only need some of them. In other words, the original module would only need to be modified if a certain process wasn't possible due to limitations of its API. This allows the module's code to be more efficient since only code for the desired functionality gets executed. Having an API also frees up a developers time since the development of new features can be done both others.
One way to developer an API is to focus on the nouns and verbs used to describe the things a module does. This method could also be used to find the accessor and mutator methods of a class in an OOP as these essentially are providing an API to that class. The hooks provided by an API should require a minimum understanding of the underlying code involved. Assumptions about usage and dependences upon other modules should be kept at a minimum. Also, consider writing several test extensions of the module via on top of its API to help identify any logical errors or limitations.