Hubspot Bulk Import CRM Data API question - hubspot

I've been using the hubspot documentation to attempt a batch upload contacts that have a first name, age, phone number, city, and site url with hubspots CRM API. I've tried with both a csv file, and an xlsx file with five rows of test data (I'd changed fileFormat to CSV and SPREADSHEET when testing them both). I have the file sitting in the same directory as my python program that calls it, so I know pathing is not an issue.
Here's my python code:
import requests
import json
post_url = 'http://api.hubapi.com/crm/v3/imports?hapikey=c76....901'
latest_file = "thisIsTestData.csv"
headers = {'accept': 'application/json'}
data = {
"name": "import_contacts",
"files": [
{
"fileName": latest_file,
"fileFormat": "CSV",
"fileImportPage": {
"hasHeader": True,
"columnMappings": [
{
"ignored": False,
"columnName": "FirstName",
"idColumnType": None,
"propertName": "firstname",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": False,
"columnName": "Web Site URL",
"idColumnType": None,
"propertyName": "website",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": False,
"columnName": "Ad_Age",
"idColumnType": None,
"propertyName": "ad_age",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": False,
"columnName": "City",
"idColumnType": None,
"propertyName": "city",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": False,
"columnName": "Mobile Phone Number",
"idColumnType": None,
"propertyName": "mobilephone",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
]
}
}
]
}
r = requests.post(url=post_url, data=data, headers=headers)
print(r.status_code)
print(r.text)
I've added a status_code print at the bottom, and receive a 415 response. I checked hubspot, and none of the test values have been uploaded so I know something is definitely not working. The file is in the correct location, I've used the account settings to verify that the column mappings are correctly named and match the existing column names in the csv and xlsx, the api key is correct, and I've got the request set to POST. Unfortunately the hubspot docs do not have an example of a working post example, so I can't use anything existing to troubleshoot my issues. I'm not sure at this point what it is I'm missing, and any help or guidance would be appreciated.

It took all week of grinding away and talking with their internal support about what was missing from their documentation, but I finally got it working.
The header should not have been {'accept': 'application/json'} like in most of their other documentation. Instead it required {"importRequest": datastring} followed by a jsonified string of the data object. A files object also had to be created, and allowed to read the absolute path to the file in binary. In the final post request line, it used the crafted url with api key, the jsonified data string, and finally the binary reading of the csv file.
Any column value in the csv that you did not want transferred over, had to be marked with "ignored":True, instead of omitted from the data configuration. The data had to be listed in the same order they appear in the csv file as well.
Here's my updated code that reflects a lot of the changes that were needed.
import os
import requests
import json
url = "http://api.hubapi.com/crm/v3/imports?hapikey={insert HAPI KEY HERE}"
full_path = os.path.abspath("TestData.csv")
data = {
"name": "test_import",
"files": [
{
"fileName": "TestData.csv",
"fileFormat": "CSV",
"fileImportPage": {
"hasHeader": True,
"columnMappings": [
{
"ignored": False,
"columnName": "Web Site URL",
"idColumnType": None,
"propertyName": "website",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": False,
"columnName": "FirstName",
"idColumnType": None,
"propertyName": "firstname",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifierColumn": False
},
{
"ignored": False,
"columnName": "Ad_Age",
"idColumnType": None,
"propertyName": "ad_age",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": False,
"columnName": "Mobile Phone Number",
"idColumnType": None,
"propertyName": "mobilephone",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": False,
"columnName": "City",
"idColumnType": None,
"propertyName": "city",
"foreignKeyType": None,
"columnObjectType": "CONTACT",
"associationIdentifiedColumn": False
},
{
"ignored": True,
"columnName": "Create Date"
},
{
"ignored": True,
"columnName": "Stock Photo"
}
]
}
}
]}
datastring = json.dumps(data)
payload = {"importRequest": datastring}
files = [
('files', open(full_path, 'rb'))
]
response = requests.request("POST", url, data=payload, files=files)
#Output checking
print(response.text.encode('utf8'))
print(response.status_code)

Related

Amplify Cognito Google invalid email address format

I would like to identify users by email in a project using AWS Amplify + Google federation.
I was getting good results with usernames until I tried to switch to emails. The error shows up as error_description in the callback URL as follows
https://domain.tld/?error_description=Invalid+email+address+format.+&state=some-state&error=invalid_request
What should go in cli-inputs.json / Cognito configuration to support email based identification?
I don't know about the Google federation, but I think you must be using 'email' from the start (amplify add auth). You can't switch to email after the fact, you'd need to make a new pool and migrate users into it.
I use 'email' for the username. Here's my cli-inputs.json, hope it helps.
{
"version": "1",
"cognitoConfig": {
"identityPoolName": "xxxxxa96d_identitypool_0821234d",
"allowUnauthenticatedIdentities": false,
"resourceNameTruncated": "xxxxx0821234",
"userPoolName": "xxxxxa96d_userpool_081234d",
"autoVerifiedAttributes": [
"email"
],
"mfaConfiguration": "OFF",
"mfaTypes": [
"SMS Text Message"
],
"smsAuthenticationMessage": "Your authentication code is {####}",
"smsVerificationMessage": "Your verification code is {####}",
"emailVerificationSubject": "Your verification code",
"emailVerificationMessage": "Your verification code is {####}",
"defaultPasswordPolicy": false,
"passwordPolicyMinLength": 8,
"passwordPolicyCharacters": [],
"requiredAttributes": [
"email"
],
"aliasAttributes": [],
"userpoolClientGenerateSecret": false,
"userpoolClientRefreshTokenValidity": 30,
"userpoolClientWriteAttributes": [
"email"
],
"userpoolClientReadAttributes": [
"email"
],
"userpoolClientLambdaRole": "xxxx_userpoolclient_lambda_role",
"userpoolClientSetAttributes": false,
"sharedId": "081234d",
"resourceName": "xxxx0821234d",
"authSelections": "identityPoolAndUserPool",
"useDefault": "manual",
"usernameAttributes": [
"email"
],
"userPoolGroupList": [],
"serviceName": "Cognito",
"usernameCaseSensitive": false,
"useEnabledMfas": true,
"authRoleArn": {
"Fn::GetAtt": [
"AuthRole",
"Arn"
]
},
"unauthRoleArn": {
"Fn::GetAtt": [
"UnauthRole",
"Arn"
]
},
"breakCircularDependency": true,
"dependsOn": [],
"thirdPartyAuth": false,
"userPoolGroups": false,
"adminQueries": false,
"triggers": {},
"hostedUI": false,
"authProviders": [],
"parentStack": {
"Ref": "AWS::StackId"
},
"permissions": []
}
}

Selenium Cookies

Ive copied all the cookies for a website after I logged in (has 2fa verification if it matters) and sent them with selenium, the problem is that after approximately 1 hour the cookies seems to not work anymore as I get asked for 2FA.
Cookies being sent look like this:
{
"expirationDate": 1651051461,
"hostOnly": false,
"httpOnly": false,
"name": "s_dslv_s",
"path": "/",
"secure": false,
"session": false,
"storeId": null,
"value": "Less%20than%201%20day"
},
{
"expirationDate": 2083049656,
"hostOnly": false,
"httpOnly": false,
"name": "s_nr",
"path": "/",
"secure": false,
"session": false,
"storeId": null,
"value": "1651049656703-Repeat"
},
{
"expirationDate": 1745657661,
"hostOnly": false,
"httpOnly": false,
"name": "s_dslv",
"path": "/",
"secure": false,
"session": false,
"storeId": null,
"value": "1651049661026"
},
{
"hostOnly": false,
"httpOnly": false,
"name": "s_ppv",
"path": "/",
"secure": false,
"session": true,
"storeId": null,
"value": "Open%2520VET%2520Page%2520-%2520Render%2C83%2C83%2C1297%2C1%2C1"
},
Altho cookies being sent are incomplete as I get an error if I send these 2 cookies
"sameSite": null,
"domain": ".somewebsite.work",
My question is. Could this expiry problem be caused because the cookies are sent without the two ones from above?
On my normal browser even when the session expires i only get asked to relog without completing the 2fa.

REST dataset for Copy Activity Source give me error Invalid PaginationRule

My Copy Activity is setup to use a REST Get API call as my source. I keep getting Error Code 2200 Invalid PaginationRule RuleKey=supportRFC5988.
I can call the GET Rest URL using the Web Activity, but this isn't optimal as I then have to pass the output to a stored procedure to load the data to the table. I would much rather use the Copy Activity.
Any ideas why I would get an Invalid PaginationRule error on a call?
I'm using a REST Linked Service with the following properties:
Name: Workday
Connect via integration runtime: link-unknown-self-hosted-ir
Base URL: https://wd2-impl-services1.workday.com/ccx/service
Authentication type: Basic
User name: Not telling
Azure Key Vault for password
Server Certificate Validation is enabled
Parameters: Name:format Type:String Default value:json
Datasource:
"name": "Workday_Test_REST_Report",
"properties": {
"linkedServiceName": {
"referenceName": "Workday",
"type": "LinkedServiceReference",
"parameters": {
"format": "json"
}
},
"folder": {
"name": "Workday"
},
"annotations": [],
"type": "RestResource",
"typeProperties": {
"relativeUrl": "/customreport2/company1/person%40company.com/HIDDEN_BI_RaaS_Test_Outbound"
},
"schema": []
}
}
Copy Activity
{
"name": "Copy Test Workday REST API output to a table",
"properties": {
"activities": [
{
"name": "Copy data1",
"type": "Copy",
"dependsOn": [],
"policy": {
"timeout": "7.00:00:00",
"retry": 0,
"retryIntervalInSeconds": 30,
"secureOutput": false,
"secureInput": false
},
"userProperties": [],
"typeProperties": {
"source": {
"type": "RestSource",
"httpRequestTimeout": "00:01:40",
"requestInterval": "00.00:00:00.010",
"requestMethod": "GET",
"paginationRules": {
"supportRFC5988": "true"
}
},
"sink": {
"type": "SqlMISink",
"tableOption": "autoCreate"
},
"enableStaging": false
},
"inputs": [
{
"referenceName": "Workday_Test_REST_Report",
"type": "DatasetReference"
}
],
"outputs": [
{
"referenceName": "Destination_db",
"type": "DatasetReference",
"parameters": {
"schema": "ELT",
"tableName": "WorkdayTestReportData"
}
}
]
}
],
"folder": {
"name": "Workday"
},
"annotations": []
}
}
Well after posting this, I noticed that in the copy activity code there is a nugget about "supportRFC5988": "true" I switched the true to false, and everything just worked for me. I don't see a way to change this in the Copy Activity GUI
Editing source code and setting this option to false helped!

Graph API doesn't restore a mail message, instead it is creating a new message with CreateDateTime automatically updated to present date

When I am performing restore of an email message via graph API with a Post request, instead of restoring it is creating a new message with the same data. Because in the JSON createDateTime is being updated although I am passing previous createDataTime.
To elaborate more: I want to restore below mail message which got created in 2018 ( "createdDateTime": "2018-12-31T14:49:42Z") but when I am posting same JSON for restore, createDateTime is being updated automatically to the present date. Which is problem because it's not the restore, it is just like creating new message.
{
"#odata.type": "#microsoft.graph.eventMessageResponse",
"#odata.etag": "W/\"DAAAABYAAABjFtMyIejaSbuRSeM/auJwAAGfpJnO\"",
"id": "AAMkAGZiNGI0MWM4LTQ0NjUtNDUyMy1hOTI2LWNopaTZiMGYxZTBkNQBGAAAAAACaBIVNrajXSj6AQcjiAFBwBjFtMyIejaSbuRSeM-auJwAAAAAAEJAABjFtMyIejaSbuRSeM-auJwAAGf4eRfAAA=",
"createdDateTime": "2018-12-31T14:49:42Z",
"lastModifiedDateTime": "2020-12-31T14:49:46Z",
"changeKey": "DopskAkslaAABjFtMyIejaSbuRSeM/auJwAAGfpJnO",
"categories": [],
"receivedDateTime": "2020-12-31T14:49:43Z",
"sentDateTime": "2020-12-31T14:49:42Z",
"hasAttachments": false,
"internetMessageId": "<MA1PR0101MB207oPF15907003958DB7A58BDD60#MA1PR0101MB2070.INDPRD01.PROD.OUTLOOK.COM>",
"subject": "Accepted: New Year Party",
"bodyPreview": "",
"importance": "normal",
"parentFolderId": "AQMkAGZiNGI0MWM4LTQ0ADY1LTQ1MjMtYTkyNi1jZGU2YjBmMWUwZDUALgAAA5oEhU2tqNdKuqPoBByOIAlkallspspspspspppAAAIBCQAAAA==",
"conversationId": "AAQkAGZiNGI0MWM4LTQ0NjUtNDUyMy1hOTI2LWNkZTZiMGYxZTBkNQAQAEJ5AU8Tk1nklXE3E0XGh2w=",
"conversationIndex": "AQHW34QsrZ0Wy3deoU2Bn2byefNABQ==",
"isDeliveryReceiptRequested": null,
"isReadReceiptRequested": false,
"isRead": true,
"isDraft": false,
"inferenceClassification": "focused",
"meetingMessageType": "meetingAccepted",
"type": "singleInstance",
"isOutOfDate": false,
"isAllDay": false,
"isDelegated": false,
"responseType": "accepted",
"recurrence": null,
"body": {
"contentType": "text",
"content": ""
},
"sender": {
"emailAddress": {
"name": "Mark Rober",
"address": "mark#securemigration.in"
}
},
"from": {
"emailAddress": {
"name": "Mark Rober",
"address": "mark#securemigration.in"
}
},
"toRecipients": [
{
"emailAddress": {
"name": "#Class Yammer",
"address": "ClassYammer#securemigration.in"
}
}
],
"ccRecipients": [],
"bccRecipients": [],
"replyTo": [],
"flag": {
"flagStatus": "notFlagged"
},
"startDateTime": {
"dateTime": "2020-12-31T15:00:00.0000000",
"timeZone": "UTC"
},
"endDateTime": {
"dateTime": "2020-12-31T15:30:00.0000000",
"timeZone": "UTC"
}
}
Please help me with it.

Docusign : 400 Error "Unable to parse multipart body" when trying to create envelope from Template ID from UI5 application

We are trying to figure out whether Docusign can be used in productive scenarios for our client requirements.
We have a UI5 application which will be used to sign Documents. We have created a template in the demo instance of Docusign.
However when we are trying to create an envelope from the application we are getting 400 Error Unable to parse multipart body. Now the same payload when used in POSTMAN application results in the envelope getting created successfully. The headers passed are also the same.
In Ui5 App :
var settings = {
"async": true,
"crossDomain": true,
"url": "/docusign/envelopes",
"method": "POST",
"timeout": 0,
"headers": {
"Authorization": "User DnVj27euWrCi4ANoMV5puvxVxYAcUCG3PlkUSpWpC08=, Organization 6ba64ce816dec995b17d04605e329a30, Element X4XuUq/T5UUh2o9xwaamZCCRwOKUCPr1Kv1Nj+qHPj0=",
"Content-Type": "application/json"
},
"data": JSON.stringify({
"status": "sent",
"compositeTemplates": [{
"compositeTemplateId": "1",
"inlineTemplates": [{
"recipients": {
"signers": [{
"email": "johndoe#testmail.com",
"name": "John Doe",
"recipientId": "1",
"roleName": "Signer",
"clientUserId": "12345",
"tabs": {
"textTabs": [{
"tabLabel": "firstName",
"value": "John"
}, {
"tabLabel": "lastName",
"value": "Doe"
}, {
"tabLabel": "phoneNo",
"value": "022-635363"
}, {
"tabLabel": "email",
"value": "test#gmail.com"
}]
}
}]
},
"sequence": "1"
}],
"serverTemplates": [{
"sequence": "1",
"templateId": "0bf97611-a457-4e8e-ac7e-1593c17ba3f6"
}]
}]
})
};
var deferred = $.Deferred();
$.ajax(settings).done(function (response) {
deferred.resolve(response);
}.bind(this)).fail(function (error) {
deferred.reject(error);
}.bind(this));
In Postman :
Help would be greatly appreciated in resolving this issue.
Could you stringify outside of the json settings and perhaps break your call down a little before placing everything in settings.
i.e. Try and re-shape your jquery ajax call:
var headers = {"Authorization": "User DnVj27euWrCi4ANoMV5puvxVxYAcUCG3PlkUSpWpC08=, Organization 6ba64ce816dec995b17d04605e329a30, Element X4XuUq/T5UUh2o9xwaamZCCRwOKUCPr1Kv1Nj+qHPj0=", "Content-Type": "application/json" };
var payload = JSON.stringify({
"status": "sent",
"compositeTemplates": [{
"compositeTemplateId": "1",
"inlineTemplates": [{
"recipients": {
"signers": [{
"email": "johndoe#testmail.com",
"name": "John Doe",
"recipientId": "1",
"roleName": "Signer",
"clientUserId": "12345",
"tabs": {
"textTabs": [{
"tabLabel": "firstName",
"value": "John"
}, {
"tabLabel": "lastName",
"value": "Doe"
}, {
"tabLabel": "phoneNo",
"value": "022-635363"
}, {
"tabLabel": "email",
"value": "test#gmail.com"
}]
}
}]
},
"sequence": "1"
}],
"serverTemplates": [{
"sequence": "1",
"templateId": "0bf97611-a457-4e8e-ac7e-1593c17ba3f6"
}]
}]
});
$.ajax({
"async": true,
"crossDomain": true,
"url": "/docusign/envelopes",
"method": "POST",
"timeout": 0,
"headers": headers,
"data": payload
});
I am sure this will lead you to your final "consolidated" answer.
If the exact same JSON is being sent from Postman and from the UI5 application, then you'll get the same results. But you aren't, so something is different.
Probably the UI5 system is sending the API as a mime multi-part request, but isn't setting the content type for the JSON request part correctly.
To verify: use the DocuSign API logger to see what is being received by DocuSign. Compare between the request being sent from UI5 and from Postman.
To fix: you'll need to set additional UI5 parameters so the request is NOT sent as a multi-part mime message. Or send the multi-part message with the needed settings. See the docs and see a multi-part example.
PS PLEASE post an answer to your question with the solution to your problem (once you've found it) to help others in the future. Thank you!!
I was able to fix the issue by directly using the Docusign API (https://demo.docusign.net/restapi/v2/accounts). I was earlier using the SAP Openconnector to connect to Docusign.
https://api.openconnectors.eu3.ext.hanatrial.ondemand.com/elements/api-v2
Thanks all for the help.
I have run into the very same issue recently, and almost decided to give up, but finally, I have managed to find a way to make it work!
The thing is that you need to execute the Ajax call in the following way:
_createEnvelops: function () {
var deferred = $.Deferred();
var oTemplateData = this._getTemplateData();
var oFormData = new FormData();
oFormData.append('envelope', JSON.stringify(oTemplateData));
var settings = {
"async": true,
"crossDomain": true,
"url": '/docusign/envelopes',
"method": "POST",
"data": oFormData,
processData: false,
contentType: false,
"headers": {
"Authorization": sAuthToken
}
};
$.ajax(settings).done(function (response) {
deferred.resolve(response);
}.bind(this)).fail(function (error) {
deferred.reject(error);
}.bind(this));
return deferred;
},
Maybe it will be useful for someone in the future ;)