[Zapier/API] Creating a Contact

I’ve been trying to get my Zapier connections all set up and integrated with Invoice Ninja. So far so good, but I’ve run into an issue; I’d like to add a Contact to a Client when one is added to my project management software.

I’ve reviewed the API docs and see that there’s a POST method for Clients. I know this is wrong, but the PUT method isn’t right either since I’m not trying to update the “Client” record.

There doesn’t appear to be an endpoint specifically for Client Contacts and I’m a bit lost. Attached is my Zapier setup, could someone help me figure this out? Thanks!!

@gsm

We expect an array of contacts on the client object, so you’d want to attach your contact within an array on the client object.

Howdy David,
If I’m following Zapier’s docs correctly, the double underscore after contacts placing the those items in an array.

The way it’d be submitted is(I think):
{“id”: “m________0”,
“contacts”: [{
“first_name”: “Bob”,
“last_name”: “Your Uncle”,
“email”: “bob@youruncle.com”,
“phone”: “(999) 999-9999”
}]}

“If you need to add nested values, you can define child objects by adding the parent object and a double underscore before the object.”
https://zapier.com/help/create/code-webhooks/send-webhooks-in-zaps

I believe that’s the correct format, right? When I POST it creates a new Client record, when I PUT, it overrides the contact record stored.

You know, I see that Zapier throws in double-curly’s, I wonder if I just sent a custom POST with square brackets if that’d fix things…

@David I’ve spent days now trying to figure out how to add a client contact to a client. Through Zapier I’ve tried sending a PUT with the just the new contact info and I can’t even get that to create a contact which is’t completely empty.

Would you be willing to write out the method required to update and add new contacts? I’ve literally tried every combination I can think of with no results. Thanks!

@gsm

This is a sample CURL to create a client with a contact.

curl -X POST 'http://ninja.test:8000/api/v1/clients' \
-H "X-API-TOKEN:TOKEN" \
-H "Content-Type:application/json" \
-d '{"name":"Le Dudette","contacts":[{"first_name":"helly","email":"email@gmail.com"}],"settings":{"invoice_terms":"Client Terms"}}' \
-H "X-Requested-With: XMLHttpRequest";

One thing to note is that you always must sent the entire contacts array up. for all requests (POST,PUT)

Still not working. Here’s where we’re at: We’ve moved to using Zapier Code, JS, specifically.

Zapier data:

JS code:

const headers = {
  'X-Api-Secret': 'password',
  'X-Api-Token': 'TOKEN-ID-HERE',
}

fetch(`https://URL-HERE.com/api/v1/clients/${inputData.clientId}`, { headers })
.then((response) => response.json())
.then((client) => {
  const data = inputData.data.split(',')
  const labels = inputData.label.split(',')
  const newContact = {}

  labels.map((label, index) => {
    newContact[label] = data[index]
  })

  client.data.contacts.push(newContact)

//  console.log(client.data)
//  client.data.contacts.map(console.log)

  fetch(`https://URL-HERE.com/api/v1/clients/${inputData.clientId}`, {
    headers,
    method: 'put',
    body: client.data,
  })
  .then((response) => response.json())
  .then((json) => callback(null, json))
  .catch((error) => callback(error))
})
.catch((error) => callback(error))

When we spit out the data to the console log it appears that the existing contacts are there, and then the new contact, with the 4 fields is appended to the array. WHen the code is run though, all existing contacts are “deleted”, and a new, empty contact is created for the client.

Where are we going wrong?

Can you confirm you are also using the following headers

X-Requested-With: XMLHttpRequest

If that doesn’t help, it may be helpful if you show the output of the full request object that you are sending to the server.

We didn’t have that header in there, but I added it and it’s the exact same result. It’ll mark any attached contacts as deleted, then add an empty record new contact.

Here’s the updated header that we’re including:

const headers = {
  'X-Api-Secret': 'password',
  'X-Api-Token': 'TOKER-ID-HERE',
  'X-Requested-With': 'XMLHttpRequest',
}

Here’s the console.log(client.data):

INFO { id: 'm-------------0',
 user_id: 'V-----------m',
 assigned_user_id: '',
 name: 'Grey Sky Media',
 website: 'https://greyskymedia.com',
 private_notes: '',
 balance: 0,
 group_settings_id: '',
 paid_to_date: 0,
 credit_balance: 0,
 last_login: 0,
 size_id: '',
 public_notes: '',
 client_hash: 'B---------------------------9',
 address1: '5701 Lonetree Blvd',
 address2: '#315',
 phone: '',
 city: 'Rocklin',
 state: 'CA',
 postal_code: '95765',
 country_id: '840',
 industry_id: '',
 custom_value1: '',
 custom_value2: '',
 custom_value3: '',
 custom_value4: '',
 shipping_address1: '5701 Lonetree Blvd',
 shipping_address2: '#315',
 shipping_city: 'Rocklin',
 shipping_state: 'CA',
 shipping_postal_code: '95765',
 shipping_country_id: '',
 settings:
 { language_id: '1',
 currency_id: '1',
 payment_terms: '0',
 valid_until: '30',
 default_task_rate: 000 },
 is_deleted: false,
 vat_number: '',
 id_number: '66421',
 updated_at: 1631719427,
 archived_at: 0,
 created_at: 1630359874,
 display_name: 'Grey Sky Media',
 number: '00004',
 contacts:
 [ { id: 'GELe32Qd69',
 first_name: 'Jamison',
 last_name: 'Mergens',
 email: '111@000.com',
 created_at: 1630688732,
 updated_at: 1631719426,
 archived_at: 0,
 is_primary: true,
 is_locked: false,
 phone: '(916) 234-0040',
 custom_value1: '',
 custom_value2: '',
 custom_value3: '',
 custom_value4: '',
 contact_key: 'w---------------------------d',
 send_email: true,
 last_login: 0,
 password: '',
 link:
 'https://URL-HERE.com/client/key_login/w---------------------------d' },
 { id: 'K-----------L',
 first_name: '222',
 last_name: '222',
 email: '222@000.com',
 created_at: 1631551570,
 updated_at: 1631719427,
 archived_at: 0,
 is_primary: false,
 is_locked: false,
 phone: '(916) 234-0040',
 custom_value1: '',
 custom_value2: '',
 custom_value3: '',
 custom_value4: '',
 contact_key: 'q---------------------------4',
 send_email: true,
 last_login: 0,
 password: '',
 link:
 'https://portal.greyskymedia.com/client/key_login/q---------------------------4' },
 { first_name: '000',
 last_name: '000',
 email: '000@000.com',
 phone: '+000 000 000-0000' } ],
 documents: [],
 gateway_tokens: [] }

And the client.data.contacts.map(console.log):

INFO { id: 'K-------------L',
 first_name: '222',
 last_name: '222',
 email: '222@000.com',
 created_at: 1631551570,
 updated_at: 1631719065,
 archived_at: 0,
 is_primary: false,
 is_locked: false,
 phone: '(916) 234-0040',
 custom_value1: '',
 custom_value2: '',
 custom_value3: '',
 custom_value4: '',
 contact_key: 'q-------------------------------4',
 send_email: true,
 last_login: 0,
 password: '',
 link:
 'https://URL-HERE.com/client/key_login/q--------------------------------4' } 1 [ { id: 'G----------9',
 first_name: '111',
 last_name: '111',
 email: '111@000.com',
 created_at: 1630688732,
 updated_at: 1631719065,
 archived_at: 0,
 is_primary: true,
 is_locked: false,
 phone: '(916) 234-0040',
 custom_value1: '',
 custom_value2: '',
 custom_value3: '',
 custom_value4: '',
 contact_key: 'w---------------------------d',
 send_email: true,
 last_login: 0,
 password: '',
 link:
 'https://URL-HERE.com/client/key_login/w-----------------------------d' },
 { id: 'K------------L',
 first_name: '000',
 last_name: '000',
 email: '222@000.com',
 created_at: 1631551570,
 updated_at: 1631719065,
 archived_at: 0,
 is_primary: false,
 is_locked: false,
 phone: '(916) 234-0040',
 custom_value1: '',
 custom_value2: '',
 custom_value3: '',
 custom_value4: '',
 contact_key: 'q-------------------------------4',
 send_email: true,
 last_login: 0,
 password: '',
 link:
 'https://URL-HERE.com/client/key_login/q--------------------------4' },
 { first_name: '000',
 last_name: '000',
 email: '000@000.com',
 phone: '+000 000 000-0000' } ]

See anything out of place with my request? THANK YOU

@gsm

the request looks ok, i am assuming the redacted contact ids are for the individual contact?

@hillel are you able to see anything odd here?

Yes, they are. There are two existing contacts, then I’m trying to add the 3rd.

and just to confirm, when adding the third, you are pushing all three contacts up?

Yeah, we’re sending the entire result of the contacts array plus the new one appended to the end

And when you CURL to the server does it work as expected?