I have attempted to post a document in VBA by mimicking the syntax in the six programming languages listed in docusign documentation but no luck. I can successfully GET login information but using this information to POST a document proves fatal: here is the error I receive:
INVALID_MULTI_PART_REQUEST An error was found while parsing the multipart request. Boundary terminator '--BOUNDARY--' was not found in the request.
Any assistance would be appreciated. Here is the code I have so far:
Private Sub APILoginCallTest()
' Step 1 - get initial login information
' defined request and result variables
Set httpRequest = New XMLHTTP60
Set httpResult = New DOMDocument60
' clear out login information response fields
With ThisWorkbook.Sheets("Dashboard")
.Range("rngResponseLoginStatus").Value = vbNullString
.Range("rngResponseLoginFull").Value = vbNullString
End With
'open login information url
httpRequest.Open "GET", "https://demo.docusign.net/restapi/v2/login_information", False
' set headers (listed below)
With ThisWorkbook.Sheets("Dashboard")
For h = 1 To 3
httpRequest.setRequestHeader .Range("rngAPIHeaderLI0" & CStr(h)).Offset(0, -1).Value, _
.Range("rngAPIHeaderLI0" & CStr(h)).Value
Next h
End With
' currently headers are defined as follows (there are three) filling in the method above :
' X-DocuSign-Authentication : <DocuSignCredentials>
' <Username>[username]</Username>
' <Password>[password]</Password>
' <IntegratorKey>[ikey]</IntegratorKey>
' </DocuSignCredentials>
' Accept : application/xml
' Content-Type : application/xml
' send login information request
httpRequest.send
' record response in Dashboard worksheet for later review
With ThisWorkbook.Sheets("Dashboard")
.Range("rngResponseLoginStatus").Value = httpRequest.Status & "-" & httpRequest.statusText
.Range("rngResponseLoginFull").Value = httpRequest.responseText
End With
' display response in immediate window
Debug.Print "Login Status and Text=" & httpRequest.Status, httpRequest.statusText
Debug.Print "Login Response=" & httpRequest.responseText
' Step 2 signature request
' clear out sig request responses
With ThisWorkbook.Sheets("Dashboard")
.Range("rngResponseSigRequestStatus").Value = vbNullString
.Range("rngResponseSigRequestFull").Value = vbNullString
End With
' define the new URL for the signature request using the Base URL returned aboved appended with '/envelopes'
Dim sigURL As String
sigURL = ThisWorkbook.Sheets("Dashboard").Range("rngResponseLoginBaseUrl").Value & "/envelopes"
' currently sig URL is 'https://demo.docusign.net/restapi/v2/accounts/[account number]'
Dim sigBody As String
' start the body of the request
sigBody = "<envelopeDefinition xmlns=\" & Chr(34) & "http://www.docusign.com/restapi\" & Chr(34) & ">"
' add email info to the body
sigBody = sigBody & "<emailSubject>API Call for adding signature request to document and sending</emailSubject>" & _
"<status>sent</status>"
' add documents to the body
sigBody = sigBody & "<documents>" & _
"<document>" & _
"<documentId>1</documentId>" & _
"<name>" & ThisWorkbook.Sheets("Dashboard").Range("rngDocumentName").Value & "</name>" & _
"</document>" & _
"</documents>"
' add email recipients
sigBody = sigBody & "<recipients>" & _
"<signers>" & _
"<signer>" & _
"<recipientId>1</recipientId>" & _
"<name>" & ThisWorkbook.Sheets("Dashboard").Range("rngRecipientName").Value & "</name>" & _
"<email>" & ThisWorkbook.Sheets("Dashboard").Range("rngRecipientEmail").Value & "</email>" & _
"<tabs>" & _
"<signHereTabs>" & _
"<signHere>" & _
"<xPosition>100</xPosition>" & _
"<yPosition>100</yPosition>" & _
"<documentId>1</documentId>" & _
"<pageNumber>1</pageNumber>" & _
"</signHere>" & _
"</signHereTabs>" & _
"</tabs>" & _
"</signer>" & _
"</signers>" & _
"</recipients>"
' close the envelope definition
sigBody = sigBody & "</envelopeDefinition>"
' read in document in byte array
Dim intFileNum%, bytTemp As Byte, intCellRow%
Dim bytTempAll As String
intFileNum = FreeFile
intCellRow = 0
Open (ThisWorkbook.Path & "\" & ThisWorkbook.Sheets("Dashboard").Range("rngDocumentName").Value) For Binary Access Read As intFileNum
Do While Not EOF(intFileNum)
' intCellRow = intCellRow + 1
Get intFileNum, , bytTemp
'Cells(intCellRow, 1) = bytTemp
bytTempAll = bytTempAll & bytTemp
Loop
Close intFileNum
Dim lenFile As Long
lenFile = Len(bytTempAll) ' just curious
Set AdobeStream = CreateObject("ADODB.STREAM")
With AdobeStream
.Type = 1 ' binary
.Open ' open the file
.LoadFromFile (ThisWorkbook.Path & "\" & ThisWorkbook.Sheets("Dashboard").Range("rngDocumentName").Value)
End With
' create multipart/form-data request into a 'Pre' and a 'Post' with the document bytes eventually going in between
Dim requestBodyPre As String
requestBodyPre = "\r\n\r\n--BOUNDARY\r\n" & _
"Content-Type: multipart/form-data, boundary =BOUNDARY" & vbCrLf & _
"Content-Length: " & lenFile & "\r\n" & _
sigBody & _
"\r\n\r\n--BOUNDARY\r\n" & _
"Content-Type: " & ThisWorkbook.Sheets("Dashboard").Range("rngContentType").Value & "\r\n" & _
"Content-Disposition: file; filename:\" & Chr(34) & ThisWorkbook.Sheets("Dashboard").Range("rngDocumentName").Value & Chr(34) & "\; " & _
"documentid=1\r\n\r\n"
' break up the requestBody into 'Pre' and 'Post' because document bytes need to be passed in the middle
Dim requestBodyPost As String
requestBodyPost = "\r\n" & "--BOUNDARY--\r\n\r\n"
' reset response variables for use in signature response
Set httpRequest = Nothing
Set httpResult = Nothing
Set httpRequest = New XMLHTTP60
Set httpResult = New DOMDocument60
' open url for signature POST
Debug.Print "POST to url " & sigURL
httpRequest.Open "POST", sigURL, False
' attach headers
For h = 1 To 3
httpRequest.setRequestHeader ThisWorkbook.Sheets("Dashboard").Range("rngAPIHeaderSR0" & CStr(h)).Offset(0, -1).Value, _
ThisWorkbook.Sheets("Dashboard").Range("rngAPIHeaderSR0" & CStr(h)).Value
Next h
' currently headers are defined as follows (there are three) filling in the method above :
' X-DocuSign-Authentication : <DocuSignCredentials>
' <Username>[username]</Username>
' <Password>[password]</Password>
' <IntegratorKey>[ikey]</IntegratorKey>
' </DocuSignCredentials>
' Accept : application/xml
' Content-Type multipart/form-data; boundary=BOUNDARY
' send request
Dim streamAll As String
'streamAll = StrConv(requestBodyPre, vbUnicode) & StrConv(requestBodyPost, vbUnicode)
'streamAll = AdobeStream.readtext
'
Debug.Print "sending " & requestBodyPre
Debug.Print "sending " & requestBodyPost
' post request
httpRequest.send requestBodyPre & AdobeStream.read & requestBodyPost
' record sig request response in worksheet
With ThisWorkbook.Sheets("Dashboard")
.Range("rngResponseSigRequestStatus").Value = httpRequest.Status & "-" & httpRequest.statusText
.Range("rngResponseSigRequestFull").Value = httpRequest.responseText
End With
Set httpRequest = Nothing
Set httpResult = Nothing
Set AdobeStream = Nothing
MsgBox "Done!"
End Sub
vbCrLf. The CRLF sequence for HTTP is ASCII 13 10 whichvbCrLfis a shorthand for. Using "\r\n" will almost certainly generate ASCII 92 114 92 110 because it will be interpreted as text rather than an escape sequence. You might try sending some experimental POST requests to http://httpbin.org/post as that will display what was actually received in the request