Can't use "Create Attachment POST" API: failing to read body. I get "file must be included" error
Asked by SiDawg:

According to the [API documentation](https://developer.atlassian.com/cloud/confluence/rest/v1/api-group-content---attachments/#api-wiki-rest-api-content-id-child-attachment-post) all I need to supply is a value for "minorEdit" and "file" with a filepath, but even if I provide no body at all I get the same error "**...BadRequestException: At least one attachment file must be included** ". I wondered if maybe it needs the ACTUAL file not just the path so I tried including content type and base64 encoded text of my image. Also wondered why the documentation says "relative file path"... relative to what? But I'm thinking it's failing before that point altogether: I don't think I'm constructing the body content correctly: does this LOOK correct?  

--IMabOUnDArY  
Content-Disposition: form-data; name="minorEdit"  
"true"  
--IMabOUnDArY  
Content-Disposition: form-data; name="file"  
"C:\\Users\\me\\ParsedHTML\\Input\\Files\\DiagramSMK-191453.jpg"  
--IMabOUnDArY--

Or I found this post [Solved: Uploading attachment into Confluence (atlassian.com)](https://community.atlassian.com/t5/Answers-Developer-Questions/Uploading-attachment-into-Confluence/qaq-p/473851) which seems to include the actual file content in the post (although it doesn't mention that on the API documentation, that seems more logical?) but that doesn't work either? Should I try different characters for carriage return new line perhaps?


Answers:
author: SiDawg
body: OK got it working in the end.  

Top tips:

* Use Postman so you can work out how its mean to work and inspect the HTTP code :D
* I think they should document this but I guess it's common knowledge: you need to embed the full file data, not just the path... which makes sense. So you should have:  

  ```
  ------IMabOUnDdfdfAaAAAA
  Content-Disposition: form-data; name="file" ; filename="hmmmm.jpg"
  Content-Type: image/jpg

  Pz8/Pz9BAUFBAD8/YD8/Xn4/fj8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz80204/Pz8/Pz...[etc]
  ```

* Note you also need the "filename" parameter (also not documented)
* The hard part is encoding: after you get the API to work, I struggled with this with VBA. Basically the answer is "use ADODB stream to create both the text and binary parts and join them together"
* Make sure you have TWO CR/LF characters in key places: after the "content-type" and after the second "content-disposition" line (the one with the minorEdit directive). I placed that at the end but i don't think the order matters.
* If you're getting "stream ended unexpected" errors or "header is too large" or "needs at least one file" error like above, it will likely be either the CRLF thing or like me you missed a "--" from a boundary on one line
* Dont worry about the content length header that Postman adds: works without it (maybe a good reason to use it some times?)

Was using VBA (one off migration task) hence the need for manually constructing the body (using MSXML2.XMLHTTP60). This is why postman is nice: it's a lot easier to use these days I found too. Just setup auth = "API Key" and put Key = "Authorization" and Value = "Basic \[and your base64 encoded username:api-key you got from your Atlassian profile\]". Click the little \</\> icon on the right to view the code snippets: select the "HTTP" one to kinda see the raw info that you can mimic for VBA. Took me 10 minutes to get working in postman and a full day to get working in VBA lol. Hope this helps someone!


Tags: api

cloud

confluence-cloud