Having looked at and created quite a few APIs, I thought I'd put together a few hints on how to create a good, portable API.
First, understand what you're trying to do. Seriously. Writing an application and writing an API are two different things. I've seen some API's which were literally wrappers around a function declaration that looks hauntingly like C's main. Methods in the "API" turned parameters into command-line arguments and passed them in to a single entry point.
Second, decide on your target platform(s) and what resources you'll need and what resources will need to be provided. Choices could include UNIX flavors, Windows, Mac OS, JVM, .NET, etc. This is an important early decision and will determine how much pain you may suffer in the future.
Third, decide on your I/O mechanism, if any. If your answer is "file names", you're probably taking the wrong approach. File names look like they're easy - just pass in a string, hand it to fopen() and off I go. The problem with this is, what constitutes a path? How long is it? What's the path separator? If I am creating the file, who gets ownership? Who has permissions? Are the permissions portable? If components of the path don't exist, should the API create them or fail? You didn't think you'd be creating so many problems with such a simple API, did you? A streaming API is far more flexible and brings far fewer problems. A stream is usually an abstract object that represents a data source or sink (or both) and offers methods to read, write, seek, get position, get length, flush, and close.
Fourth, decide what you need to model and how you're going to do it and then how it will be presented. A perfect example is date and time. There are lots of ways to represent such an object and chances are you will be reinventing the wheel. Look at what your target platform offers before you go make something new. If you are supporting multiple target platforms, you are best off trying to abstract the behavior you want and then implementing the concrete version - maybe in terms of something existing on that platform. By the way, if you need to provide an abstract notion of something, please, please, please create concrete implementations for your target so you clients don't have to. Using the stream idea above, if your target is Windows, do provide at least a stream that constructs from a file handle or a Windows file name. If your target is .NET, include a version that works for Stream. If you do this, your customers will love you. If you don't, your customers will, at best, be annoyed by you. For example, if you create an abstraction of a rectangle that you use in your API's and at least one of your targets is .NET, make sure that your special rectangles can be constructed from .NET System.Drawing.Rectangle and System.Drawing.RectangleF, and generate them as well.
Fifth, understand what you're wrapping fully and if it's obscure, be sure to take some time to explain it in your documentation. Some things that people think they understand, but usually don't include typography, color and color representations, printing, and localization. For each one of these, I can rattle off APIs that are clearly wanting for them (I'm looking at you Graphics.DrawString).