Setting up GET cURL Request (PHP) - php

I'm a little confused on how to set up a cURL request to an API I'm working with. To be specific, it's for a fulfillment center called ShipStation (http://api.shipstation.com). I've done many cURL requests in the past but now I'm trying to figure out how to set up a 'MERGE' cURL request as opposed to a 'GET' cURL request, etc. You can see on here the 'GET' header to pull info from the API:
http://api.shipstation.com/Order-Resource.ashx#Reading_an_Order_5
And then to update/merge data:
http://api.shipstation.com/Order-Resource.ashx#Updating_an_Order_6
Every time I try to send a request though, I get curl_setopt(): supplied argument is not a valid cURL handle resource errors on several lines. I tried initially by copying the data and trying to send it as a header:
$header .= "GET https://data.shipstation.com/1.3/Orders(128714) HTTP/1.1";
$header .= "User-Agent: Microsoft ADO.NET Data Services";
$header .= "Accept-Charset: UTF-8";
$header .= "DataServiceVersion: 1.0;NetFx";
$header .= "MaxDataServiceVersion: 2.0;NetFx";
$header .= "Accept: application/atom+xml,application/xml";
$header .= "Host: data.shipstation.com";
//Send request
$curlConn = curl_init();
curl_setopt($curlConn,CURLOPT_USERPWD,'myusername:mypassword');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $header);
curl_setopt($curlConn,CURLOPT_RETURNTRANSFER,1);
$ret = curl_exec($curlConn);
curl_close($curlConn);
I do update the username and password to my credentials since you need that to log into this API. I basically copied the header as it was and it doesn't work. I also updated 'CURLOPT_CUSTOMREQUEST' to 'CURLOPT_HTTPHEADER' but both gave errors.
I'm not understanding where I'm going wrong and I also don't know how (if it's possible) to return more detailed error messages so I can get to the bottom of the problem with the code since I just get the supplied argument error.
Thanks for your help!
EDIT
Perhaps I'm approaching this wrong? How would I send a 'MERGE' request as evidenced in the documentation in the links above. I don't know how to take that info that they've given (the header info) and translate it into a request to the API.

Try in this way:
$end = "\r\n";
$header .= "GET https://data.shipstation.com/1.3/Orders(128714) HTTP/1.1" . $end;
$header .= "User-Agent: Microsoft ADO.NET Data Services" . $end;
$header .= "Accept-Charset: UTF-8" . $end;
$header .= "DataServiceVersion: 1.0;NetFx" . $end;
$header .= "MaxDataServiceVersion: 2.0;NetFx" . $end;
$header .= "Accept: application/atom+xml,application/xml" . $end;
$header .= "Host: data.shipstation.com" . $end;
//Send request
$curlConn = curl_init();
curl_setopt($curlConn,CURLOPT_USERPWD,'myusername:mypassword');
curl_setopt($curlConn, CURLOPT_CUSTOMREQUEST, $header);
curl_setopt($curlConn,CURLOPT_RETURNTRANSFER,1);
$ret = curl_exec($curlConn);
curl_close($curlConn);

Please try this:
$username = "YOUR API KEY";
$password = "YOUR API SECRET";
$endpoint = "https://ssapi.shipstation.com";
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTPHEADER, array ("
Content-Type: application/json"
));
create_order($ch, $endpoint);
function create_order($ch, $endpoint) {
curl_setopt($ch, CURLOPT_URL, $endpoint . "/orders/createorder");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{
\"orderNumber\": \"ABC124\",
\"orderKey\": \"0f6aec18-3e89-4771-83aa-f392d84f4c74\",
\"orderDate\": \"2015-01-31T17:46:27.0000000\",
\"paymentDate\": \"2015-01-31T17:46:27.0000000\",
\"orderStatus\": \"awaiting_shipment\",
\"customerUsername\": \"headhoncho#whitehouse.gov\",
\"customerEmail\": \"headhoncho#whitehouse.gov\",
\"billTo\": {
\"name\": \"The President\",
\"company\": \"US Govt\",
\"street1\": \"1600 Pennsylvania Ave\",
\"street2\": \"Oval Office\",
\"street3\": null,
\"city\": \"Washington\",
\"state\": \"DC\",
\"postalCode\": \"20500\",
\"country\": \"US\",
\"phone\": null,
\"residential\": true
},
\"shipTo\": {
\"name\": \"The President\",
\"company\": \"US Govt\",
\"street1\": \"1600 Pennsylvania Ave\",
\"street2\": \"Oval Office\",
\"street3\": null,
\"city\": \"Washington\",
\"state\": \"DC\",
\"postalCode\": \"20500\",
\"country\": \"US\",
\"phone\": null,
\"residential\": true
},
\"items\": [
{
\"lineItemKey\": null,
\"sku\": \"ABC123\",
\"name\": \"Test item #1\",
\"imageUrl\": null,
\"weight\": {
\"value\": 24,
\"units\": \"ounces\"
},
\"quantity\": 2,
\"unitPrice\": 99.99,
\"warehouseLocation\": \"Aisle 1, Bin 7\",
\"options\": []
},
{
\"lineItemKey\": null,
\"sku\": \"DEF456\",
\"name\": \"Test item #2\",
\"imageUrl\": null,
\"weight\": {
\"value\": 0.01,
\"units\": \"ounces\"
},
\"quantity\": 3,
\"unitPrice\": 1.25,
\"warehouseLocation\": \"Aisle 7, Bin 34\",
\"options\": []
}
],
\"amountPaid\": 218.73,
\"taxAmount\": 5,
\"shippingAmount\": 10,
\"customerNotes\": null,
\"internalNotes\": \"This order was created via the ShipStation API\",
\"gift\": false,
\"giftMessage\": null,
\"requestedShippingService\": \"Priority Mail\",
\"paymentMethod\": null,
\"carrierCode\": \"fedex\",
\"serviceCode\": \"fedex_2day\",
\"packageCode\": \"package\",
\"confirmation\": \"delivery\",
\"shipDate\": \"2014-04-08\",
\"weight\": {
\"value\": 0,
\"units\": \"ounces\"
},
\"dimensions\": {
\"units\": \"inches\",
\"length\": 7,
\"width\": 5,
\"height\": 6
},
\"insuranceOptions\": {
\"provider\": null,
\"insureShipment\": false,
\"insuredValue\": 0
},
\"internationalOptions\": {
\"contents\": null,
\"customsItems\": null
},
\"advancedOptions\": {
\"warehouseId\": 34369,
\"nonMachinable\": false,
\"saturdayDelivery\": false,
\"containsAlcohol\": false,
\"storeId\": 42756,
\"customField1\": \"Some custom data\",
\"customField2\": null,
\"customField3\": null,
\"source\": null
}
}");
$response = curl_exec($ch);
curl_close($ch);
print_r($response);
}

Related

Gemini API via PHP cURL: InvalidSignature

I converted the following Python code from the official docs(https://docs.sandbox.gemini.com/rest-api/#private-api-invocation) to PHP but I always get InvalidSignature error:
url = "https://api.gemini.com/v1/mytrades"
gemini_api_key = "mykey"
gemini_api_secret = "1234abcd".encode()
t = datetime.datetime.now()
payload_nonce = time.time()
payload = {"request": "/v1/mytrades", "nonce": payload_nonce}
encoded_payload = json.dumps(payload).encode()
b64 = base64.b64encode(encoded_payload)
signature = hmac.new(gemini_api_secret, b64, hashlib.sha384).hexdigest()
request_headers = {
'Content-Type': "text/plain",
'Content-Length': "0",
'X-GEMINI-APIKEY': gemini_api_key,
'X-GEMINI-PAYLOAD': b64,
'X-GEMINI-SIGNATURE': signature,
'Cache-Control': "no-cache"
}
response = requests.post(url, headers=request_headers)
My PHP code is this and everything looks correct:
$b64 = base64_encode(utf8_encode(json_encode([ "request" => "/v1/balances", "nonce" => time() ])));
$header = [
'Content-Type: text/plain',
'Content-Length: 0',
'X-GEMINI-APIKEY: master-XXXXXXX',
'X-GEMINI-PAYLOAD: ' . $b64,
'X-GEMINI-SIGNATURE: ' . md5(hash_hmac('sha384', utf8_encode('XXXXXXXXXX'), $b64)),
'Cache-Control: no-cache'
];
$ch = curl_init('https://api.sandbox.gemini.com/v1/balances');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
echo curl_exec($ch);
Error:
{"result":"error","reason":"InvalidSignature","message":"InvalidSignature"}
I don't have any access to the API, but could you please try the following chagnes:
Remove the MD5 function from the signature calculation. The hash_hmac function in PHP already does this by default.
'X-GEMINI-SIGNATURE: ' . hash_hmac('sha384', utf8_encode('XXXXXXXXXX'), $b64),
Switch around the payload and the key in the same line:
'X-GEMINI-SIGNATURE: ' . hash_hmac('sha384', $b64, utf8_encode('XXXXXXXXXX')),

Illegal string offset 'name', code worked with example json response

I'm currently working on a website to control my SmartBulbs at home via a webpage. To do so I use the provided API.
I tried my code with an example json response from the manufacturers website. Everything worked fine and all the lights listed in the example response where represented by divs with the names of the lights.
When I tried my code at home (called the API like in the code) I got a valid response but I also got an error which stated Illegal string offset 'label'. What am I doing wrong?
Everything worked fine when I used the example response. The response when I use the API looks the same for me. Shouldn't it also work then?
You can find everything down below. If you need some mor information just ask :)
php code
function get_lights(){
$link = "https://api.lifx.com/v1/lights/all";
$authToken = "I inserted my token here and got a valid response";
$ch = curl_init($link);
$headers = array('Authorization: Bearer ' . $authToken);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, $headers);
$response = curl_exec($ch);
$json = json_decode($response, true);
$html = null;
foreach($json as $object)
{
$html.= '<div class="element" onclick="get_info();">' . $object['label'] . '</div>';
}
return $html;
}
example response
[
{
"id": "d3b2f2d97452",
"uuid": "8fa5f072-af97-44ed-ae54-e70fd7bd9d20",
"label": "Left Lamp",
"connected": true,
"power": "on",
"color": {
"hue": 250.0,
"saturation": 0.5,
"kelvin": 3500
},
"infrared": "1.0",
"brightness": 0.5,
"group": {
"id": "1c8de82b81f445e7cfaafae49b259c71",
"name": "Lounge"
},
"location": {
"id": "1d6fe8ef0fde4c6d77b0012dc736662c",
"name": "Home"
},
"last_seen": "2015-03-02T08:53:02.867+00:00",
"seconds_since_seen": 0.002869418,
"product": {
"name": "LIFX+ A19",
"company": "LIFX",
"identifier": "lifx_plus_a19",
"capabilities": {
"has_color": true,
"has_variable_color_temp": true,
"has_ir": true,
"has_multizone": false
}
}
}
]
my API response
[
{
"id":"d073d513bfd6",
"uuid":"02ea5835-9dc2-4323-84f3-3b825419008d",
"label":"MainLight",
"connected":true,
"power":"on",
"color":{
"hue":27.581597619592586,
"saturation":0.0,
"kelvin":2500
},
"zones":null,
"brightness":0.49999237048905165,
"group":{
"id":"d5aa0e1180293e0af56607cbe47f4940",
"name":"MyRoom"
},
"location":{
"id":"451e4b376a38062cdd10c54ab2698975",
"name":"My Home"
},
"product":{
"name":"Color 1000",
"identifier":"lifx_color_a19",
"company":"LIFX",
"capabilities":{
"has_color":true,
"has_variable_color_temp":true,
"has_ir":false,
"has_multizone":false
}
},
"infrared":null,
"last_seen":"2017-02-18T21:40:58.164+00:00",
"seconds_since_seen":0.001675218
}
]
You're setting the wrong option for your cURL handle:
$ch = curl_init($link);
$headers = array('Authorization: Bearer ' . $authToken);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);

Create new user using the Freshdesk API in PHP

This is my code:
$contact_data = json_encode(array(
"name" => "Jimmy Jimmy",
"email" => "jimmy#example.com",
"phone" => "555-555-555",
"mobile" => "312-312-213"
));
$url = $domain."api/v2/contacts";
$ch = curl_init($url);
$header[] = "Content-type: application/json";
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_USERPWD, "$apiKey");
curl_setopt($ch, CURLOPT_POSTFIELDS, $contact_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
$info = curl_getinfo($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($server_output, 0, $header_size);
$response = substr($server_output, $header_size);
if($info['http_code'] == 201) {
echo "Contact created successfully, the response is given below \n";
echo "Response Headers are \n";
echo $headers."\n";
echo "Response Body \n";
echo "$response \n";
} else {
if($info['http_code'] == 404) {
echo "Error, Please check the end point \n";
} else {
echo "Error, HTTP Status Code : " . $info['http_code'] . "\n";
echo "Headers are ".$headers."\n";
echo "Response is ".$response;
}
}
curl_close($ch);
When I executed this piece of code , I received this errors message:
Response is {"description":"Validation failed","errors":[{"field":"last_name","message":"It should be a/an String","code":"missing_field"},{"field":"life_cycle_status","message":"It should be a/an String","code":"missing_field"}]}
The documentation nothing mentioned about these fields : last_name & life_cycle_status to create a new contact in freshdesk. Any idea what am i doing wrong ? thx
[UPDATE]
$contact_data = json_encode(array(
"name" => "Jimmy Jimmy",
"email" => "jimmy#example.com",
"phone" => "555-555-555",
"mobile" => "312-312-213"
"life_cycle_status" => "asdasdsa",
"last_name" =>"dasdasdad"
));
With these new items, I got this message error:
Response is {"description":"Validation failed","errors":[{"field":"life_cycle_status","message":"Unexpected/invalid field in request","code":"invalid_field"},{"field":"last_name","message":"Unexpected/invalid field in request","code":"invalid_field"}]}
These fields are not default for the Freshdesk Contact entity but are, probably, defined as required in the backend (Check Admin > Customer fields in the backend of Freshdesk)
This means we have to define them as custom_fields as indicated in the Freshdesk API documentation here.
This means your POST array would look something like this
$contact_data = json_encode(array(
'name' => 'Jimmy Jimmy',
'email' => 'jimmy#example.com',
'custom_fields' => [
// put all your custom fields here
'last_name' => 'Jimmy',
'life_cycle_status' => 'value'
]
));
Well you already have the answer - you did read that error message yes?
Response:
{
"description": "Validation failed",
"errors":[
{
"field":"last_name",
"message":"It should be a/an String",
"code":"missing_field"
},
{
"field":"life_cycle_status",
"message":"It should be a/an String",
"code":"missing_field"
}
]
}
Meaning:
last_name and life_cycle_status both need to be a String and cannot be empty.

OAuth2 integration with ExactOnline

I am trying to integrate our app with Exact Online website using OAuth2,or more specifically i am trying to create hour registration which should include "Employee","Project","Hours","Hours type".
function registerTime($access_token_for_data) {
//$dataToFilterAccounts = array('$filter' => 'IsSales eq true');
$dataToRetrieveFromEmployees = array('$select' => 'ID');
// $queryToFilterAccounts = http_build_query($dataToFilterAccounts);
$queryToRetrieveFromEmployees = http_build_query($dataToRetrieveFromEmployees);
// $dataToFilterItems = array('$filter' =>'IsSalesItem eq true');
$dataToRetrieveProjects = array('$select' => 'ID');
//$queryToFilterItems = http_build_query($dataToFilterItems);
$queryToRetrieveProjects = http_build_query($dataToRetrieveProjects);
$urlProjects = 'https://start.exactonline.nl/api/v1/638842/project/Projects';
$urlEmployees = 'https://start.exactonline.nl/api/v1/638842/payroll/Employees';
$curlProjects = curl_init($urlProjects);
$curlEmployees = curl_init($urlEmployees);
$headers = array(
'Authorization: Bearer ' . $access_token_for_data,
'Accept: application/json',
'Content-type: application/json'
);
curl_setopt($curlProjects, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curlProjects, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curlProjects, CURLOPT_URL, $urlProjects . '?' . $queryToRetrieveProjects);
curl_setopt($curlProjects, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($curlEmployees, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curlEmployees, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curlEmployees, CURLOPT_URL, $urlEmployees . '?' . $queryToRetrieveFromEmployees);
curl_setopt($curlEmployees, CURLOPT_CUSTOMREQUEST, 'GET');
$resultProjects = curl_exec($curlProjects);
$resultEmployees = curl_exec($curlEmployees);
$projectsData = json_decode($resultProjects, true);
$projectID = $projectsData["d"]["results"]["0"]["ID"];
$employeesData = json_decode($resultEmployees, true);
$employeeID = $employeesData["d"]["results"]["0"]["ID"];
curl_close($curlProjects);
curl_close($curlEmployees);
$urlTimeTransaction = 'https://start.exactonline.nl/api/v1/638842/project/TimeTransactions';
$curlTimeTransacation = curl_init($urlTimeTransaction);
$content = json_encode(array("Project" => $projectID, "Employee" => $employeeI));
curl_setopt($curlTimeTransacation, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curlTimeTransacation, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curlTimeTransacation, CURLOPT_POST, true);
curl_setopt($curlTimeTransacation, CURLOPT_POSTFIELDS, $content);
$createdTimeTransaction = curl_exec($curlTimeTransacation);
$status = curl_getinfo($curlTimeTransacation, CURLINFO_HTTP_CODE);
if ($status != 201) {
die("Error: call to URL $curlTimeTransacation failed with status $status, response $createdTimeTransaction, curl_error " . curl_error($curlTimeTransacation) . ", curl_errno " . curl_errno($curlTimeTransacation));
}
echo "HTTP status $status creating time registartion<br/><br/>";
curl_close($curlTimeTransacation);
}
And this is the error i get
Error: call to URL Resource id #56 failed with status 500, response { "error": { "code": "", "message": { "lang": "", "value": "Mandatory: Employee\r\nMandatory: Hours\r\nMandatory: Hour type" } } }, curl_error , curl_errno 0
But when i try to include any of these mandatroy fileds i get:
Error: call to URL Resource id #56 failed with status 400, response { "error": { "code": "", "message": { "lang": "", "value": "Error processing request stream. The property name 'Hours' specified for type 'Exact.Web.Api.Models.TimeTransaction' is not valid." } } }, curl_error , curl_errno 0
please note that /api/v1/638842 contains your division ID. You might want to change that into a variable.
Regarding your problem: please note that the error messages contain text to be consumed by humans. The actual technical names can be different. I always do it the other way around: I query the existing data and look at all fields, and then I know what to send. You can use the Query Tool for Exact Online in the app center of Exact to do the query on REST api of Exact Online (but I am biased because involved).
As Guido pointed out correctly, there is no field named Hours in the TimeTransaction on projects, there is a field named Hours on the manufacturing TimeTransaction. This is a little confusing, especially since the error message isn't very clear.
You need to set Quantity on TimeTransactions in order to specify the hours on a project's time transaction.

send docx files using curl php

i am using the rest api for docusign.
i am sending a document to another user for online signing. What is happening in the code is that the document is being uploaded and the contents of the file is being read using the file_get_contents function and then using curl this content is sent to the other user through docusign.
Here is my code:
$data = "{
\"emailBlurb\":\"\",
\"emailSubject\":\"DocuSign API - Please Sign This Document...\",
\"documents\":[
{
\"documentId\":\"1\",
\"name\":\"agreement.pdf\"
}
],
\"recipients\":{
\"signers\":[
{
\"email\":\"$email\",
\"name\":\"$name\",
\"recipientId\":\"1\",
\"tabs\":{
\"signHereTabs\":[
{
\"xPosition\":\"100\",
\"yPosition\":\"100\",
\"documentId\":\"1\",
\"pageNumber\":\"1\"
}
]
}
}
]
},
\"status\":\"sent\"
}";
$file_contents = file_get_contents("uploads/envelopes/" . $file_name);
$requestBody = "\r\n"
."\r\n"
."--myboundary\r\n"
."Content-Type: application/json\r\n"
."Content-Disposition: form-data\r\n"
."\r\n"
."$data\r\n"
."--myboundary\r\n"
."Content-Type:application/pdf\r\n"
."Content-Disposition: file; filename=\”document.pdf\"; documentid=1 \r\n"
."\r\n"
."$file_contents\r\n"
."--myboundary--\r\n"
."\r\n";
// *** append "/envelopes" to baseUrl and as signature request endpoint
$curl = curl_init($baseUrl . "/envelopes" );
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type: multipart/form-data;boundary=myboundary',
'Content-Length: ' . strlen($requestBody),
"X-DocuSign-Authentication: $header" )
);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ( $status != 201 ) {
$msg = 'Error. Please try again';
}
The above code is working fine for pdf files but not for docx files.
For docx files, i have changed the code like this (changed the content type):
$requestBody = "\r\n"
."\r\n"
."--myboundary\r\n"
."Content-Type: application/json\r\n"
."Content-Disposition: form-data\r\n"
."\r\n"
."$data\r\n"
."--myboundary\r\n"
."Content-Type:application/vnd.openxmlformats-officedocument.wordprocessingml.document\r\n"
."Content-Disposition: file; filename=\”document.docx\"; documentid=1 \r\n"
."\r\n"
."$file_contents\r\n"
."--myboundary--\r\n"
."\r\n";
Thanks
DocuSign does support sending .docx files, so file format is not causing your issue. Are you receiving a specific error message when you attempt to send a .docx file? If so, then what's the error?
FWIW, I'm able to send a .docx file via the DocuSign REST API -- I've included my full request below. If possible, I'd suggest that you use Fiddler (or any similar utility) to produce a trace of the full request that you're sending to the server, and compare its contents/structure with the (successful) example request that I've included below. Doing so would hopefully allow you to identify (and resolve) the problem with your request.
POST https://demo.docusign.net/restapi/v2/accounts/ACCOUNT_NUMBER/envelopes HTTP/1.1
X-DocuSign-Authentication: {"Username":"USERNAME","Password":"PASSWORD","IntegratorKey":"INTEGRATOR_KEY"}
Content-Type: multipart/form-data; boundary=MY_BOUNDARY
Accept: application/json
Host: demo.docusign.net
Content-Length: 15384
--MY_BOUNDARY
Content-Type: application/json
Content-Disposition: form-data
{
"status" : "sent",
"emailBlurb":"Test Email Body",
"emailSubject": "-- Test Email Subject --",
"documents": [
{
"name": "CustomerAgreement.docx",
"documentId": 1
}],
"recipients": {
"signers" : [{
"email": "bobsemail#outlook.com",
"name": "Bob Adamson",
"recipientId": "1",
"routingOrder": "1",
"tabs": {
"signHereTabs": [
{
"recipientId": "1",
"tabLabel": "Customer_Signature",
"documentId": "1",
"pageNumber": "1",
"xPosition": "99",
"yPosition": "424"
}]
}
}]
}
}
--MY_BOUNDARY
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
Content-Disposition: file; filename="CustomerAgreement.docx"; documentid="1"
<document bytes removed>
--MY_BOUNDARY--

Categories