All Collections
Advanced Python SDK Migration Guide
Advanced Python SDK Migration Guide

Support for migrating to our Advanced Python SDK!

Matthew Ho avatar
Written by Matthew Ho
Updated over a week ago

Based on customer feedback, we have been working on improving our all-category SDKs. We recently released our Advanced Python SDK. It is currently available for anyone to use.

Note that the existing Python SDKs are fully functional and will continue to work.

There are key benefits in using this Advanced SDK. We understand that migrating will take both time and effort, which is why we’ve worked on putting together this helpful migration guide.

We strongly recommend to use the new SDKs. You’ll play an integral role in providing feedback on our SDKs, making them more usable and robust and get a head start on migrating over.

We would love any and all feedback by reaching out to your engagement manager or [email protected]. All your feedback will be promptly addressed.

Migration Guide

This guide is for Merge customers using the gen-0 and gen-1 python SDKs:

We recommend all customers move to the Advanced SDK:

This SDK has the following advantages:




Methods can be run using await which was released as part of the asyncio package

More http layer configurability

Easier configuration options to change timeouts, retries, etc.


The new SDK exposes a more comprehensive set of Python types. Caveat that expanded responses and dynamic enum values will not adhere to these standard types.


This SDK ships with a much more comprehensive set of unit tests compared with the prior SDK.

This SDK has all Merge categories, which makes it easy for Merge customers to find all endpoint methods in one package. The earlier single-category SDKs as well as the multi-category SDK all have the same style of method call, so let’s consider what it looks like to move from an existing employees list call to the new SDK.

Pip Changes

Firstly, you may have a pip requirements file that have a line like:

... MergePythonSDK==1.0.0 # or some other version number. ...

To bring in the new package, swap out that line for

... mergepythonclient=0.0.1 ...

Earlier SDK Code

hris_configuration = Configuration() 
hris_configuration.access_token = "your api key" hris_configuration.api_key_prefix['tokenAuth'] = 'Bearer' hris_configuration.api_key['accountTokenAuth'] = 'YOUR_X_ACCOUNT_TOKEN'

with ApiClient(hris_configuration) as api_client:
hris_employees_api_instance = EmployeesApi(api_client)
api_response = hris_employees_api_instance.employees_list()
assert api_response.results is not None

next_page =
next_response = hris_employees_api_instance.employees_list(cursor=next_page)
assert next_response.get("results") is not None
except ApiException as e:
print('Exception when calling HRIS API: %s' % e) raise e

Advanced SDK Equivalent

api_key = "your api key"
hris_account_token = "YOUR_X_ACCOUNT_TOKEN"

client = Merge(api_key=api_key, _strict_response_validation=False, account_token=hris_account_token)

employees = client.hris.employees.list()
if employees.has_next_page():
next_page = employees.get_next_page()...

# alternatively, you can use the result as an iterator in a plain for loop
for employee in client.hris.employees.list():
# operate on employee...

Here are some key advantages from the new client class:

  • Authentication configuration has been somewhat simplified, you do not need to specify "Bearer" prefix anymore as it is assumed.

  • Pagination is easier, there are helper methods as well as the built-in iterator

Typed Models

One of the longstanding drawbacks of the earlier SDKs are that they follow a very meta-programming approach to models. All of the models inherit this utility class:

class ModelNormal(OpenApiModel):
"""the parent class of models whose type == object in their
def get(self, name, default=None):
"""returns the value of an attribute or some default value if the attribute was not set"""
if name in self.required_properties:
return self.__dict__[name]

return self.__dict__['_data_store'].get(name, default)

def __getitem__(self, name):
"""get the value of an attribute using square-bracket notation: `instance[attr]`"""
if name in self:
return self.get(name)

raise ApiAttributeError(
"{0} has no attribute '{1}'".format(
type(self).__name__, name),
[e for e in [self._path_to_item, name] if e]

This made it difficult to run type checking, although it does allow for metadata-based validation of things like required properties. By contrast, the type definitions for the new SDK are much more conventional:

class Employee(BaseModel):
avatar: Optional[str]
"""The URL of the employee's avatar image."""

company: Optional[str]
"""The ID of the employee's company."""

custom_fields: Optional[object]
"""Custom fields configured for a given model."""

date_of_birth: Optional[datetime]
"""The employee's date of birth."""

display_full_name: Optional[str]
"""The employee's full name, to use for display purposes.

In the new SDK, the BaseModel definition contains only a few pydantic-based type checking options, with none of the getattr/setattr behavior of the earlier SDKs. This should make using these models easier, and allow it to work more seamlessly with customer build systems.

Did this answer your question?