[BUG] Content API bindings expect underscores, but the API expects slashes
Open
Nobody has claimed this yet.
type: bug
- Dominant language
- Python
- Stars
- 2.1k
- Forks
- 815
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 2
Description
Describe the bug
Creating content templates via rest endpoints works, doesn't work in the bindings
The example below demonstrates each step
Code snippet
import json
import requests # install it
from twilio.rest import Client
# Hardcoded credentials for reproduction (replace with test credentials as needed)
TWILIO_ACCOUNT_SID = "DONT_FORGET_THIS_ONE"
TWILIO_AUTH_TOKEN = "DONT_FORGET_THIS_ONE"
def sdk_attempt_create_delete():
print("=== SDK attempt (expected to fail) ===")
client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
cl = client.content.v1.contents
try:
types = cl.Types({'twilio_text': cl.TwilioText({'body': 'Hi {{1}}'})})
req = cl.ContentCreateRequest({'friendly_name': 'sdk_bug_demo', 'language': 'en', 'types': types})
# Observe what the SDK will send
try:
print('SDK types to_dict:', types.to_dict())
except Exception:
pass
content = cl.create(req)
print('SDK CREATED_SID', content.sid)
# cleanup
client.content.v1.contents(content.sid).delete()
print('SDK DELETED')
except Exception as e:
print('SDK CREATE_ERR', e)
def manual_http_create_delete():
print("=== Manual HTTP (expected to succeed) ===")
url = 'https://content.twilio.com/v1/Content'
payload = {
'friendly_name': 'manual_http_demo',
'language': 'en',
'types': {
'twilio/text': {'body': 'Hi {{1}}'}
}
}
print('HTTP payload:', json.dumps(payload))
resp = requests.post(url, json=payload, auth=(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN), timeout=30)
print('HTTP STATUS', resp.status_code)
print('HTTP BODY', resp.text)
resp.raise_for_status()
sid = resp.json().get('sid')
print('HTTP CREATED_SID', sid)
# cleanup
del_resp = requests.delete(f'{url}/{sid}', auth=(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN), timeout=30)
print('HTTP DELETE STATUS', del_resp.status_code)
if __name__ == '__main__':
sdk_attempt_create_delete() # fail
manual_http_create_delete() # success
Actual behavior
Bindings fail, API succeeds, logs here
=== SDK attempt (expected to fail) ===
2 │ SDK types to_dict: {'twilio_text': {'body': 'Hi {{1}}'}, 'twilio_media': None, 'twilio_location': No
│ ne, 'twilio_list_picker': None, 'twilio_call_to_action': None, 'twilio_quick_reply': None, 'twilio_c
│ ard': None, 'twilio_catalog': None, 'twilio_carousel': None, 'twilio_flows': None, 'whatsapp_card':
│ None, 'whatsapp_authentication': None}
3 │ SDK CREATE_ERR HTTP 400 error: Unable to create record: Invalid types. At least one content type def
│ inition is required
4 │ === Manual HTTP (expected to succeed) ===
5 │ HTTP payload: {"friendly_name": "manual_http_demo", "language": "en", "types": {"twilio/text": {"bod
│ y": "Hi {{1}}"}}}
6 │ HTTP STATUS 201
7 │ HTTP BODY {"account_sid": "CENSORED", "date_created": "2025-08-29T00:02:13
│ Z", "date_updated": "2025-08-29T00:02:13Z", "friendly_name": "manual_http_demo", "language": "en", "
│ links": {"approval_create": "https://content.twilio.com/v1/Content/HX3089b50716f1bb4a5415919ef2788bf
│ 3/ApprovalRequests/whatsapp", "approval_fetch": "https://content.twilio.com/v1/Content/HX3089b50716f
│ 1bb4a5415919ef2788bf3/ApprovalRequests"}, "sid": "CENSORED", "types": {"tw
│ ilio/text": {"body": "Hi {{1}}"}}, "url": "https://content.twilio.com/v1/Content/HX3089b50716f1bb4a5
│ 415919ef2788bf3", "variables": { }}
8 │ HTTP CREATED_SID CENSORED
9 │ HTTP DELETE STATUS 204
Expected behavior
The bindings should work exactly as the API
twilio-python version
9.7.2
Python version
3.11.11
Logs or error messages
No response
Additional context
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Python client entry point shown in the report, client.content.v1.contents, and inspect how Types.to_dict() serializes content type keys. Compare the SDK output with the successful manual request using twilio/text; done means SDK creation accepts the slash-form key and the regression is covered by an appropriate test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100