Post

2 followers Follow
1
Avatar

File upload and attach to Request via REST API

If my understanding is correct according to the REST API documentation:

1) Perform GET on V2.0/services/files/getUploadUrl/
2) Use response 'uploadUrl' from #1 above and perform POST of file to this uploadUrl
3) Perform POST on V2.0/services/files/upload/ with documentId(entityId) and fileInformation parameters to attach the file to the request

Steps #1 and #2 complete successfully (although I'm not able to find the document in Clarizen after step #2 completes). It is on step #3 that I receive the following error (I'm working in the Clarizen training box):

{ "errorCode": "Internal", "message": "An internal error has occurred, the error was logged and will be examined.", "referenceId": "2qjTwbsOuP6x9qPEpM2rCg" }

Code for step #3 (authentication header is added via CustomAuthenticator):
request = new RestRequest("V2.0/services/files/upload/", Method.POST);
request.AddHeader("Content-type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddHeader("Accept-Encoding", "gzip");
request.RequestFormat = DataFormat.Json;
request.AddParameter("documentId", "/EnhancementRequest/5bzijon2unjqiuxngci7kj3by7186");
request.AddParameter("fileInformation", "{filename:" + FileUpload2.FileName + "}");
request.AddParameter("uploadUrl", uploadUrl.uploadUrl);

            response = _client.Execute(request);

Any assistance would be very appreciated. Thanks.

Erwin Hernandez Answered

Please sign in to leave a comment.

7 comments

3
Avatar

Seems like the documentation is missing some key concepts of how Documents and Files works in the API and there is some confusion related to their API names vs their names in the UI.
Let me try to explain:
Let's assume you have a Request object in Clarizen to which you would like to attach a File. A file "content" in Clarizen can have different storage backends: Google Doc, Box or an uploaded file. Let's map those UI names to API names:
- Request in the UI is called EnhancementRequest in the API
- File in the UI is called Document in the API
- Attached file in the UI is called "AttachmentLink" in the API
- File Content (Or uploaded file) in the UI is called File in the API
(Sorry about this confusion but that happens when we're changing entity names in the UI to make them easier to understand but need to maintain API compatibility)

So now you should follow these steps in order to attach a file to a request:
- Assuming you have a Request with ID "5bzijon2unjqiuxngci7kj3by7186"
- Create a Document object via the API (let's assume this document ID is "abc123"
- Create an AttachmentLink between the Request and the new Document (5bzijon2unjqiuxngci7kj3by7186 to abc123)
- Now that you have a document, you want to populate it with content. This is where the 3 steps you mentioned above kick in. You will need to perform them again but make sure to change the documentId parameter to use the Document you just created and not the Request

Hope this is clearer now.

The next issue there is with your request is that we are not able to parse it because it is not in JSON format.
According to our logs it is sent using urlencoded form format.

Eyal Post 3 votes
Comment actions Permalink
0
Avatar

Thanks for your detailed explanation. This helps a great deal. What are the parameters for the AttachmentLink entity PUT? I know I have to pass in {documentId,requestId} but I just need to know what the parameter name should be. I couldn't find this in the documentation.

Also, in this scenario, how should the fileInformation parameter be formatted for the POST to /V2.0/services/files/upload? The documentation only specifies the property names but not what each should refer to or which ones are required. Thanks again for your help.

storage storage <-- What values for each of the storage properties (Server, Url, Link)
url string <-- Is this the same as the uploadUrl obtained in the previous GET request?
fileName string <-- I think we can make a safe assumption here?
subType string <-- ??
extendedInfo string <-- ??

Erwin Hernandez 0 votes
Comment actions Permalink
1
Avatar
  • The field names for AttachmentLink are "Document" and "Entity"
  • The JSON should look something like this: { documentId : doc.id, fileInformation: { storage : "Server", fileName : "test.txt" }, uploadUrl : ".." }
Eyal Post 1 vote
Comment actions Permalink
0
Avatar

By the way, can you send me the link to the 3 steps upload procedure you described below so I can open a request to update it?

Eyal Post 0 votes
Comment actions Permalink
0
Avatar

Thanks so much for this information. I have gathered the documentation and put the pieces together from several places including:
- https://api.clarizen.com/V2.0/services/files/GetUploadUrl
- https://api.clarizen.com/V2.0/services/files/Upload
- https://api.clarizen.com/V2.0/services/types/FileInformation
- https://success.clarizen.com/hc/communities/public/questions/203993198-Clarizen-Web-Services-API-Guide-V1-0 (under section named: "The following example shows how to upload a new document to Clarizen")

Everything works perfectly using your instructions in curl. Working through C#/RestSharp I have all steps working with the sole exception of updating the document content with the contents of the file. I am getting an error ref id: 2nan0ViTuD3iwTDst0h2S3 (training box). Can you please let me know what this is referring to so I can narrow it down? I'm trying to determine if the error is being caused by the fileInformation parameter. I have tried several different ways of passing this parameter with the same result.

Here is the method:

public bool UpdateDocumentContent(string docID, string uploadUrl)
{
var obj = new UpdateDocContentFileInformation("Server",FileUpload2.FileName);
var json = JsonConvert.SerializeObject(obj);

        var successful = false;
        var request = new RestRequest("V2.0/services/files/upload", Method.POST);
        request.RequestFormat = DataFormat.Json;
        request.AddHeader("Content-type", "application/json");
        request.AddHeader("Accept", "application/json");
        request.AddParameter("documentId", docID);
        request.AddParameter("uploadUrl", uploadUrl);
        request.AddParameter("fileInformation",json,ParameterType.RequestBody);

        var response = _client.Execute(request);

        if (response.StatusCode == HttpStatusCode.OK) successful = true;
        return successful;
    }

Class:
public class UpdateDocContentFileInformation
{
public string storage { get; set; }
public string fileName { get; set; }

    public UpdateDocContentFileInformation(string Storage, string FileName)
    {
        storage = Storage;
        fileName = FileName;
    }

This is the result string after the obj is JsonSerialized:
{\"storage\":\"Server\",\"fileName\":\"Test_Word89.docx\"}

Thanks again for all your help. We're almost there!

Erwin Hernandez 0 votes
Comment actions Permalink
1
Avatar

The entire request body needs to be in JSON format. The way to currently send it, only the fileInformation is in JSON

Eyal Post 1 vote
Comment actions Permalink
0
Avatar

That worked! Thank you! For others who may find this helpful:

public bool UpdateDocumentContent(string docID, string uploadURL)
{
var obj = new UpdateDocContentFileInformation("Server",FileUpload2.FileName);

        var successful = false;
        var request = new RestRequest("V2.0/services/files/upload", Method.POST);
        request.RequestFormat = DataFormat.Json;
        request.AddHeader("Content-type", "application/json");
        request.AddHeader("Accept", "application/json");
        request.AddJsonBody(new
        {
            documentId = docID,
            uploadUrl = uploadURL,
            fileInformation = obj
        });

        var response = _client.Execute(request);

        if (response.StatusCode == HttpStatusCode.OK) successful = true;
        return successful;
    }
Erwin Hernandez 0 votes
Comment actions Permalink