Calling createContact() with logged in user returns 403 error

@paoloabarcelona Hi there OK I hav e some feedback for you.

I have looked at your site and noted a couple of things. At the moment it doesn’t allow new email addresses to be used for quoting. All you do is take and update a pre-existing record.

I think you should think through the requirements a little more. Here is a proposal that should get you passed the current hurdle.

IF all you want to do is use the email for sending triggered emails for quotes then there is a simple solution.

ONLY createContact if you don’t already have a record of the email in your ContactList data collection. Otherwise the contactId that you have stored for the email in your local data collection should do the trick.

ere is a proposal for the code you need. Notice I have tried to simplify the code by leveraging the power of Promises. Let me know if this makes sense.

$w("#submitForm").onClick( (event) => {
 /***********************************
 * TODO: Check ContactList table if email exists. 
 * If it doesn't, create a new contact in wixCRM
 * Get the ID of the new contact in wixCRM, create new row in the ContactList Table
 * Then start sending the email.. populate the fields by the ID. 
 ************************************/
 // check if there is passed data, if there's none, close this lightbox
 let bValid = true,
 guestName = $w("#name").value,
 guestCompany = $w("#companyName").value,
 guestEmail = $w("#email").value,
 guestPhone = $w("#phone").value,
 jobPost = null;
 // hide initially
 $w("#errorMessage").hide(); 
 // empty required fields?
 if (guestCompany === '' || guestEmail === '') {
     bValid = false;
 }
 // Any errors?
 if (!bValid) {
     // show error messages..
     $w("#errorMessage").show();
     return false;
 }
 // Any item Data?
 if (itemData.data && itemData.data.itemId) {
     wixData.get("JobList", itemData.data.itemId)
     .then( (results) => {
         // initialize
         jobPost = results; //see item below
         console.log(guestEmail);
         // check if contact exists
         // We return the result so we can propagate exceptions to the outer promise handler 
         // and use a single catch handler.
         return wixData.query("ContactList")
         .eq("email", guestEmail)
         .find()
         .then( (contactList) => {
 // We will use a Promise trick to allow for more simple code
 // keepMyPromise allows one of multiple responses to be sent to the next then
 // in sequence
             let keepMyPromise = Promise.resolve({});
             let contacts = contactList.items;
 // We should only see zero or one record with the guestEmail address
             if (contacts.length === 0) {
 // We haven't seen this one before so let's try add it to our CRM
 // then we can send a triggered email to the user
 // Set up keepMyPromise which, if successful should create the contact AND
 // save a new record to the "ContactList". The save result will be a new
 // "ContactList" item which we need to send our email
                 keepMyPromise = wixCRM.createContact({
                     "name": guestName,
                     "emails": [guestEmail],                             
                     "company": guestCompany,
                     "phones": [guestPhone],
                     "interest_area": jobPost.title,
                 })
                 .then((contactId) => {
 // CRM update successful
 // create new contactList entry
                     let newRow = {
                         title: guestEmail,
                         contact_id: contactId,
                         name: guestName,
                         phone: guestPhone,
                         company: guestCompany,
                         email: guestEmail
                     };
 // create a new SentQuoteList row. Return the promise so it can be used in
 // The outer .then() handler
                     return wixData.save("ContactList", newRow);
                 });
             } else if (contacts.length === 1) {
 // We have a record for this email already so we don't need to do anything 
 // other then pass the "ContactList" item to the email processing code
 // This requires a Promise
                 let existingContactRecord = contacts[0];
                 keepMyPromise = Promise.resolve(existingContactRecord);
             }
 // We don't need another else as we will end up returning an empty object if either of the
 // Previous tests fail
             return keepMyPromise; // Pass the contact item (if there is one) to our email handler
         })
         .then( (contactItem) => {
 // Data should have been successfully saved 
             if (Object.values(contactItem).length === 0) {
 // We didn't get a record from the previous processing - this can only happen if
 // the createContact fails due to a duplication
 // we find more than one record with the same email address in the "ContactList"
 // data collection - which cannot happen!
 // We will throw an error here to force the catch in the outer promise handler
                 throw Error('ERROR: CRM Record for email already exists OR internal server error');
             }
 
 // We have valid data
 // now we can send out the email
 // Get the contact id from the contact item
             let contactId = contactItem.contactId;
             if (!contactId) {
 // We will throw an error here which will force catch in our 
 // outer promise handler
                 throw Error("ERROR: ContactList record missing a CRM contact ID");
             }
 // We have a contactId so we can send the email! Return the promise result 
 // to the outer promise handler so we have a single catch to worry about

 // newsletter_signup below is the title of the triggered email
             return wixCRM.emailContact("quote_email", contactId, {
                 "variables": {
                     "title": jobPost.title,
                 }
             }).then(() => {
 // do something after the email was sent
                  let newSentRow = {
                        title: jobPost.title,
                        item_id: jobPost._id,
                        contact_id: contactId
                  };
 // create a new SentQuoteList row.
 // We return the save because that way we can delegate any exception
 // catches to the outer promise handler
                  return wixData.save("SentQuoteList", newSentRow)
                  .then( (results) => {
 // do redirect, or close the lightbox or show a message
                       console.log('sent details saved, email sent. (new contact)');
                 } );    
             }); 
         });
     })
     .catch( (error) => {
          let errorMsg = error.message;
          console.log("error: "+errorMsg);
          if (error.stack) {
              console.log("stack: "+error.stack);
          }
     });
  }

});

Hopefully this helps sort things out.

Steve