The API continues to evolve...

A couple months back as part of our Roadmap to v2, I made the claim that one of the large features in that release would be the merging of the Write API plugin into core. The majority of the exploratory work had been completed in a development branch reserved for v2-only changes, but the need for a consistent RESTful API became more and more important, and we simply could not wait for v2 (which hadn't and still hasn't, a release date) to drop.

So two months ago, I started pulling out this work to a separate branch based off of master, and set about to finishing the integration. I'm proud to say that the preliminary release of this API has been merged into core, and is available starting v1.15.0.

Better yet, the docs have been much improved, and are now maintained similar to the Read API, using the OpenAPI v3 format, and can be found here 👇

Write API Documentation

Isn't "Write API" a misnomer?

Yes! In a sense, it is a transitionary title while the API evolves over time.

  • The Read API, such as it is, contains a number of non-GET routes
    • These would mostly be upload-specific routes (avatars, cover photos, topic thumbnails, etc.)
  • The Write API, on the other hand, does contain a couple of GET routes, and will be gaining more, over time.

The nomenclature comes from its predecessor, nodebb-plugin-write-api. I wanted to keep the feature name similar so as to reduce confusion.

Over time, we intend to introduce additional GET routes, especially for new feature construction (or rewrites of such). For example, the topic thumbnail functionality is currently undergoing a rewrite, and will using the Write API exclusively.

All routes using the new Write API are visually separate from the Read API routes in that they all begin with /api/v3 (e.g. POST api/v3/topics to create a new topic.)

Eventually, the plan is to rename the Write API into the REST API (imaginative, I know.)

Does this mean the death of the /api prefix?

Not at all! The existing API will continue to be maintained. We have no plans to deprecate this API. It will likely be renamed from Read API to Page API or similar. This is purely for aesthetics.

Oftentimes, we would tell clients that any page you can browse to, you can see its underlying data by prepending /api onto that page's path. This remains true today, but we also want the reverse to be true. This means additional routes would be removed from the Read API and ported over to the Write API.

NodeBB's existing frontend uses the Read API exclusively to render page templates, and to that end the Read API is functioning as intended. The Write API was originally intended to allow external services (and specific usage from within NodeBB) leaner access to forum resources.

What's with the /api/v3 prefix?

My plan with the Write API was to iterate on version numbers whenever there were breaking changes. There was one major change, which brought the plugin's prefix to api/v2, and for this move, we will be bumping it one last time (more on why below) to api/v3. I chose to continue with api/v3 as it would not conflict with users who wished to use the Write API plugin in parallel with a newer version of NodeBB.

Keep in mind: Most users of the Write API should be able to migrate to v3 with no significant issues.

The full list of breaking changes from v2 to v3 can be found here.

Eventually, I intend to introduce a versioning system for the API, inspired by the Stripe API team. They release new versions of their API prolifically, versioned by the date (e.g. 2017-05-24), and requests sent in to the API with that specific version number will instruct Stripe to mutate the response to match what the response would have looked like under that version. It absolutely blows my mind how that worked, and my plan is to mimic something similar for successive releases of the API.

How does this play with NodeBB's websocket implementation?

The websockets/ interface was never meant to be for external use. We rely on websockets for real-time events, such as new posts, notifications, online indicators, etc.

I fully admit (on behalf of my peers Baris and Andrew) that we abused this system to also handle simpler requests for information, or to instruct the server to do things.

These call-and-response type of requests were not what was designed for. That said, it handles these types of actions without breaking a sweat, but why reinvent the wheel when a battle-hardened version exists in the form of HTTP requests? even falls back to using XHR when a websocket connection is not available, imagine that!

Let me be clear, we have no intention of dropping our use of When we implement real-time events on websockets/, they work really really well, and it would be much easier to treat our use of websockets simply as a form of progressive enhancement, rather than an integral part of our software which won't work without it.

There is one (rather significant) additional reason why I personally wanted to switch to using a REST API — many of our clients don't have the technical knowledge to interface via websockets. This was the original reason why the Write API was created, but if a client wanted functionality that wasn't provided by that API, they were essentially SOL because domain knowledge on how to connect to a websocket server was far and few between. HTTP is a no-brainer, and many many developers know how to handle and negotiate responses with external APIs.

As an extension to that reason — if clients couldn't easily figure it out, neither could (or would) white-hat hackers. This meant that we had a blind spot in our websocket implementation, in that fewer eyes were looking at the code, and fewer people were trying to break in, simply due to the relative obscurity of websockets. While security by obscurity can be a part of your security plan, relying solely on security by obscurity is plain bad practice. The easier it is to interface with NodeBB, the easier it will be for clients to use, and for us to feel assured that it is implemented in a safe way.

The remaining 10%

Getting the rest of the call-and-response usages of websockets migrated to the Write API is the last 10%, and of course, the 10% is the hardest and dullest work. Once we're done this, we'll likely move forward with the name change from Write API to REST API.

The average end-user of NodeBB shouldn't see a single bit of difference in their every day use. If nobody can see what I'm doing, I'd consider the migration a success 🙂