271

A REST API can have arguments in several places:

  1. In the request body - As part of a json body, or other MIME type
  2. In the query string - e.g. /api/resource?p1=v1&p2=v2
  3. As part of the URL-path - e.g. /api/resource/v1/v2

What are the best practices and considerations of choosing between 1 and 2 above?
2 vs 3 is covered here.

Henke
  • 4,445
  • 3
  • 31
  • 44
Jonathan Livni
  • 101,334
  • 104
  • 266
  • 359
  • 4
    Does this answer your question? [REST API Best practices: Where to put parameters?](https://stackoverflow.com/questions/4024271/rest-api-best-practices-where-to-put-parameters) – Steve Chambers Nov 27 '19 at 08:56
  • 2
    In addition to the above, how about using header ? – variable Jul 20 '20 at 10:07

4 Answers4

114

What are the best practices and considerations of choosing between 1 and 2 above?

Usually the content body is used for the data that is to be uploaded/downloaded to/from the server and the query parameters are used to specify the exact data requested. For example when you upload a file you specify the name, mime type, etc. in the body but when you fetch list of files you can use the query parameters to filter the list by some property of the files. In general, the query parameters are property of the query not the data.

Of course this is not a strict rule - you can implement it in whatever way you find more appropriate/working for you.

You might also want to check the wikipedia article about query string, especially the first two paragraphs.

stan0
  • 11,549
  • 6
  • 42
  • 59
  • 3
    A reasonable takeaway to your above analysis is that idempotent operations are best kept in the url query strings and CRUD is best kept to strictly typed response bodies, which essentially takes advantage of SOP and prevents very basic forms of social engineering/phishing attacks – Rice Aug 19 '19 at 22:03
  • 3
    @Rice R in CRUD is an indempotent operation. – user398039 Aug 12 '20 at 15:26
58

I'll assume you are talking about POST/PUT requests. Semantically the request body should contain the data you are posting or patching.

The query string, as part of the URL (a URI), it's there to identify which resource you are posting or patching.

You asked for a best practices, following semantics are mine. Of course using your rules of thumb should work, specially if the web framework you use abstract this into parameters.

You most know:

  • Some web servers have limits on the length of the URI.
  • You can send parameters inside the request body with CURL.
  • Where you send the data shouldn't have effect on debugging.
Leonel Galán
  • 6,993
  • 2
  • 41
  • 60
  • 1
    is there any source you can cite in terms of the semantic that for post requests the request body should contain the data ? – Pfinnn Aug 02 '22 at 15:42
36

The following are my rules of thumb...

When to use the body:

  • When the arguments don't have a flat key:value structure
  • If the values are not human readable, such as serialized binary data
  • When you have a very large number of arguments

When to use the query string:

  • When the arguments are such that you want to see them while debugging
  • When you want to be able to call them manually while developing the code e.g. with curl
  • When arguments are common across many web services
  • When you're already sending a different content-type such as application/octet-stream

Notice you can mix and match - put the the common ones, the ones that should be debugable in the query string, and throw all the rest in the json.

Jonathan Livni
  • 101,334
  • 104
  • 266
  • 359
  • 73
    Selecting how to structure your API based on development convenience is not a good practice. – Eric Stein Aug 19 '14 at 14:42
  • 2
    Like @EricStein said, you've got it backwards. – DanMan Aug 19 '14 at 20:11
  • 42
    Guys, the reason I asked the question is to get the right answer. Go ahead, write an answer and I'll remove my flawed one. @EricStein – Jonathan Livni Aug 20 '14 at 11:41
  • The second argument for the query can also be used for the body as you can also use `curl` to edit the body. – Ioanna Oct 30 '17 at 10:00
  • 4
    @Jonathan apis that are easy to consume via human hands are almost always good apis. Kudos for accurately calling out KISS – Chris Marisic Feb 20 '18 at 16:56
  • @Jonathan I didn't quite get last point in the query string "When you're already sending a different content-type such as application/octet-stream" what does it mean? could you please give an example. Thanks. – Akshay Hiremath Jul 31 '19 at 16:48
  • 1
    @AkshayHiremath He's referring to the fact that you might be sending something else in the body, e.g. if you sent a ContentType header like "image/jpeg" you would need to have your message body contain the jpeg data and could not include anything else in it – shayaan Feb 26 '20 at 16:20
16

The reasoning I've always used is that because POST, PUT, and PATCH presumably have payloads containing information that customers might consider proprietary, the best practice is to put all payloads for those methods in the request body, and not in the URL parms, because it's very likely that somewhere, somehow, URL text is being logged by your web server and you don't want customer data getting splattered as plain text into your log filesystem.

That potential exposure via the URL isn't an issue for GET or DELETE or any of the other REST operations.

cvkline
  • 415
  • 5
  • 7