Step 4: Migrating the records of legacy custom objects
This article describes how to migrate the records created from your legacy objects to the new custom objects experience.
Topics covered in this article:
- Understanding how legacy records map to records in the new custom objects experience
- Migrating legacy object records
- Next steps
This is the fourth article in a series on migrating legacy custom objects:
- Step 1: Migrating the object types of legacy custom objects
- Step 2: Migrating the schemas of legacy custom objects
- Step 3: Migrating the relationship types of legacy custom objects
- Step 4: Migrating the records of legacy custom objects
- Step 5: Migrating the relationship records of legacy custom objects
Disclaimer: Zendesk provides this article for instructional purposes only. Zendesk doesn't provide support for the example code in this article. Zendesk doesn't support third-party technologies such as Python.
Understanding how legacy records map to records in the new custom objects experience
The data of a legacy record is stored in the attributes
property of the record. Example:
{
"attributes": {
"id": "3b0ff066-e8ec-11e6-bf01-fe55135034f3",
"name": "Miso",
"breed": "Corgi",
"training": false
}
}
In the new custom objects experience, the data of a record is stored in the custom_object_fields
property as well as the name
property. For example, after migrating the legacy record above to the new custom object experience, the new record should look as follows:
{
"custom_object_record": {
"custom_object_fields": {
"breed": "Corgi",
"training": false
},
"name": "Miso",
"id": "01GDXYEY1FQYN066VHF49YHJ21"
}
}
The name
property is the standard name
field for the object. See Custom Object Fields. If you selected autonumbering in Admin Center for the custom object's standard name
field, then the name
property isn't allowed because the value is automatically generated. If uniqueness is enforced for the standard name
field, then the name
value must be unique.
Migrating legacy object records
Migrating legacy object records consists of retrieving the records of a legacy object and then using each record to create a corresponding record in the new experience.
Example main function logic
The following example main()
function shows the general logic of migrating legacy records to the new custom objects experience. The called functions are explained in the follow-up sections.
def main():
record_map = {}
object_types = get_object_types()
for object_type in object_types:
object_records = get_object_records(object_type)
for record in object_records:
migrate_object_record(record, record_map)
write_json_file('record_map.json', record_map)
# utility function
def write_json_file(file_path, file_data):
with open(file_path, mode='w', encoding='utf-8') as f:
json.dump(file_data, f, sort_keys=True, indent=2)
Example function for getting the object records
The following example Python function gets the records of a legacy object.
The function uses the List Legacy Object Records endpoint to export a list of records for a given object:
GET /api/sunshine/objects/records
You don't need to get the records of standard Zendesk objects (tickets, users, and organizations). They're shared between the two custom objects experiences in the same account.
def get_object_records(object_type) -> list[dict]:
object_records: list[dict] = []
params = {'type': object_type['key'], 'per_page': 1000}
endpoint = 'api/sunshine/objects/records'
url = f'https://{ZENDESK_SUBDOMAIN}.zendesk.com/{endpoint}'
auth = f'{ZENDESK_USER_EMAIL}/token', ZENDESK_API_TOKEN
response = requests.get(url, params=params, auth=auth)
# paginate through results
while url:
if response.status_code != 200:
print(f'Failed to retrieve {object_type["key"]} records: {response.status_code}: {response.text}')
return []
records = response.json()['data']
if records:
object_records.extend(records)
links = response.json()['links']
if links['next']:
url = f'https://{ZENDESK_SUBDOMAIN}.zendesk.com{links["next"]}'
response = requests.get(url, auth=auth)
else:
url = ''
return object_records
Example function for migrating a record
The following example Python function creates a record in the new experience based on a legacy record.
The function uses the Create Custom Object Record endpoint:
POST /api/v2/custom_objects/{custom_object_key}/records
The body of a request consists of a custom_object_record
object such as the following:
{
"custom_object_record": {
"custom_object_fields": {
"breed": "Corgi",
"training": false
},
"name": "Miso"
}
}
The name
property corresponds to the standard name
field for the custom object. If you didn't map a field to it from the schema of the legacy object, you must provide a value when you create each record for the object. If you selected auto-numbering in Admin Center for the standard name
field, then you can omit the name
property from records because the value is automatically generated. If uniqueness is enforced for the standard name
field, then make sure the name
value is unique.
The example function assumes name auto-numbering and uniqueness are not enabled in Admin Center.
It's also important to get the id of each record you create and map it to the id of its associated legacy record, then save the map. You'll need this map to recreate the relationships between the records in the next step.
If you get errors, check the fields of the custom object to make sure they're correctly mapped to the schema of the legacy custom object. In Admin Center, click Objects and rules in the sidebar, then select Custom objects > Objects. Select the object, then click the Fields tab.
def migrate_object_record(record, record_map):
# set the record name
if 'name' in record['attributes']:
name = record['attributes']['name']
del record['attributes']['name']
else:
name = record['type'].replace('_', ' ').capitalize()
# create the request body
data = {
'custom_object_record': {
'custom_object_fields': record['attributes'],
'name': name
}
}
# make the request
custom_object_key = record['type'] # assumes legacy and new object keys are same
endpoint = f'api/v2/custom_objects/{custom_object_key}/records'
url = f'https://{ZENDESK_SUBDOMAIN}.zendesk.com/{endpoint}'
response = requests.post(url, json=data, auth=AUTH)
if response.status_code != 201:
print(f'- Failed to create record for record {record["id"]}: {response.status_code}: {response.text}')
return {}
data = response.json()
created_record_id = data['custom_object_record']['id']
record_map[record['id']] = created_record_id
Next steps
After migrating the records of your legacy custom objects, you can recreate the relationships between them. See Step 5: Migrating the relationship records of legacy custom objects.