I do not like working with SOAP APIs, but with Netsuite you can only use REST APIs if you write them yourself. In this area Netsuite keeps it consistent by having round about, complicated, unintuitive APIs, but hopefully this will help demystify them a little bit. I will follow this up with a more detailed description of how to interact with Netsuite’s SOAP APIs using Python.
Navigating the WSDL:
Netsuite’s WSDL is broken up into 38 namespaces that you will need to navigate to retrieve the relevant object structures. There is a useful guide in SuiteAnswers that lists the record types in each of the namespaces with a link to the namespace, so you can investigate the object further. In order to get to the guide you will need to log into Netsuite, click on Support > SuiteAnswers. Once the page has fully loaded you can paste in this link:
https://netsuite.custhelp.com/app/answers/detail/a_id/10824/kw/soap%20api
If you try to go directly to the link you will be prompted to login and then be taken to the Netsuite homepage, so unfortunately you have to follow the above order operations.
To retrieve an object’s structure you will first need to navigate to the relevant namespace and then retrieve the structure using the object’s exact name as it is listed in the WSDL. There are multiple ways to specify the namespace. You can use the namespace name that is listed, e.g. “urn:core_2018_1.platform.webservices.netsuite.com”, or you can refer to them by number, e.g. ns0. The python netsuite connector I use has methods that enable you to navigate to different Namespaces using plain english, which is nice.
Lookup Fields:
In the Netsuite WSDL lookup fields have the type RecordRef. In order to set a RecordRef field on any record type you will need to first get the structure for a RecordRef field. You can do this by navigating to the Core namespace, "urn:core_2018_1.platform.webservices.netsuite.com" and then getting the RecordRef structure. As an aside as you are trying to navigate these files you can usually find the object you are looking for by searching fore complextype=”{name}”.
Once you have the record RecordRef you will want to set that as the value for your RecordRef field. To specify the value for the RecordRef field I generally prefer to use the internalId. To do this you simply set the internalId in the internalId field of the RecordRef.
Here is an example of what a RecordRef field looks like in Python:
'subsidiary': {
'name': 'Formlabs Inc.',
'internalId': '5',
'externalId': None,
'type': None
}
Keep in mind that you only need to populate the internalId field to set the value.
Custom Fields:
Setting custom fields in Netsuite is particularly annoying. Instead of simply being key, value pairings in the main body custom fields are added in a related list, with, you guessed it, its own type and of course each custom field has its own type as well. In order to set these you will need to know the type and internalId of the custom field. If your custom field is a drop down then you will also want to know the internalId of the value you want to set.
Each Netsuite object definition in the WSDL has a customFieldList key. You will need to set this to the Core CustomFieldList structure. Then set the CustomFieldList.CustomField to a list of all your custom fields.
For each custom field you want to set you will want to know its type (Long, Double, Boolean, String, Date, Select, Multiselect) so you can get the appropriate structure. These structures are all available in the Core namespace with names like, {type}CustomFieldRef, e.g. StringCustomFieldRef. In order to set it I recommend setting the InternalId and the value.
For Selects and Multiselects there is an added step. In the value section you will have to add another WSDL structure, Core ListOrRecordRef. In the case of the Multiselect type it will contain a list of this type.
Here is an example of what a CustomFieldList looks like in Python:
'customFieldList': {
'customField': [{
'value': '32977',
'internalId': '1666',
'scriptId': 'custentity_nm_mg_cust_id'
}, {
'value': False,
'internalId': '2724',
'scriptId': 'custentity_cps_bdc_lastupdatedbyimport'
}, {
'value': {
'name': 'Formlabs US',
'internalId': '13',
'externalId': None,
'typeId': '206'
},
'internalId': '1700',
'scriptId': 'custentity_nm_mg_website'
}, {
'value': False,
'internalId': '1667',
'scriptId': 'custentity_nm_mg_gs_customer'
}, {
'value': True,
'internalId': '2491',
'scriptId': 'custentity_smba_updatesub'
}, {
'value': False,
'internalId': '983',
'scriptId': 'custentity_celigo_mg_customerexport'
}, {
'value': '32977',
'internalId': '981',
'scriptId': 'custentity_celigo_magento_id'
}, {
'value': {
'name': 'Japan (Distributor)',
'internalId': '205',
'externalId': None,
'typeId': '213'
},
'internalId': '1665',
'scriptId': 'custentity_nm_mg_cust_group'
}, {
'value': '32977',
'internalId': '2481',
'scriptId': 'custentity_magento_customer_id'
}, {
'value': True,
'internalId': '1527',
'scriptId': 'custentity_celigo_sfnc_push_to_salesforc'
}]
}
Example SelectCustomFieldRef:
{
'internalId': '1665',
'scriptId': 'custentity_nm_mg_cust_group',
'value': {
'name': 'Japan (Distributor)',
'internalId': '205',
'externalId': None,
'typeId': '213'
}
}
Keep in mind that you only need to populate the internalId field to set the value.
Hopefully this helps give you a decent starting point for interacting with the Netsuite WSDL to set the values you want. The way I learned was reading a lot of code that uses the Netsuite SOAP APIs, staring vacantly at the WSDL and writing code that uses the Netsuite SOAP APIs. I imaging that will unfortunately probably be a necessary step for anyone trying to integrate with Netsuite through their SOAP APIs.