I'm trying to POST a new item to my SharePoint 365 list via Java 6. (I know this is an old version. This is a technology constraint I have to work with.)

First I worked out the url and the body and tried my post in Postman, and that creates a new list item and gets a 201 back as expected. But when I try it in Java I get 400.

SimpleDateFormat sdf = new SimpleDateFormat("YYYY-mm-dd hh:mm:ss");
try {
    String url = "https://xxxx.sharepoint.com/sites/yyyy/_api/lists/getbytitle('TaxExemptRecords')/items";
    StringBuilder sb = new StringBuilder();

    String token = "...";
    Calendar c = Calendar.getInstance();
    Date d = c.getTime();
        .append("\"Title\"").append(":").append("\"A Test Fax\",")
        .append("\"Received\"").append(":\"").append( sdf.format(d) ).append("\"")
    String payload = sb.toString();
    Map<String,String> headers = new HashMap<String,String>();
    headers.put("Content-Type", "application/json");
    headers.put("Accept", "application/json");
    headers.put("X-RequestDigest", "...");
    ServiceClient client = new ServiceClient();
    ServiceResponse response = client.Post(url, token, headers, payload);
    } finally {


public ServiceResponse Post(String url, String token, Map<String,String> headers, String body) throws Exception {
    StringBuilder sb = new StringBuilder();
    try {
        URL urlObj = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
        for(String k:headers.keySet()) {
            connection.setRequestProperty(k, headers.get(k));
        connection.setRequestProperty ("Authorization", "Bearer " + token);
        OutputStream os = connection.getOutputStream();
        byte[] input = body.getBytes();
        os.write(input, 0, input.length);           
        int responseCode = connection.getResponseCode();
        BufferedReader inputReader = new BufferedReader( new InputStreamReader(connection.getInputStream()) );
        String inputLine;
        while ((inputLine = inputReader.readLine()) != null) {
        String responseBody = sb.toString();
        return new ServiceResponse(responseCode, responseBody); 
    } catch(IOException ioe) {
        String stackTrace = Util.ExceptionToString(ioe);
        return null;
    } catch(Exception e) {
        String stackTrace = Util.ExceptionToString(e);
        return null;

Neither my token nor digest is expired. The stack trace doesn't say much:

java.io.IOException: Server returned HTTP response code: 400 for URL: https://xxxxx.sharepoint.com/sites/yyyyy/_api/lists/getbytitle('TaxExemptRecords')/items
    at sun.reflect.GeneratedConstructorAccessor26.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:57)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:437)
    at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1959)
    at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1954)
    at java.security.AccessController.doPrivileged(AccessController.java:694)
    at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1953)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1523)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1507)
    at com.ibm.net.ssl.www2.protocol.https.b.getInputStream(b.java:3)
  • Try setting your Accept and Content-Type headers to application/json;odata=nometadata Feb 21, 2022 at 18:43
  • @Rob, Thanks for that suggestion. I tried that, but it made no difference I can see.
    – Thomas
    Feb 21, 2022 at 19:09

1 Answer 1


It seems like your request body missing __metadata notation.

You need to do GET from this URL https://xxxx.sharepoint.com/sites/yyyy/_api/web/lists/GetByTitle('TaxExemptRecords')?$select=ListItemEntityTypeFullName

Get the value of ListItemEntityTypeFullName, then put it in your request body like below.

    "__metadata": {
        "type": "-------the ListItemEntityTypeFullName value-----"
    "Title": "A Test Fax",
    "SenderFax": "8005551212",
    "SenderState": "TN",
    "Received": "2022-12-31T05:22:00",

Let me know if it works, as I'm not sure what else is missing. Make sure the date format is also in ISO8601.

  • I tried that, it seems to make no difference - not that I can tell by looking a the stack trace anyway. If I log out by headers and payload I get {Accept=application/json;odata=nometadata, X-RequestDigest=xxxxxxxxxxxxxxxxxxxxxxxxx, Content-Type=application/json;odata=nometadata} {"__metadata": {"type": "SP.Data.TaxExemptRecordsListItem"},"Title":"A Test Fax","SenderFax":"8005551212","SenderState":"TN","Received":"2022-34-21 01:34:04"}
    – Thomas
    Feb 21, 2022 at 19:34
  • Usually, regardless of the error, the response will still return you with the correct error message in JSON format. Can you try call getResponseMessage() and see what's the return? docs.oracle.com/javase/8/docs/api/java/net/… By the way, HTTP error 400 can be many things. code2care.org/sharepoint/… Feb 21, 2022 at 19:47
  • The response message is just 'Bad Request'.
    – Thomas
    Feb 21, 2022 at 20:32
  • I did correct my date format to yyyy-MM-dd HH:mm:ss but I still get the bad request. It's odd that there's nothing else in the response.
    – Thomas
    Feb 21, 2022 at 20:50
  • What if you use ISO8601 format? It'd be yyyy-MM-dd'T'HH:mm:ss Feb 22, 2022 at 1:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.