Create Survey Template ====================== +-----------------------------------------------------------------------+-----------------------------------------------+-----------------+ | URL | Required Values | HTTP Methods | +=======================================================================+===============================================+=================+ | https://app.tingting.io/api/v1/survey-templates/ | name, voice, content | POST | +-----------------------------------------------------------------------+-----------------------------------------------+-----------------+ Creates a new survey template. Supports both ``multipart/form-data`` (for file uploads) and ``application/json``. **Step Object fields (inside** ``content`` **):** +---------------+-------------------+----------+---------------------------------------------------------------------+ | Field | Type | Required | Description | +===============+===================+==========+=====================================================================+ | order | integer (>= 0) | Yes | Step execution order. Must be unique within a template. | +---------------+-------------------+----------+---------------------------------------------------------------------+ | content_type | string | Yes | One of: ``say``, ``play``, ``info`` | +---------------+-------------------+----------+---------------------------------------------------------------------+ | response_type | string | No | One of: ``dtmf``, ``raw_record``, ``none`` | +---------------+-------------------+----------+---------------------------------------------------------------------+ | input_name | string (max 128) | No | Variable name to store the response. Falls back to ``field_name``. | +---------------+-------------------+----------+---------------------------------------------------------------------+ | field_name | string (max 128) | No | Alias for ``input_name``. Used if ``input_name`` is absent. | +---------------+-------------------+----------+---------------------------------------------------------------------+ | audio_file | string or null | No | Absolute URL (downloaded by server) or local file upload. | +---------------+-------------------+----------+---------------------------------------------------------------------+ Scenario A — JSON body, no audio files --------------------------------------- Sample Input: .. code-block:: json { "name": "Simple DTMF Survey", "voice": { "voice_internal_name": "np_rijan" }, "length_factor": "1.00", "content": [ { "order": 0, "content_type": "say", "response_type": "dtmf", "input_name": "rating" }, { "order": 1, "content_type": "info", "response_type": "none", "input_name": "outro" } ] } Sample Response (201 Created): .. code-block:: json { "id": 3, "name": "Simple DTMF Survey", "voice": { "id": 5, "voice_display_name": "Rijan", "voice_internal_name": "np_rijan", "is_premium": false, "is_beta": false }, "length_factor": "1.00", "content": [ { "order": 0, "content_type": "say", "response_type": "dtmf", "input_name": "rating", "audio_file": null }, { "order": 1, "content_type": "info", "response_type": "none", "input_name": "outro", "audio_file": null } ], "created_at": "2026-06-02T12:00:00Z" } Scenario B — Multipart form with uploaded audio files ------------------------------------------------------ Audio file field name conventions (higher priority wins for the same step): +----------+-------------------------------+----------------------------------------------+ | Priority | Field name | Description | +==========+===============================+==============================================+ | High | ``step__audio_file`` | ```` is the step's ``order`` value | +----------+-------------------------------+----------------------------------------------+ | Medium | ``content[][audio_file]`` | ```` is the 0-based index in the array | +----------+-------------------------------+----------------------------------------------+ | Low | ``step__audio_file`` | ```` is the 0-based array index | +----------+-------------------------------+----------------------------------------------+ Sample Request (multipart/form-data): .. code-block:: text POST /api/v1/survey-templates/ Content-Type: multipart/form-data Authorization: Token name=Voice Survey voice={"voice_internal_name":"np_rijan"} length_factor=1.2 content=[{"order":0,"content_type":"play","response_type":"raw_record","input_name":"feedback"}] step_0_audio_file= Sample Response (201 Created): .. code-block:: json { "id": 4, "name": "Voice Survey", "voice": { "id": 5, "voice_display_name": "Rijan", "voice_internal_name": "np_rijan", "is_premium": false, "is_beta": false }, "length_factor": "1.20", "content": [ { "order": 0, "content_type": "play", "response_type": "raw_record", "input_name": "feedback", "audio_file": "https://example.com/media/survey_templates/audio/step_0_9f3e21ab.mp3" } ], "created_at": "2026-06-02T12:05:00Z" } Scenario C — JSON body with audio file URL (server downloads it) ----------------------------------------------------------------- Sample Input: .. code-block:: json { "name": "Pre-recorded Survey", "voice": { "voice_internal_name": "np_rijan" }, "content": [ { "order": 0, "content_type": "play", "response_type": "dtmf", "input_name": "choice", "audio_file": "https://cdn.example.com/audio/intro.mp3" } ] } The server downloads the provided URL, stores the file, and returns an absolute media URL in the response. **Error Responses (400 Bad Request):** Missing voice on create: .. code-block:: json { "voice": "Voice is required." } Voice language mismatch: .. code-block:: json { "voice": "This voice belongs to the 'si' language but your account language is 'np'. Please select a voice that matches your language." } Invalid content structure: .. code-block:: json { "content": [ "Step 0 (order=0): content_type must be one of: ['say', 'play', 'info']", "Step 1 (order=1): duplicate order" ] }