For a long time, my API development workflow lived in Emacs, inside a carefully
maintained api.org
file that grew to nearly 2,000 lines. Each endpoint had a
dedicated section, annotated and structured using org-mode
and
restclient.el
. It was efficient,
flexible, and tightly integrated with my editor.
While Emacs is still my daily driver for note-taking, planning, and writing, the
VS Code REST Client extension
has quietly replaced the need for a dedicated .org
file for API calls.
For example, where I used to write this in Emacs:
#+BEGIN_SRC restclient
POST http://localhost:3000/v1/something
Content-Type: application/json
{
"name": "testing something"
}
#+END_SRC
I now write this:
### @name createSomething
POST http://localhost:3000/v1/something
Content-Type: application/json
{
"name": "testing something"
}
The response can then be reused in subsequent requests without writing scripts
or using tools like jq
to extract values. In Emacs, this might have looked
like:
#+name: get_something_id
#+begin_src restclient :results value :jq-args -r :jq .[0].id
GET http://localhost:3000/v1/something
#+end_src
#+begin_src restclient :var something_id=get_something_id
GET http://localhost:3000/v1/something/:something_id
#+end_src
But in REST Client:
### @name createSomething
POST http://localhost:3000/v1/something
Content-Type: application/json
{
"name": "testing something"
}
### Get something by ID
GET http://localhost:3000/v1/something/{{createSomething.response.body.$.id}}
One unexpected benefit of this switch is how much easier it is to share
endpoints with others on the team, especially when everyone uses the different
tools. These .http
files work well across workflows, and can even be embedded
as http
code blocks in Markdown to mimic the “living documentation” feel of an
org
file.
It’s not a replacement for org-mode
, but for API workflows, the REST Client is
a simpler and more portable alternative. And it helps to have your API tools and
code in the same editor.
Bonus Example: File Uploads
One thing I really disliked in my old setup was having to mix restclient
and
shell
blocks just to upload a file. For example:
#+begin_src shell :var something_id=(org-sbe get_something_id)
curl -F "file=@./something.jpeg" \
"http://localhost:3000/v1/something/:something_id/files"
#+end_src
Using REST Client, I can now write the same thing in a single .http
file:
### Upload file
POST http://localhost:3000/v1/something/{{createSomething.response.body.$.id}}/files
Content-Type: multipart/form-data; boundary=--FileUpload
----FileUpload
Content-Disposition: form-data; name="something"; filename="2194889204.jpeg"
Content-Type: image/jpeg
< ./something.jpeg
----FileUpload--
Note: According to
RFC 2046 Section 5.1.1,
multipart boundaries must start with --
. Easy to overlook when writing by
hand.