# API requests using GET method with body content

**URL:** https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710
**Category:** general
**Created:** [January 31, 2023, 11:51pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710 "2023-01-31T23:51:13Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![Tim\_McCollough](https://community.openboxes.com/user_avatar/community.openboxes.com/tim_mccollough/32/623_2.png) [@Tim\_McCollough](https://community.openboxes.com/u/Tim_McCollough)
#### Post date: [January 31, 2023, 11:51pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/1 "2023-01-31T23:51:13Z")

</div>

I have been perusing the OpenBoxes API documentation, and I have found several cases of an API that uses the HTTP GET method, but also necessitates the use of a JSON in the request body.

It has been my understanding that including request body content in a GET request is problematic because the semantics of such requests are left wholly undefined. That is, it is very unpredictable what various intervening proxies, caches, gateways and other tooling does with these kinds of requests; some forbid body content, some dispose of body content, some use only the URL to return cached content.

See this url for discussion of this topic:

> <https://stackoverflow.com/questions/978061/http-get-with-request-body>

The tooling I am using does not allow GET method to have body content without jumping through some hoops.

Do these APIs allow an alternate HTTP method (i.e. POST) to perform the same function?

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 1, 2023, 4:10am UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/2 "2023-02-01T04:10:52Z")

</div>

Can you provide an example of where we use GET requests with a body?

GET requests are generally used to retrieve data (either a list of objects or a single object), POST requests are used to create objects and PUT requests are used to update existing objects.

We tend to use mostly GET for retrieve and POST for create and update (sometimes deletes). I’m pretty sure you can use PUT for updates and DELETE for deletes in most cases as well.

---

<div class="post-metadata">

### Author: ![Tim\_McCollough](https://community.openboxes.com/user_avatar/community.openboxes.com/tim_mccollough/32/623_2.png) [@Tim\_McCollough](https://community.openboxes.com/u/Tim_McCollough)
#### Post date: [February 1, 2023, 12:35pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/3 "2023-02-01T12:35:57Z")

</div>

[https://docs.openboxes.com/en/develop/api-guide/product/#list](https://docs.openboxes.com/en/develop/api-guide/product/#list)

> Blockquote

```auto
$ curl -i -X GET -H "Content-Type: application/json" -b cookies.txt \
-d '{ "offset":0, "max":1 }' https://openboxes.ngrok.io/openboxes/api/products

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 10 Jun 2018 22:13:27 GMT
[{
    "id": "ff80818155df9de40155df9e329b0009",
    "productCode": "00003",
    "name": "Aspirin 20mg",
    "category": {
        "id": "1",
        "name": "Medicines"
    },
    "description": null,
    "dateCreated": "2016-07-12T14:58:55Z",
    "lastUpdated": "2016-07-12T14:58:55Z"
}]

```

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 1, 2023, 2:52pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/4 "2023-02-01T14:52:48Z")

</div>

Yeah if you want you can pass the data in the URL as request parameters.

```auto
curl -i -X GET -H "Content-Type: application/json" -b cookies.txt \ 
https://openboxes.ngrok.io/openboxes/api/products?max=1&offset=0

```

---

<div class="post-metadata">

### Author: ![Tim\_McCollough](https://community.openboxes.com/user_avatar/community.openboxes.com/tim_mccollough/32/623_2.png) [@Tim\_McCollough](https://community.openboxes.com/u/Tim_McCollough)
#### Post date: [February 1, 2023, 3:08pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/5 "2023-02-01T15:08:47Z")

</div>

This is true in general wherever a GET is used with a request body? The json attributes can be passed as URL parameters?

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 1, 2023, 5:33pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/6 "2023-02-01T17:33:19Z")

</div>

I think this is generally true but let us know if you encounter an API where this doesn’t hold.

---

<div class="post-metadata">

### Author: ![Tim\_McCollough](https://community.openboxes.com/user_avatar/community.openboxes.com/tim_mccollough/32/623_2.png) [@Tim\_McCollough](https://community.openboxes.com/u/Tim_McCollough)
#### Post date: [February 1, 2023, 9:09pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/7 "2023-02-01T21:09:00Z")

</div>

Just a note to inform you of a mistake in the documentation of the “Products” api. The document quoted above in this conversation implies that the payload of the response is a JSON array. This is in fact not true. The payload is in fact an object that contains two fields “data” which is an array, and “totalCount” which apparently gives a count of the number of elements available to be returned.

---

<div class="post-metadata">

### Author: ![Tim\_McCollough](https://community.openboxes.com/user_avatar/community.openboxes.com/tim_mccollough/32/623_2.png) [@Tim\_McCollough](https://community.openboxes.com/u/Tim_McCollough)
#### Post date: [February 7, 2023, 1:44pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/8 "2023-02-07T13:44:20Z")

</div>

The /product/search endpoint is implemented using the GET method, and it seems to require json body content. It does not work to pass in the search arguments in URL query string. But, as stated before, body content on a get method is undefined in the HTTP RFC, so tooling does not allow for (i.e. Apache’s HTTPClient)

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 7, 2023, 2:48pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/9 "2023-02-07T14:48:54Z")

</div>

Thanks @Tim_McCollough. Can you provide an example of a search that isn’t working?

---

<div class="post-metadata">

### Author: ![Tim\_McCollough](https://community.openboxes.com/user_avatar/community.openboxes.com/tim_mccollough/32/623_2.png) [@Tim\_McCollough](https://community.openboxes.com/u/Tim_McCollough)
#### Post date: [February 7, 2023, 2:55pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/10 "2023-02-07T14:55:48Z")

</div>

Using the example given in the Generic API documentation for searches. I have no idea how an array of search criteria would be converted to query parameters. Do you?

```auto
$ curl -i -X GET -H "Content-Type: application/json" -b cookies.txt \
-d '{"searchAttributes":[{"property":"name", "operator":"ilike", "value":"Ace%"}]}' \
https://openboxes.ngrok.io/openboxes/api/generic/product/search?max=1

```

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 7, 2023, 3:38pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/11 "2023-02-07T15:38:02Z")

</div>

Ah, the generic API. I’ll take a look and see if there’s something we can do here.

Disclaimer: The Generic APIs are there as a catch-all for our domain classes. They were meant to satisfy some basic requirements (search, retrieve, save) as we flesh out the APIs needed for the application.

You can also use the main Products API. There are two endpoints (list, search) that support basic search on products. See below for examples of how to use them.

The documentation for the APIs is admittedly pretty weak, so you’ll need to look at the code to get a better understanding of what is supported.

> **[Products - OpenBoxes](https://docs.openboxes.com/en/latest/api-guide/product/#search)**
>
> OpenBoxes documentation

But, for what it’s worth, that’s why I created this discussion forum. Since we’re an open-source project with limited funding, we don’t have unlimited resources for writing documentation. Therefore, I deployed this Discourse instance because I wanted to make sure users and developers had the ability to get answers to their questions.

So don’t feel like you’re imposing by asking tons of questions. It’ll help us grow.

From my perspective, posting specific questions about what you are trying to implement does at least three things for the community:

1. Allows us to help you (and others) to answer specific questions and move your projects forward
2. Allows us to figure out what documentation we need to write
3. Allows us to better understand what features we need to support

Here are a few examples. We could/should do a better job of standardizing these endpoints but again don’t hesitate to tell us what you’re looking to do and we’ll provide some ideas on how to achieve your goals.

Lookup by name, product code, etc

```auto
$ curl -b cookies.txt -X GET -H "Content-Type: application/json" 
https://demo.openboxes.com/openboxes/api/products?q=KS08
{
  "data": [
    {
      "id": "c1e344344072bbd501407a6d5fcd0003",
      "productCode": "KS08",
      "name": "Kojin?s",
      "description": "Juodos spalvos kojin?s",
      "category": "Apparel",
      "unitOfMeasure": "35",
      "pricePerUnit": 50,
      "dateCreated": "2013-08-14T01:25:23Z",
      "lastUpdated": "Sep 01, 2021",
      "updatedBy": "Anahy R",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null,
      "active": true
    }
  ],
  "totalCount": 1
}

```

Search by name, product code, etc

```auto
$ curl -b cookies.txt -X GET -H "Content-Type: application/json" 
https://demo.openboxes.com/openboxes/api/products/search?name=Ibuprofen
{
  "data": [
    {
      "id": "c1e344344072bbd50140ba2c40f4010a",
      "productCode": "BU45",
      "name": "Ibuprofen 200mg",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e34434413773c60141bcacee1000f1",
      "productCode": "PC26",
      "name": "Ibuprofen or Placebo",
      "color": null,
      "handlingIcons": [
        {
          "icon": "fa-snowflake",
          "color": "#3bafda",
          "label": "Cold chain"
        }
      ],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e344344200f2cb014253b54fcd009d",
      "productCode": "NK001",
      "name": "Ibuprofen, 200mg",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e3443443b6764c0143bfee85960019",
      "productCode": "JX55",
      "name": "Ibuprofen",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e34434445c2b5301448c50ba990038",
      "productCode": "KY96",
      "name": "Ibuprofen",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e344344fccfaf0014ffb173ed21214",
      "productCode": "GK86",
      "name": "Ibuprofen 200mg tablet",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e34434665700290166896b13fc3100",
      "productCode": "EE87",
      "name": "Ibuprofen, 200mg",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e34434665700290166b8a4464367f9",
      "productCode": "i001",
      "name": "Ibuprofen ",
      "color": null,
      "handlingIcons": [
        {
          "icon": "fa-exclamation-circle",
          "color": "#db1919",
          "label": "Controlled substance"
        }
      ],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e344346fecc3df01706fa5146801d9",
      "productCode": "ibuprofen 200",
      "name": "Ibuprofen 200mg tablet",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e34434727d92fb01749f93018a090c",
      "productCode": "ib002343153112",
      "name": "Ibuprofen 200mg",
      "color": null,
      "handlingIcons": [
        {
          "icon": "fa-snowflake",
          "color": "#3bafda",
          "label": "Cold chain"
        },
        {
          "icon": "fa-exclamation-triangle",
          "color": "#ffa500",
          "label": "Hazardous material"
        }
      ],
      "lotAndExpiryControl": null
    },
    {
      "id": "c1e34434766833b101773234427b02ad",
      "productCode": "GX24",
      "name": "Ibuprofen 200mg",
      "color": null,
      "handlingIcons": [
        {
          "icon": "fa-exclamation-circle",
          "color": "#db1919",
          "label": "Controlled substance"
        }
      ],
      "lotAndExpiryControl": null
    },
    {
      "id": "ff8081817f4160ad0180447b9ecf02de",
      "productCode": "7861194608327",
      "name": "Ibuprofen 200mg",
      "color": null,
      "handlingIcons": [
        {
          "icon": "fa-snowflake",
          "color": "#3bafda",
          "label": "Cold chain"
        }
      ],
      "lotAndExpiryControl": null
    },
    {
      "id": "ff8081818125768501829d16213503bf",
      "productCode": "0265748646",
      "name": "Ibuprofen 200mg",
      "color": null,
      "handlingIcons": [],
      "lotAndExpiryControl": true
    }
  ]
}

```

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 7, 2023, 3:39pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/12 "2023-02-07T15:39:55Z")

</div>

And you are correct, there’s no way for the search criteria to be converted to query parameters.

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 7, 2023, 3:51pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/13 "2023-02-07T15:51:59Z")

</div>

Also, can you describe what hoops you need to jump through to use a JSON body on GET requests using the Apache HttpClient?

---

<div class="post-metadata">

### Author: ![Tim\_McCollough](https://community.openboxes.com/user_avatar/community.openboxes.com/tim_mccollough/32/623_2.png) [@Tim\_McCollough](https://community.openboxes.com/u/Tim_McCollough)
#### Post date: [February 7, 2023, 4:18pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/14 "2023-02-07T16:18:14Z")

</div>

The simplest solution I have found (using Stack Overflow) Is sub-classing the HttpPost class and then overriding the _getMethod()_ to return “GET” rather than “POST”. I guess it isn’t that much of a hoop.

> public static class HttpGetWithEntity extends HttpPost {

```
    public final static String METHOD_NAME = "GET";

    public HttpGetWithEntity(URI url) {
        super(url);
    }

    public HttpGetWithEntity(String url) {
        super(url);
    }

    @Override
    public String getMethod() {
        return METHOD_NAME;
    }
}

```

FYI: This does work and I am able to search using the generic product search.

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [February 8, 2023, 6:58am UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/15 "2023-02-08T06:58:10Z")

</div>

Oh, nice. A little annoying but I’ve done similar things to work around similar issues.

In addition, I’ll look into what it would take to allow POST requests for advanced search APIs like this one.

---

<div class="post-metadata">

### Author: ![Gideon](https://community.openboxes.com/user_avatar/community.openboxes.com/gideon/32/805_2.png) [@Gideon](https://community.openboxes.com/u/Gideon)
#### Post date: [December 28, 2023, 7:34am UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/16 "2023-12-28T07:34:47Z")

</div>

I have been trying to create stock requests using /openboxes/api/stockMovements endpoint with the following JSON body but it does not work. I got error 500 - internal server error. Is there a way this can be fixed?

{  
“errorCode”: 500,  
“cause”: “java.lang.NullPointerException”,  
“errorMessage”: “Cannot get property ‘id’ on null object”  
}

**JSON body**  
{  
“name”: “my new stock movement2”,  
“description”: “same as name”,  
“identifier”: “483ZSA”,  
“origin.id”: “2”,  
“destination.id”: “1”,  
“dateRequested”: “12/27/2023”,  
“requestedBy.id”: “1”,  
“lineItems”: [{  
“product.id”: “ff8081818b2e8f2a018c9651ea8400f8”,  
“quantityRequested”: “102”,  
“sortOrder”: 0,  
“recipient.id”: “1”  
}]  
}

---

<div class="post-metadata">

### Author: ![Gideon](https://community.openboxes.com/user_avatar/community.openboxes.com/gideon/32/805_2.png) [@Gideon](https://community.openboxes.com/u/Gideon)
#### Post date: [December 28, 2023, 7:37am UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/17 "2023-12-28T07:37:41Z")

</div>

**Catalina.out**

2023-12-28 07:10:51,323 [http-bio-0.0.0.0-8080-exec-366] INFO filters.SecurityFilters - stockMovementApi.create: [user:admin, location:null]  
2023-12-28 07:10:51,323 [http-bio-0.0.0.0-8080-exec-366] INFO filters.SecurityFilters - No rule for stockMovementApi:create → allow anonymous  
2023-12-28 07:10:51,326 [http-bio-0.0.0.0-8080-exec-366] INFO core.UserService - Is role ROLE\_ADMIN in [ROLE\_AUTHENTICATED, ROLE\_SUPERUSER, ROLE\_BROWSER, ROLE\_MANAGER, ROLE\_ASSISTANT, ROLE\_ADMIN] = true  
2023-12-28 07:10:51,350 [http-bio-0.0.0.0-8080-exec-366] ERROR errors.GrailsExceptionResolver - Exception occurred when processing request: [POST] /openboxes/api/stockMovements  
Stacktrace follows:  
java.lang.NullPointerException: Cannot get property ‘id’ on null object  
at org.pih.warehouse.api.StockMovementApiController$\_closure3.doCall(StockMovementApiController.groovy:113)  
at org.pih.warehouse.api.StockMovementApiController$\_closure3.call(StockMovementApiController.groovy)  
at grails.plugin.springcache.web.GrailsFragmentCachingFilter.doFilter(GrailsFragmentCachingFilter.groovy:66)  
at net.sf.ehcache.constructs.web.filter.Filter.doFilter(Filter.java:86)  
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)  
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:622)  
at java.lang.Thread.run(Thread.java:748)  
2023-12-28 07:10:51,353 [http-bio-0.0.0.0-8080-exec-366] INFO filters.SecurityFilters - errors.handleException: [user:admin, location:null]  
2023-12-28 07:10:51,353 [http-bio-0.0.0.0-8080-exec-366] INFO filters.SecurityFilters - No rule for errors:handleException → allow anonymous  
2023-12-28 07:10:51,354 [http-bio-0.0.0.0-8080-exec-366] INFO filters.SecurityFilters - Request duration for (errors/handleException): 1ms/0ms  
2023-12-28 07:10:51,355 [http-bio-0.0.0.0-8080-exec-366] INFO filters.SecurityFilters - Request duration for (errors/handleException): 1ms/1ms

---

<div class="post-metadata">

### Author: ![jmiranda](https://community.openboxes.com/user_avatar/community.openboxes.com/jmiranda/32/199_2.png) [@jmiranda](https://community.openboxes.com/u/jmiranda)
#### Post date: [December 30, 2023, 2:52pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/18 "2023-12-30T14:52:34Z")

</div>

Sorry for the delay @Gideon. Most of us are on leave this week for Christmas. I can take a closer look at this next week, but I have a suggestion below.

My guess is that you haven’t logged into a location and some APIs don’t handle that gracefully yet. We plan to add some better validation and error handling to prevent this, but it looks like the docs are woefully quiet on the subject as well. So I’ve added a ticket to deal with that.

> <https://github.com/openboxes/openboxes/issues/4437>

You can see what location the application thinks you’re logged into using the logging from the SecurityFilters mechanism.

```auto
2023-12-28 07:10:51,353 [http-bio-0.0.0.0-8080-exec-366] INFO filters.SecurityFilters - errors.handleException: [user:admin, location:null]

```

There are two ways to choose a location

1. While authenticating, you can provide a location property in your JSON body

2. After authenticating, you can call the Choose Location API.

---

<div class="post-metadata">

### Author: ![Gideon](https://community.openboxes.com/user_avatar/community.openboxes.com/gideon/32/805_2.png) [@Gideon](https://community.openboxes.com/u/Gideon)
#### Post date: [December 31, 2023, 5:32pm UTC](https://community.openboxes.com/t/api-requests-using-get-method-with-body-content/710/19 "2023-12-31T17:32:52Z")

</div>

Hi Justin,  
I understand the situation and I hope you are enjoying the holidays.

The issue was resolved when I added the location.  
Thank you so much.
