Python SDK bulk user creation from CSV throwing 409

Is there a clean way to handle 409 Conflict: A user with the same email address already exists. when using the Python SDK to bulk-create users from a CSV file?

I am building a Kafka Connect sink that ingests HR system events and pushes them to Genesys Cloud via the Python SDK (genesyscloud 2.0.14). The pipeline reads a CSV containing email, name, and division_id.

Here is the relevant snippet:

from genesyscloud.users.api import users_api

api = users_api.UsersApi(api_client)
for row in csv_data:
 try:
 user = api.post_users(body=CreateUserRequest(
 email=row['email'],
 name=row['name'],
 division_id=row['division_id']
 ))
 except ApiError as e:
 if e.status == 409:
 # Currently just logging and skipping
 logger.warning(f"Duplicate: {row['email']}")

Simply skipping the 409 is a band-aid. I need to either:

  1. Check existence first via GET /api/v2/users with email filter.
  2. Use an upsert mechanism if one exists (doesn’t seem to).

The GET approach feels inefficient for high-volume batches. Is there a more robust pattern in the SDK for idempotent user creation? I want to avoid flooding the API with existence checks before every write.

This looks like a scope issue in your error handling logic. docs state “a 409 Conflict response indicates that the requested resource already exists.” you are getting this because your script tries to create a user with an email that is already provisioned in the organization. i am confused why you do not check for existence first.

the suggestion above ignores the idempotency requirement. you need to catch the specific ApiException with status code 409. if you just let it crash, your Kafka sink fails. use this pattern to skip existing users.

from genesyscloud.rest import ApiException
from genesyscloud.users.api import UsersApi

users_api = UsersApi()

for row in csv_data:
 try:
 user_request = {
 'email': row['email'],
 'name': row['name'],
 'division_id': row['division_id']
 }
 created_user = users_api.post_users(body=user_request)
 print(f"Created user: {created_user.id}")
 except ApiException as e:
 if e.status == 409:
 # User already exists, skip creation
 print(f"User {row['email']} already exists. Skipping.")
 else:
 # Other API errors should be raised or logged differently
 print(f"Unexpected error: {e.body}")
 raise

docs state “the API returns 409 if the email is already in use.” your code must handle this gracefully. if you do not catch 409, your pipeline stops. this is basic error handling. why do you think creating a duplicate user is valid? it is not. use the try-except block above. it works. i tested it in my local environment. the timeout issue you mentioned earlier is separate. focus on the 409 first.

Have you tried wrapping the creation call in a try-except block to catch ApiException with status 409? The suggestion above is correct, but you must ignore the error instead of failing the pipeline, as idempotency requires treating existing users as successful operations.

The quickest way to solve this is to wrap the create_user call in a try-except block. Catch the ApiException and check if e.status == 409. This treats the conflict as a successful idempotent operation, preventing pipeline failure when the email already exists in the tenant.

Just ensure you log the conflict for auditing. Do not retry the request. The genesyscloud SDK raises this exception explicitly, so handling it locally keeps your Kafka sink stable.

It depends, but generally…

The 409 conflict is standard behavior for idempotent bulk operations. The suggestion above regarding try-except is correct, but for CI/CD pipelines or high-volume ingestion, raw exception handling can add latency. A more robust pattern involves pre-fetching existing user IDs or leveraging the SDK’s built-in retry logic with specific HTTP status codes.

Here is a refined approach using PureCloudPlatformClientV2 to handle the conflict gracefully without crashing the pipeline:

from genesyscloud.rest import ApiException
from genesyscloud.users.api import UsersApi

def create_user_idempotent(api: UsersApi, user_body):
 try:
 return api.post_users(body=user_body)
 except ApiException as e:
 if e.status == 409:
 # Log conflict, treat as success for idempotency
 print(f"User already exists: {user_body.email}")
 return None 
 raise e

Ensure your OAuth token has the user:write scope. Verify the division_id matches the target org structure.

  • Idempotency keys
  • Rate limit headers (X-RateLimit-Remaining)
  • Division ID validation
  • OAuth scope permissions