DEV Community

Cover image for How to Use Murf AI API
Preecha
Preecha

Posted on

How to Use Murf AI API

Murf AI API: A Developer's Guide to Text-to-Speech Integration

Murf AI transforms text into natural-sounding speech with studio-quality voiceovers. Developers integrate the Murf AI API to build applications that narrate content, create audio versions of articles, power virtual assistants, and generate voiceovers at scale.

Try Apidog today

πŸ’‘ Before diving into complex coding, save significant development time by testing and debugging the Murf AI API in Apidog β€” a free, all-in-one API development tool that lets you visually inspect endpoints, generate client code in any language, and verify TTS output instantly without writing a single line of boilerplate code.

What is the Murf AI API?

Murf AI is a cloud-based text-to-speech service that converts written content into realistic, human-like audio. Unlike robotic-sounding TTS engines, Murf uses AI-powered voice synthesis to produce natural intonation, proper emphasis, and authentic emotional expression.

Image

Murf AI Dashboard

The API exposes this functionality to developers. Key capabilities:

  • Voice Library β€” 120+ AI voices across different genders, ages, and accents
  • Multi-language Support β€” generate speech in 20+ languages including English, Spanish, French, German, and Hindi
  • Voice Customization β€” adjust pitch, speed, and emphasis for precise control
  • Multiple Output Formats β€” export audio as MP3, WAV, or FLAC
  • SSML Support β€” fine-tune pronunciation using Speech Synthesis Markup Language

Typical use cases: video narration, podcast production, IVR systems, audiobook generation, and accessibility features. The API handles both short snippets and long-form content.

Getting Started with the Murf AI API

Authentication uses API keys and follows standard REST conventions. Set it up in three steps.

Step 1: Create a Murf AI Account

Visit murf.ai and sign up. The free tier includes limited credits β€” enough for testing the API. Production use requires a paid plan that includes API access.

Image

Murf AI API key create account

Step 2: Generate Your API Key

Open your account settings, locate the API section, and generate a new API key. Store it securely β€” it authenticates every request.

Image

Murf AI API key generation interface

Keep your API key confidential. Never commit it to version control or expose it in client-side code.

Step 3: Use the Base URL

All Murf AI API requests go to:

https://api.murf.ai/v1
Enter fullscreen mode Exit fullscreen mode

The API follows RESTful conventions with JSON request/response bodies. Authentication happens via the api-key header.

Authenticating with the Murf AI API

Every request requires your API key in the headers:

[REDACTED CREDENTIAL]
Content-Type: application/json
Enter fullscreen mode Exit fullscreen mode

Python

import requests

[REDACTED CREDENTIAL]
BASE_URL = "https://api.murf.ai/v1"

headers = {
    [REDACTED CREDENTIAL],
    "Content-Type": "application/json"
}

# Test authentication by fetching available voices
response = requests.get(f"{BASE_URL}/voices", headers=headers)

if response.status_code == 200:
    print("Authentication successful!")
    voices = response.json()
    print(f"Available voices: {len(voices)}")
else:
    print(f"Authentication failed: {response.status_code}")
Enter fullscreen mode Exit fullscreen mode

JavaScript

const [REDACTED CREDENTIAL];
const BASE_URL = 'https://api.murf.ai/v1';

const headers = {
    'api-key': API_KEY,
    'Content-Type': 'application/json'
};

// Test authentication
fetch(`${BASE_URL}/voices`, { headers })
    .then(response => response.json())
    .then(data => console.log('Voices available:', data.length))
    .catch(error => console.error('Auth failed:', error));
Enter fullscreen mode Exit fullscreen mode

cURL

curl -X GET "https://api.murf.ai/v1/voices" \
  -H "[REDACTED CREDENTIAL] \
  -H "Content-Type: application/json"
Enter fullscreen mode Exit fullscreen mode

A successful authentication returns 200. Invalid keys return 401 Unauthorized.

Fetching Available Voices

Before generating speech, retrieve the voice list to pick one that fits your use case. The /voices endpoint returns all accessible voices with their metadata.

List All Voices

import requests

[REDACTED CREDENTIAL]
BASE_URL = "https://api.murf.ai/v1"

headers = {
    [REDACTED CREDENTIAL],
    "Content-Type": "application/json"
}

response = requests.get(f"{BASE_URL}/voices", headers=headers)
voices = response.json()

# Display voice information
for voice in voices[:5]:  # Show first 5 voices
    print(f"Name: {voice['name']}")
    print(f"Voice ID: {voice['voiceId']}")
    print(f"Language: {voice['language']}")
    print(f"Gender: {voice['gender']}")
    print(f"Accent: {voice.get('accent', 'N/A')}")
    print("---")
Enter fullscreen mode Exit fullscreen mode

Each voice in the response includes:

Property Description Example
voiceId Unique identifier for the voice "en-US-marcus"
name Display name of the voice "Marcus"
language Language code "en-US"
gender Voice gender "male" or "female"
accent Regional accent "American", "British"
style Voice style/tone "conversational", "formal"

Filter Voices by Language

# Filter for English voices
english_voices = [v for v in voices if v['language'].startswith('en')]
print(f"English voices available: {len(english_voices)}")

# Filter for Spanish voices
spanish_voices = [v for v in voices if v['language'].startswith('es')]
print(f"Spanish voices available: {len(spanish_voices)}")
Enter fullscreen mode Exit fullscreen mode

Generating Speech from Text

The core endpoint is /speech: it accepts text plus voice parameters and returns an audio file.

Basic Text-to-Speech Request

import requests

[REDACTED CREDENTIAL]
BASE_URL = "https://api.murf.ai/v1"

headers = {
    [REDACTED CREDENTIAL],
    "Content-Type": "application/json"
}

payload = {
    "text": "Welcome to our application. This audio was generated using Murf AI.",
    "voiceId": "en-US-marcus",
    "format": "mp3",
    "sampleRate": 24000
}

response = requests.post(
    f"{BASE_URL}/speech",
    headers=headers,
    json=payload
)

if response.status_code == 200:
    # Save the audio file
    with open("output.mp3", "wb") as f:
        f.write(response.content)
    print("Audio saved to output.mp3")
else:
    print(f"Error: {response.status_code} - {response.text}")
Enter fullscreen mode Exit fullscreen mode

Request Parameters

Parameter Type Required Description
text string Yes The text to convert to speech
voiceId string Yes ID of the voice to use
format string No Output format: mp3, wav, flac (default: mp3)
sampleRate integer No Audio sample rate: 8000, 16000, 24000, 48000
speed float No Speaking speed: 0.5 to 2.0 (default: 1.0)
pitch float No Voice pitch adjustment: -10 to 10

Adjusting Voice Speed and Pitch

payload = {
    "text": "This text is spoken at a slower pace with a lower pitch.",
    "voiceId": "en-US-marcus",
    "format": "mp3",
    "speed": 0.8,    # 80% of normal speed
    "pitch": -2      # Slightly lower pitch
}

response = requests.post(f"{BASE_URL}/speech", headers=headers, json=payload)
Enter fullscreen mode Exit fullscreen mode

Using SSML for Advanced Control

Speech Synthesis Markup Language (SSML) provides fine-grained control over pronunciation, pauses, and emphasis. Murf AI supports SSML tags for professional-grade audio output.

SSML Example

ssml_text = """
<speak>
    Welcome to <emphasis level="strong">Murf AI</emphasis>.
    <break time="500ms"/>
    Our text-to-speech technology creates <prosody rate="slow">natural sounding</prosody> audio.
    <break time="300ms"/>
    The word <phoneme alphabet="ipa" ph="ˈdeΙͺtΙ™">data</phoneme> is pronounced correctly.
</speak>
"""

payload = {
    "text": ssml_text,
    "voiceId": "en-US-julia",
    "format": "mp3",
    "ssml": True  # Enable SSML parsing
}

response = requests.post(f"{BASE_URL}/speech", headers=headers, json=payload)
Enter fullscreen mode Exit fullscreen mode

Common SSML Tags

Tag Purpose Example
<break> Insert pause <break time="500ms"/>
<emphasis> Stress a word <emphasis level="strong">important</emphasis>
<prosody> Adjust rate/pitch <prosody rate="slow">text</prosody>
<phoneme> Custom pronunciation <phoneme alphabet="ipa" ph="...">word</phoneme>
<say-as> Interpret as type <say-as interpret-as="date">2026-01-29</say-as>

Testing the Murf AI API with Apidog

Test your API calls interactively before writing integration code. Apidog provides a visual interface for crafting requests, inspecting responses, and debugging issues.

Image

Apidog interface showing API request configuration

Setting Up Apidog for Murf AI

1. Download and install Apidog β€” it's free and supports Windows, Mac, Linux, and web browsers.

2. Create a new project β€” name it "Murf AI Integration" to keep your endpoints organized.

3. Set up environment variables:

{
    "baseUrl": "https://api.murf.ai/v1",
    [REDACTED CREDENTIAL]
}
Enter fullscreen mode Exit fullscreen mode

Environment variables keep sensitive data separate from request configurations.

4. Create your first request β€” add a POST request with:

  • URL: {{baseUrl}}/speech
  • Headers: [REDACTED CREDENTIAL] andContent-Type: application/json`
  • Body (JSON):

json
{
"text": "Testing Murf AI API with Apidog. This is a sample voiceover.",
"voiceId": "en-US-marcus",
"format": "mp3"
}

5. Send and inspect the response β€” click Send. Apidog displays the response status and headers, and lets you download the generated audio file directly.

Debugging Common Issues with Apidog

Issue How Apidog Helps
401 Unauthorized Check the api-key header in the request inspector
Invalid voiceId Use GET /voices first to verify available IDs
Empty audio response Inspect response headers for error messages
Rate limiting Monitor request history for 429 status codes

Apidog's request history lets you compare successful and failed requests side by side, making debugging straightforward.

Handling Long-Form Content

Murf AI has character limits per request. For articles, blog posts, or book chapters, split text into chunks at sentence boundaries to ensure reliable processing.

Chunking Strategy

`python
import requests

[REDACTED CREDENTIAL]
BASE_URL = "https://api.murf.ai/v1"

headers = {
[REDACTED CREDENTIAL],
"Content-Type": "application/json"
}

def chunk_text(text, max_chars=3000):
"""Split text into chunks at sentence boundaries."""
sentences = text.replace('!', '.').replace('?', '.').split('.')
chunks = []
current_chunk = ""

for sentence in sentences:
    sentence = sentence.strip()
    if not sentence:
        continue

    if len(current_chunk) + len(sentence) + 2 > max_chars:
        chunks.append(current_chunk.strip())
        current_chunk = sentence + ". "
    else:
        current_chunk += sentence + ". "

if current_chunk.strip():
    chunks.append(current_chunk.strip())

return chunks
Enter fullscreen mode Exit fullscreen mode

def generate_long_audio(text, voice_id, output_prefix="output"):
"""Generate audio for long-form content."""
chunks = chunk_text(text)
audio_files = []

for i, chunk in enumerate(chunks):
    payload = {
        "text": chunk,
        "voiceId": voice_id,
        "format": "mp3"
    }

    response = requests.post(
        f"{BASE_URL}/speech",
        headers=headers,
        json=payload
    )

    if response.status_code == 200:
        filename = f"{output_prefix}_{i+1}.mp3"
        with open(filename, "wb") as f:
            f.write(response.content)
        audio_files.append(filename)
        print(f"Generated: {filename}")
    else:
        print(f"Failed chunk {i+1}: {response.status_code}")

return audio_files
Enter fullscreen mode Exit fullscreen mode

Example usage

long_text = """
Your long article or document content goes here.
It can span multiple paragraphs and pages.
The function splits it automatically at sentence boundaries.
"""

audio_files = generate_long_audio(long_text, "en-US-marcus", "article_audio")
print(f"Generated {len(audio_files)} audio files")
`

Concatenating Audio Files

After generating chunks, combine them into a single file with FFmpeg or a Python library such as pydub:

`python
from pydub import AudioSegment

def concatenate_audio(file_list, output_file="final_audio.mp3"):
"""Combine multiple audio files into one."""
combined = AudioSegment.empty()

for filename in file_list:
    audio = AudioSegment.from_mp3(filename)
    combined += audio

combined.export(output_file, format="mp3")
print(f"Combined audio saved to {output_file}")
return output_file
Enter fullscreen mode Exit fullscreen mode

Combine the chunks

concatenate_audio(audio_files, "complete_article.mp3")
`

Error Handling Best Practices

Production applications need robust error handling. Murf AI returns standard HTTP status codes with descriptive error messages.

Common Error Codes

Status Code Meaning Solution
400 Bad Request Check request body format and parameters
401 Unauthorized Verify API key is correct and active
403 Forbidden Check account permissions and plan limits
429 Rate Limited Implement exponential backoff
500 Server Error Retry after a short delay

Robust API Client

`python
import requests
import time
from typing import Optional

class MurfAPIClient:
def init(self, [REDACTED CREDENTIAL]
self.[REDACTED CREDENTIAL]
self.base_url = "https://api.murf.ai/v1"
self.headers = {
[REDACTED CREDENTIAL],
"Content-Type": "application/json"
}

def _request(self, method: str, endpoint: str,
             data: dict = None, retries: int = 3) -> Optional[requests.Response]:
    """Make API request with retry logic."""
    url = f"{self.base_url}/{endpoint}"

    for attempt in range(retries):
        try:
            if method == "GET":
                response = requests.get(url, headers=self.headers)
            else:
                response = requests.post(url, headers=self.headers, json=data)

            if response.status_code == 200:
                return response
            elif response.status_code == 429:
                # Rate limited - wait and retry
                wait_time = 2 ** attempt
                print(f"Rate limited. Waiting {wait_time}s...")
                time.sleep(wait_time)
            elif response.status_code >= 500:
                # Server error - retry
                time.sleep(1)
            else:
                # Client error - don't retry
                print(f"Error {response.status_code}: {response.text}")
                return None

        except requests.RequestException as e:
            print(f"Request failed: {e}")
            time.sleep(1)

    return None

def get_voices(self) -> list:
    """Fetch available voices."""
    response = self._request("GET", "voices")
    return response.json() if response else []

def generate_speech(self, text: str, voice_id: str,
                    format: str = "mp3", **kwargs) -> Optional[bytes]:
    """Generate speech from text."""
    payload = {
        "text": text,
        "voiceId": voice_id,
        "format": format,
        **kwargs
    }
    response = self._request("POST", "speech", payload)
    return response.content if response else None
Enter fullscreen mode Exit fullscreen mode

Usage

client = MurfAPIClient("your_api_key")
voices = client.get_voices()
audio = client.generate_speech(
"Hello world!",
"en-US-marcus",
speed=1.0
)

if audio:
with open("output.mp3", "wb") as f:
f.write(audio)
`

Building a Voiceover Generation Service

Here's a complete Flask API that wraps Murf AI for your applications:

`python
from flask import Flask, request, jsonify, send_file
import requests
import os
import uuid

app = Flask(name)

MURF_API_KEY = os.environ.get("MURF_API_KEY")
MURF_BASE_URL = "https://api.murf.ai/v1"

headers = {
[REDACTED CREDENTIAL],
"Content-Type": "application/json"
}

@app.route("/api/voices", methods=["GET"])
def list_voices():
"""List available voices."""
language = request.args.get("language")

response = requests.get(f"{MURF_BASE_URL}/voices", headers=headers)

if response.status_code != 200:
    return jsonify({"error": "Failed to fetch voices"}), 500

voices = response.json()

if language:
    voices = [v for v in voices if v["language"].startswith(language)]

return jsonify(voices)
Enter fullscreen mode Exit fullscreen mode

@app.route("/api/synthesize", methods=["POST"])
def synthesize():
"""Generate speech from text."""
data = request.json

if not data or "text" not in data:
    return jsonify({"error": "Missing 'text' field"}), 400

if "voiceId" not in data:
    return jsonify({"error": "Missing 'voiceId' field"}), 400

payload = {
    "text": data["text"],
    "voiceId": data["voiceId"],
    "format": data.get("format", "mp3"),
    "speed": data.get("speed", 1.0),
    "pitch": data.get("pitch", 0)
}

response = requests.post(
    f"{MURF_BASE_URL}/speech",
    headers=headers,
    json=payload
)

if response.status_code != 200:
    return jsonify({"error": "Speech generation failed"}), 500

# Save to temp file
filename = f"audio_{uuid.uuid4().hex}.mp3"
filepath = os.path.join("/tmp", filename)

with open(filepath, "wb") as f:
    f.write(response.content)

return send_file(
    filepath,
    mimetype="audio/mpeg",
    as_attachment=True,
    download_name=filename
)
Enter fullscreen mode Exit fullscreen mode

if name == "main":
app.run(debug=True, port=5000)
`

This service exposes two endpoints: one to list voices and another to generate speech. Extend it with caching, authentication, and queue-based processing for production use.

Rate Limits and Pricing Considerations

Murf AI enforces rate limits based on your subscription plan. Understanding these limits helps you design efficient applications.

Image

Murf AI API Pricing

Optimizing API Usage

  • Cache generated audio β€” store results for repeated requests
  • Batch similar requests β€” combine short texts when possible
  • Use lower sample rates β€” 16000 Hz works well for voice content
  • Monitor with Apidog β€” track usage patterns and optimize

Integrating with Popular Frameworks

Node.js

`javascript
const axios = require('axios');
const fs = require('fs');

const [REDACTED CREDENTIAL];
const BASE_URL = 'https://api.murf.ai/v1';

async function generateSpeech(text, voiceId, options = {}) {
try {
const response = await axios.post(
${BASE_URL}/speech,
{
text,
voiceId,
format: options.format || 'mp3',
speed: options.speed || 1.0,
pitch: options.pitch || 0
},
{
headers: {
'api-key': API_KEY,
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
}
);

    return Buffer.from(response.data);
} catch (error) {
    console.error('Error:', error.response?.data || error.message);
    throw error;
}
Enter fullscreen mode Exit fullscreen mode

}

// Usage
(async () => {
const audio = await generateSpeech(
'Hello from Node.js!',
'en-US-marcus'
);

fs.writeFileSync('output.mp3', audio);
console.log('Audio saved!');
Enter fullscreen mode Exit fullscreen mode

})();
`

React Frontend

`jsx
import React, { useState } from 'react';

function VoiceGenerator() {
const [text, setText] = useState('');
const [voiceId, setVoiceId] = useState('en-US-marcus');
const [audioUrl, setAudioUrl] = useState(null);
const [loading, setLoading] = useState(false);

const generateAudio = async () => {
    setLoading(true);

    try {
        const response = await fetch('/api/synthesize', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ text, voiceId })
        });

        const blob = await response.blob();
        const url = URL.createObjectURL(blob);
        setAudioUrl(url);
    } catch (error) {
        console.error('Generation failed:', error);
    } finally {
        setLoading(false);
    }
};

return (
    <div className="voice-generator">
        <textarea
            value={text}
            onChange={(e) => setText(e.target.value)}
            placeholder="Enter text to convert to speech..."
        />

        <select value={voiceId} onChange={(e) => setVoiceId(e.target.value)}>
            <option value="en-US-marcus">Marcus (US Male)</option>
            <option value="en-US-julia">Julia (US Female)</option>
            <option value="en-GB-oliver">Oliver (UK Male)</option>
        </select>

        <button onClick={generateAudio} disabled={loading}>
            {loading ? 'Generating...' : 'Generate Audio'}
        </button>

        {audioUrl && (
            <audio controls src={audioUrl}>
                Your browser does not support audio playback.
            </audio>
        )}
    </div>
);
Enter fullscreen mode Exit fullscreen mode

}

export default VoiceGenerator;
`

Conclusion

The Murf AI API opens up powerful text-to-speech capabilities β€” from simple voiceovers to complex multi-voice productions, with natural-sounding output. Key takeaways:

  • Authentication β€” use API keys in request headers for all calls
  • Voice selection β€” explore 120+ voices across languages and accents
  • Customization β€” adjust speed and pitch, and use SSML for precise control
  • Error handling β€” implement retries and exponential backoff for production
  • Testing β€” use Apidog to debug and optimize your integration

Start with the free tier to experiment, then scale up as your application grows. The combination of high-quality voices and a developer-friendly API design makes Murf AI a solid choice for voice-enabled applications.

Ready to build? Download Apidog to test your Murf AI API calls and streamline your development workflow.

Top comments (0)