Genesys Cloud Analytics Export to S3: 403 Forbidden on PUT request using Python

We’ve got a daily job running to pull WEM adherence reports and drop them into an S3 bucket. The script uses the Python SDK to fetch the data and boto3 to handle the storage part.

The fetch works fine. I can see the JSON payload in memory. The issue is strictly on the upload side. The script gets a 403 Forbidden error when trying to put the object.

Here is the relevant snippet for the S3 part:

import boto3
import json

s3 = boto3.client('s3', region_name='us-east-1')

# data is the response from Genesys API
data_str = json.dumps(data)

try:
 s3.put_object(
 Bucket='our-wem-exports',
 Key=f'adherence/{date_str}/report.json',
 Body=data_str
 )
 print('Upload successful')
except ClientError as e:
 print(f'Error: {e.response["Error"]["Code"]}')

The IAM role attached to the EC2 instance has s3:PutObject permissions for that specific bucket. I verified this by running aws s3 cp from the terminal on the same instance, and that works without issues.

The error message from boto3 is just 403 Forbidden. No specific reason code in the response body.

Is there something specific about how the Python SDK handles the body encoding that might trigger a policy violation? Or is this likely a signature version mismatch?