Live data from Hacker News

Ask HN: Best practices (and examples) for designing client libraries for APIs?

news.ycombinator.com

1–10 of 21 posts

Ask HN: Best practices (and examples) for designing client libraries for APIs?

#1
I'm writing a client library for my favorite project management app's API, in PHP. Are there any best practices that I can follow? Can you recommend a good example of such a library (either written by the API provider themselves or by a third party) that I can learn from?

Doesn't need to be in PHP - Java, JS etc works too

Re: Ask HN: Best practices (and examples) for designing client libraries for APIs?

#4
I usually like to have some Client object that’s responsible for establishing connections and performing unauthenticated interactions with the API. For things that require auth, I usually hang a Login / Authenticate method off of the Client that does whatever auth is necessary (you can even have multiple if there are multiple strategies). Those authentication methods usually return some kind of Session that has whatever token is ultimately produced as state. Authenticated methods hang off the Session object. EDIT: One other nice consequence of this design is that a separate Session makes it possible to have multiple simultaneous authenticated sessions while still maintaining the ability to call unauthenticated methods (e.g. Ping()).

I’ve found this prevents users of the library from having to shuttle around credentials and accidentally calling authenticated endpoints without credentials (since those methods don’t even exist off the Client). Also, if the Client is responsible for managing connections, it can also deal with things like rate limiting and whatnot. Finally, having a separate Session object eases testing, as you don’t have to mock the entirety of the auth flow (think of the complexity of OAuth 2.0) in order to get to a state that you care about. You can simply start with “given an authenticated session...”.

There are some other pieces that can be useful too depending on the abstractions available to you in your language of choice. Sometimes I’ll include a lower-level Request to do basic URL construction given a higher-level map of parameters. Corresponding Response objects can occasionally be useful too in those scenarios to unpack JSON / XML / w/e and present a higher-level construct to your methods.

Re: Ask HN: Best practices (and examples) for designing client libraries for APIs?

#5
I've done this a lot, and I'd recommend using HTTPlug here. PHP/composer allows you to require an implementation instead of an actual package, and that lets your users pick the HTTP implementation they'd like to use (Curl/Guzzle/Socket etc).

http://docs.php-http.org/en/latest/httplug/library-developer... is the starting guide and https://packagist.org/providers/psr/http-client-implementati... is all the various providers you will automatically support this way.

There are other pros: you'll be using PSR standards, so it becomes easily extensible. However, there are some limitations, especially if you want to make fairly complex multi-part file uploads (this might have improved since, I'm not sure).

Re: Ask HN: Best practices (and examples) for designing client libraries for APIs?

#7
Creating good APIs is about developing a good taste and not surprise the user.

In your case, the first job of designing the API is done for you by the app.

So as a first step, create the foundation layer by mapping the app's API to simple objects that represent the app's API.

Then you can build a layer above to simplify certain operations and build some logic on top.

Think in terms of responsibilities, relationships and who should know about what. That's how you achieve code reuse. When you find yourself reusing your own constructs, it means you've done something right. I find it's often that developers aim for code reusability, but IMHO code reusability is just a natural outcome to good design decisions.

Use your API by writing pseudo code and see if it makes sense.

Keep iterating. Avoid trying to nail it from the first go. IMO, building functionality is more useful than designing a perfect API.

Re: Ask HN: Best practices (and examples) for designing client libraries for APIs?

#8
Personally, for building a client library I'd take a look at OpenAPI Generator (https://github.com/openapitools/openapi-generator) or Swagger Codegen (https://github.com/swagger-api/swagger-codegen) - especially if the API provider has an official OpenAPI/Swagger specification. (If not you can always write a specification yourself). Both tools support PHP among other languages.

Re: Ask HN: Best practices (and examples) for designing client libraries for APIs?

#9
Honestly, best practices depends on what you are trying to achieve. Why is the API painful to use? Try to address those aspects when creating your client library.

Many API's are easy enough to understand, they don't necessarily get lots of benefit from an official client library. Developers just write the HTTP request code themselves for whichever endpoints they are using. keep it simple if you are first starting.

create a separate file, NameAPI.js, to house your endpoint calling functions. Make it easy for the caller to provide necessary values to those functions. Sometimes API endpoints have a lot of extra optional params/properties. Don't worry about including those in the function interface unless you are actually using them for your use-case--instead choose suitable default params/properties whenever possible.

Then continue to build out your client functions as you need more endpoints or endpoint features.

I would say sometimes its helpful to provide multiple client functions per one endpoint, especially if this endpoint is already loaded with lots of different choices for params/properties. EX: ive seen create user endpoints that require a non-descriptive type property like 1 = basic user 2= admin user etc. well, you could have two client functions createUser vs createAdminUser. In this way, you are taking off some of the burden for the caller to figure out which type number they need to pass, and instead giving them natural language functions which configure and run the HTTP request for them.

A nice to have: make it easy for the caller to pass properties using host language conventions like property name casing. ex: if the host language is in javascript, it may be easier/more consistent for the caller to always provide camelCased params/properties to the function, even if the API endpoint expects snake_case for params/properties (translate the names for your caller).

be clear about how you are handling error conditions in your client functions/package. I think of two basic types of error conditions, network errors vs operational errors. Network errors would be when client has not internet connection or times out for whatever reason. Operational error would be when server DOES send back response but its an error response (like 400's client provided bad values or 500's server is malfunctioning). And will you be throwing errors on network errors AND operational errors? or just throwing on network errors? or not throwing at all (returning some value instead)? basically, how does the caller know when there was an error and what type of error? In Go, i've seen sql clients go through the trouble of returning custom error types for every possible sql error that could happen. That gives the client more potential options to decide how to recover/resume.

If you are first starting, I honestly wouldn't worry about including auth handling within the client. I find it usually confusing more than helpful. But it depends on the protocol and auth method. Perhaps auth IS one of the most painful points of using the API, in that case building some auth management into the client may be helpful. But HTTP + Authorization token is so straightforward and common, developers can manage that auth cred easily in their own way. In that case, just make the token a parameter that must be passed to the client function. That's the simplest way to start.

Next option might be to allow the caller to create an instance of the client for a specific auth cred. Then the caller can use this instance whenever it needs to call client functions given that auth cred, or create multiple instances each with a separate user/service auth cred.

if you are hosting this client as a package for others to use in the community, be sure to stay on top of any API changes which necessitate your client package to be updated. Provide clear documentation about any API changes and how your package has addressed them.

Re: Ask HN: Best practices (and examples) for designing client libraries for APIs?

#10
post #4

I usually like to have some Client object that’s responsible for establishing connections and performing unauthenticated interactions with the API. For things that require auth, I usually hang a Login / Authenticate method off of the Client that does whatever auth is necessary (you can even have multiple if there are multiple strategies). Those authentication methods usually return some kind of Session that has whate…

I agree that a good idea is having a Client object, which main concern is to authenticate to the API and make the first connection. This Client should be in charge of creating instances of each resource available in the API. Don’t try to just offer a replica of the web API: you should figure out which are the most important use cases for the API and then offer them to your end-user. And it’s important to prioritize so you don’t clutter the public interface of the library. If you want to share common features across your resources, you could create a mixin with them.

If you want to check an example, we released just a few days ago a Python-flavored client [1]. The code is readable and still in early stages; hopefully you can borrow a few ideas from there. These guidelines are mainly based on OOP, and Python with its data model (i.e. dunder methods) is flexible enough to offer a great user interface.

[1]: https://github.com/fintoc-com/fintoc-python

Edit: wording

Post reply on HN