Skip to content

[BUG] Content API bindings expect underscores, but the API expects slashes #881

@LeOndaz

Description

@LeOndaz

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: bugbug in the library

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions