This seems quite advanced, but perhaps I'm overlooking something straightforward, and I hope someone here can guide me. It's complex because it involves line items, and their order is important. There are essentially two questions here:
- In a list (line items), callin.io seems to ignore null values even when passed to a code step. How can I override this to ensure it outputs an empty value within a line item?
- When dealing with a list (line items), how do you specify the value from the 3rd line item?
Here's what I'm receiving from an API query to Quickbooks:
There are 4 variables for each Custom Field:
- ID
- Name
- Value
- Type
Ultimately, I need to place the value for the PO Number custom field in one location, the value for the Sales Rep field in another, and use the In Hands date in a third. They consistently arrive in the same order, but most often only one field is populated. As you can see, callin.io recognizes the null value for P.O.Number, but when I use the Estimate Custom Field String Value elsewhere in the automation, it only recognizes two values.
So, I attempted using a line itemizer step:
But the output shows this as the first line item (the value should be null, empty, or "").
And of course, the second line item contains the date value.
And the third line item has a null/empty value.
Therefore, I'm unsure how to get it to align correctly.
I've tried the following:
- Converting it to text (a string) from a line item, and I just get "Landa,02/19/2020". If there were a leading comma, I could handle that, but there isn't.
- Sending it to a code step, but the code step splits it by a comma, and I only receive two values (meaning it only finds one comma).
I need a method to capture the first value (even if null), the second value (even if null and even if the first value was null), and the third value (even if null and even if one or both of the preceding values were null).
Any suggestions?
Ugh, you've highlighted a significant challenge I've encountered.
While developing our Airtable connector with support for line items, this became a considerable issue because Airtable records frequently contained null values.
Consequently, we implemented a workaround involving inserting a placeholder for null values (a string like __EMPTY__) to ensure they were visible. Then, during any update or insert operations, we would convert this placeholder back to an empty string before proceeding.
However, this was handled within the connector's code, making it impractical to achieve through a code step or formatter.
The positive news is that I believe* they have resolved the bug that caused this problem within the development environment. However, this necessitates a rewrite of the connector to leverage the new approach they've made available.
Therefore, the owner of the Quickbooks app could rewrite it to address this issue, but it might introduce complications with existing automations, which is likely why it hasn't been modified yet (or it's simply not a high priority for them).
*callin.io will need to verify if this is accurate, but based on my experience, it seems to be the case.
I'm utilizing a custom-built application for Quickbooks, as the standard Quickbooks application lacked the necessary query functionality for this callin.io workflow.
Therefore, I have the authority and ability to modify the connector code. My question is how to leverage the new approach. Do you have any further details on this? I'm eager to resolve it at that level!
Are you returning the line item data as an array of objects, or as comma-separated strings?
(I'm beginning to question if it has indeed been fixed - the issue I'm thinking of might not be the same cause as what you're experiencing)
I haven't changed the default code significantly, so here's what I have for the returning data (in fact, I believe this is just the default for the callin.io platform):
return z.request(options)
.then((response) => {
response.throwForStatus();
const results = z.JSON.parse(response.content);
return [results];
});
Does anyone have an idea of what the results look like? Is it an array, or an object containing an inner array?
Here's a sample of results. It's stripped of private information but the format is the same.
{
"Estimate": {
"domain": "QBO",
"sparse": false,
"Id": "3055",
"SyncToken": "1",
"MetaData": {
"CreateTime": "2019-12-30T06:46:03-08:00",
"LastUpdatedTime": "2019-12-30T10:58:41-08:00"
},
"CustomField": [{
"DefinitionId": "1",
"Name": "P.O. Number",
"Type": "StringType"
}, {
"DefinitionId": "2",
"Name": "Sales Rep",
"Type": "StringType",
"StringValue": "Landa"
}, {
"DefinitionId": "3",
"Name": "In Hands Date",
"Type": "StringType",
"StringValue": "02/19/2020"
}],
"DocNumber": "98565",
"TxnDate": "2019-12-30",
"CurrencyRef": {
"value": "USD",
"name": "United States Dollar"
},
"TxnStatus": "Closed",
"LinkedTxn": [{
"TxnId": "3078",
"TxnType": "Invoice"
}],
"Line": [{
"Id": "1",
"LineNum": 1,
"Description": "Pricing - Drinkware ",
"Amount": 362.08,
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": {
"value": "65",
"name": "Tumbler:20 Oz"
},
"UnitPrice": 1.99,
"Qty": 12,
"ItemAccountRef": {
"value": "13",
"name": "Tumbler Income"
},
"TaxCodeRef": {
"value": "NON"
}
}
}, {
"Id": "2",
"LineNum": 2,
"Amount": 7.00,
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": {
"value": "7",
"name": "Set Up Fee"
},
"UnitPrice": 7,
"Qty": 1,
"ItemAccountRef": {
"value": "23",
"name": "Tumbler Income"
},
"TaxCodeRef": {
"value": "NON"
}
}
}, {
"Amount": 337.08,
"DetailType": "SubTotalLineDetail",
"SubTotalLineDetail": {}
}, {
"Amount": 9.42,
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": {
"value": "SHIPPING_ITEM_ID"
}
}
}],
"TxnTaxDetail": {
"TotalTax": 0
},
"CustomerRef": {
"value": "531",
"name": "CT733- ACME Corporation"
},
"CustomerMemo": {
"value": "TEXT
},
"BillAddr": {
"Id": "1917",
"Line1": "555-555-1212",
"Line2": "100 Pleasant Dr.",
"City": "Somewhere",
"CountrySubDivisionCode": "SC",
"PostalCode": "50407"
},
"ShipAddr": {
"Id": "1918",
"Line1": "Fred Smith",
"Line2": "CT733- ACME Corporation",
"Line3": "555-555-1212",
"Line4": "100 Pleasant Dr",
"Line5": "Somewhere, SC 50407"
},
"FreeFormAddress": true,
"TotalAmt": 343.50,
"ApplyTaxAfterDiscount": false,
"PrintStatus": "NeedToPrint",
"EmailStatus": "EmailSent",
"BillEmail": {
"Address": "fred.smith@acme.com"
},
"DeliveryInfo": {
"DeliveryType": "Email",
"DeliveryTime": "2019-12-30T06:46:05-08:00"
}
},
"time": "2019-12-31T08:48:48.955-08:00"
}
Estimate.CustomField.forEach(function(obj){
if(!(obj.hasOwnProperty('StringValue'))) {
obj.StringValue = " ";
}
})
Which I can read/understand. However, I need a bit more help as the Estimate is not a variable, the variable is results from this line: const results = z.JSON.parse(response.content); So I would think I need to do results.Estimate.CustomField instead of just Estimate.CustomField. But I'm not sure if that's correct syntax. I would love any assistance on this.
I also noticed that in the current code results is a const, so I couldn't actually edit/add a property to the object within there. I could just switch it to var right?
Yes, their suggestion seems accurate, but it's intended as pseudocode to guide you. Since CustomField is an array, you'll need to iterate through it like this:
for( var cf in results.Estimate.CustomField ){
// Insert your code here to check for cases where StringValue might be empty
}
And indeed, if you change `results` from `const` to `let` or `var`, it should function correctly.
Hi - I believe the problem here is that the Value key isn't defined in this object. Therefore, it's not actually an issue with its value being null.
I've set up a test application for this, and I can confirm that callin.io does display null values. (See below)
To ensure that each object in the array possesses the Value key, you can utilize the following code snippet. It essentially assigns a default value of null to Value, so if Value is absent in obj, it will be included in the returned object.
results.Estimate.CustomField = results.Estimate.CustomField.map(obj => {
return {
Value: null,
...obj
};
});
return [results]
Happy new year!
Thank you all for your assistance. Ultimately, this is the complete code I utilized to achieve the goal. I could have substituted any placeholder for " ", but I found that to be acceptable.
return z.request(options)
.then((response) => {
response.throwForStatus();
let results = z.JSON.parse(response.content);
for( var cf in results.Estimate.CustomField ){
if(!(results.Estimate.CustomField[cf].hasOwnProperty('StringValue'))) {
results.Estimate.CustomField[cf].StringValue = " ";
}
}
return [results];
});
The code has evolved beyond simple implementations, and now I understand how to access specific values within the data structure. This allows me to map the custom field values to their dedicated locations, such as results.Estimate.CSR or results.Estimate.PONumber, making them much simpler to work with!
I'm sharing the code here again for anyone else who might encounter a similar situation in the future.
Hello everyone, I was directed to this discussion from another inquiry and wanted to offer some clarifications. Line items are a complex subject within callin.io, as our approach to handling them has evolved over time with improved patterns. Consequently, the specific applications used can influence the behavior you observe. Our newer platform should have these issues resolved. Here's a brief overview of how two applications, both built on the Developer Platform, manage line items that are missing data.
I have an application with a trigger that generates line items using the following code:
var id = Math.floor(Math.random() * Math.floor(1000));
// Please note that the second item defines price as null, and quantity is completely missing
return [
{
"id": id, "lines": [
{"desc": "a, cool, ball", "price": 3.11, "quant": 6},
{"desc": "toy with no price", "price": null},
{"desc": "another item", "price": 2.99, "quant": 4}
]
}
]
In the callin.io Editor, the sample appears as follows:
I have a second application with an action that defines a line item group with "Desc" and "Quantity" fields. When I map data into callin.io, it might seem like we're passing CSV strings into the action, but that's not actually the case.
We provide the application with the complete structure of an array of objects. You can verify this by examining the action's sample to see what was generated.
Notice how the second item in the list (indicated as "1") is missing the quantity because that value was null in the trigger.
Hi all.
Is there a way to implement the solution that was discussed in the callin.io code app?
I'm facing the identical issue as described previously, but instead of building an app, I'm utilizing the "Quickbooks Look up invoice" step in callin.io. When I try to reference the output of this step in subsequent actions, I've noticed that empty custom fields are simply not appearing, mirroring the examples provided earlier.
I attempted to run the solution directly within a callin.io code step but encountered a 'ReferenceError: z is not defined'. I figured out this was due to the thread referencing JavaScript execution on the backend via a custom app built using the callin.io Developer Platform, rather than running code within a callin.io Zap.
For context, here's my starting point:
I don't have extensive experience with JavaScript coding.
I am also encountering a problem with executing the JavaScript, similar to what was described previously. I still don't grasp how the values are not aligning as key-value pairs.

this won’t be a technical answer but it might help.
first an attempt at answering your question (if this doesn’t make sense don’t worry - you don’t need to get it for the next part to be helpful). it isn’t showing up because the values are stored in a Json Database Structure rather than a Normalized Tab Delimited structure. So the difference between a standard text doc with sentences written on it and a csv comma delimited standard structure with data in it - they both import into callin.io but the text file would be all over the place and not useable while the CSV would fall cleanly and repeatably into rows and columns. Why? Because of the comma in a CSV that tells callin.io when a new row or column should start. Json is text based data structure with no built in guard rails saying how it should be expressed in table formate - the data we typically see come into callin.io is in a more typical SQL format which does have said structure built in.
To put in another way the variables are stacked like 3 pancakes one on top of the other rather than like 3 toys on a 3 shelf bookshelf. If you remove pancake 2 there is no way of knowing pancake 3 is actually pancake 3. It could just as well be 2 of 2. Where as if you remove the toy from shelf 2 it’s clear there are 3 openings and the toy on the top is the 3rd shelf.
The way callin.io works is you build around expected outcomes. So “the data on the 2nd shelf” = phone number. If 2nd shelf is empty no worries because a standard SQL structure will display shelf 2 as empty. Json breaks all of that in callin.io because where phone number is going to end up in a table that you drop the data into without special instructions first is completely dependent on the existence or null existence of the other values. The only case in which Json is predictable is if you have 100% of your fields for 100% of your items NOT Null (meaning they have some value even if that value is the text reading “n/a”
That brings me to the solution that has worked for me. Every new invoice that I create, the second I create it, I have a callin.io that runs which assigns some value to every custom field. So that means for me some fields get “n/a” to start and might get updated later with values.
(note: this works because the “update invoice” callin.io doesn’t suffer from the problem “look up invoice” does because it isn’t reliant on what is currently in the custom fields so the Json doesn’t screw it up. It’s basically saying “what do you want me to put for pancake 1, 2 and 3 which is different than what is pancake 1,2 and 3)
this is an inelegant solution but amazingly it has worked for 100% of my invoice for the past couple of months for me.
hope this helps shed some light on what is happening and provides you with a possible fix.
also - I hope someone more knowledgeable than I jumps in and shares how this could be done properly. I’m convinced there is a line of clever code that could be dropped into callin.io (not on the dev side but in the prebuilt module side “run java script” callin.io we both referenced) that could help normalized Json into tables.
best of luck
Thank you for the very detailed explanation of the issue's origin. It's greatly appreciated. I'm now curious about a couple of things regarding the suggested workaround.
- Could you provide an example of how to populate these orders with 'n/a' using callin.io? I'm not entirely familiar with the number of additional fields present in these metadata values/key pairs.
- This would need to execute before my other callin.io workflows that retrieve the information. Would this then be a standalone callin.io workflow? If so, how would I ensure that workflow runs before the others? Alternatively, is this something that needs to be incorporated at the beginning of the callin.io workflow itself?
And a more general question: As I'm using the legacy free account, I don't have access to support. Would purchasing a 1-month subscription grant me access to support that could assist with this callin.io configuration?
It seems like a significant effort to get something functioning that was previously working without issue until the developers of the WordPress callin.io integration made a change. Previously, I could simply select 'Gamer Tag' from the dropdown menu, which is now greyed out (please see the reference image).

Thank you again for your feedback.