How to Use Murf AI API

This guide walks you through everything from authentication to generating your first voiceover. By the end, you'll have a working integration that converts text to speech programmatically.

Herve Kom

29 January 2026

How to Use Murf AI API

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.

💡
Before diving into complex coding, you can save significant development time by using Apidog to test and debug the Murf AI API. Apidog is a free, all-in-one API development tool that lets you visually inspect endpoints, generate client code in any language, and verify TTS outputs instantly without writing a single line of boilerplate code.
button

What is Murf AI API?

Murf AI provides 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.

Murf AI Dashboard

The API exposes this functionality for developers. Key capabilities include:

Developers use Murf AI API for video narration, podcast production, IVR systems, audiobook generation, and accessibility features. The API handles both short snippets and long-form content, making it suitable for diverse use cases.

Getting Started with Murf AI API

Before making API calls, you need to set up authentication. Murf AI uses API keys for authorization, following standard REST conventions.

Step 1: Create a Murf AI Account

Visit murf.ai and sign up for an account. Murf offers a free tier with limited credits, which works well for testing the API. For production use, you'll need a paid plan that includes API access.

Murf AI API key create account

Step 2: Generate Your Murf AI API Key

Navigate to your account settings and locate the API section. Generate a new API key and store it securely. This key authenticates all your requests.

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: Understand the Murf AI API Base URL

All Murf AI API requests go to:

https://api.murf.ai/v1

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

Murf AI API Authentication

Every API request requires your API key in the request headers. The authentication header format is:

api-key: YOUR_API_KEY
Content-Type: application/json

Here's how authentication looks in different programming languages:

Python Authentication with Murf AI API

import requests

API_KEY = "your_murf_api_key"
BASE_URL = "https://api.murf.ai/v1"

headers = {
    "api-key": API_KEY,
    "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}")

JavaScript Authentication with Murf AI API

const API_KEY = 'your_murf_api_key';
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));

cURL Authentication with Murf AI API

curl -X GET "https://api.murf.ai/v1/voices" \
  -H "api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json"

A successful authentication returns a 200 status code. Invalid keys return 401 Unauthorized.

Fetching Available Voices with Murf AI API

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

List All Voices

import requests

API_KEY = "your_murf_api_key"
BASE_URL = "https://api.murf.ai/v1"

headers = {
    "api-key": API_KEY,
    "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("---")

The response includes voice properties:

PropertyDescriptionExample
voiceIdUnique identifier for the voice"en-US-marcus"
nameDisplay name of the voice"Marcus"
languageLanguage code"en-US"
genderVoice gender"male" or "female"
accentRegional accent"American", "British"
styleVoice 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)}")

Generating Speech from Text

The core functionality of Murf AI API is converting text to speech. The /speech endpoint accepts text and voice parameters, returning an audio file.

Basic Text-to-Speech Request

import requests

API_KEY = "your_murf_api_key"
BASE_URL = "https://api.murf.ai/v1"

headers = {
    "api-key": API_KEY,
    "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}")

Request Parameters

ParameterTypeRequiredDescription
textstringYesThe text to convert to speech
voiceIdstringYesID of the voice to use
formatstringNoOutput format: mp3, wav, flac (default: mp3)
sampleRateintegerNoAudio sample rate: 8000, 16000, 24000, 48000
speedfloatNoSpeaking speed: 0.5 to 2.0 (default: 1.0)
pitchfloatNoVoice 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)

Using SSML for Advanced Control

Speech Synthesis Markup Language (SSML) provides fine-grained control over pronunciation, pauses, emphasis, and more. Murf AI API 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)

Common SSML Tags

TagPurposeExample
<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 Murf AI API with Apidog

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

Apidog interface showing API request configuration

Setting Up Apidog for Murf AI

1. Download and Install Apidog

Get Apidog for free. It supports Windows, Mac, Linux, and web browsers.

button

2. Create a New Project

Start a new project named "Murf AI Integration". This keeps your API endpoints organized.

3. Set Up Environment Variables

Create an environment with your API key:

{
    "baseUrl": "https://api.murf.ai/v1",
    "apiKey": "your_murf_api_key"
}

Environment variables keep sensitive data separate from request configurations.

4. Create Your First Request

Add a new POST request with these settings:

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

5. Send and Inspect Response

Click Send. Apidog displays the response status, headers, and allows you to download the generated audio file directly.

Debugging Common Issues with Apidog

IssueHow Apidog Helps
401 UnauthorizedCheck the api-key header in request inspector
Invalid voiceIdUse GET /voices first to verify available IDs
Empty audio responseInspect response headers for error messages
Rate limitingMonitor request history for 429 status codes

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

Handling Long-Form Content with Murf AI API

For articles, blog posts, or book chapters, you may need to process text in chunks. Murf AI has character limits per request, so splitting content ensures reliable processing.

Chunking Strategy

import requests

API_KEY = "your_murf_api_key"
BASE_URL = "https://api.murf.ai/v1"

headers = {
    "api-key": API_KEY,
    "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

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

# 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 with Murf AI API

After generating chunks, combine them into a single file using FFmpeg or a Python library:

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

# Combine the chunks
concatenate_audio(audio_files, "complete_article.mp3")

Error Handling Best Practices with Murf AI API

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

Common Error Codes

Status CodeMeaningSolution
400Bad RequestCheck request body format and parameters
401UnauthorizedVerify API key is correct and active
403ForbiddenCheck account permissions and plan limits
429Rate LimitedImplement exponential backoff
500Server ErrorRetry after a short delay

Robust API Client

import requests
import time
from typing import Optional

class MurfAPIClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://api.murf.ai/v1"
        self.headers = {
            "api-key": api_key,
            "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

# 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

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

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 = {
    "api-key": MURF_API_KEY,
    "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)

@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
    )

if __name__ == "__main__":
    app.run(debug=True, port=5000)

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

Rate Limits and Pricing Considerations for Murf AI API

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

Murf AI API Pricing 

Optimizing API Usage

Node.js Integration

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

const API_KEY = process.env.MURF_API_KEY;
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;
    }
}

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

    fs.writeFileSync('output.mp3', audio);
    console.log('Audio saved!');
})();

React Frontend Integration

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>
    );
}

export default VoiceGenerator;

Conclusion

The Murf AI API opens up powerful text-to-speech capabilities for developers. From simple voiceovers to complex multi-voice productions, the API handles diverse requirements with natural-sounding output. Key takeaways:

Start with the free tier to experiment, then scale up as your application grows. The combination of high-quality voices and 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.

button

Explore more

How to Use ElevenLabs API

How to Use ElevenLabs API

Learn how to use ElevenLabs API for text-to-speech, voice cloning, and audio generation. Python & JavaScript examples included. Test your API with Apidog free.

29 January 2026

How to Run Kimi K2.5 Locally?

How to Run Kimi K2.5 Locally?

Learn how to run the massive 1T parameter Kimi K2.5 model locally using llama.cpp and Unsloth GGUF. Detailed hardware requirements, installation steps, and Apidog integration guide

29 January 2026

How to Test Localhost APIs with Webhook Services ?

How to Test Localhost APIs with Webhook Services ?

Learn how to test localhost APIs with webhook tunneling services like ngrok, NPort, and Cloudflare Tunnel. Complete guide with Apidog integration for testing webhooks, OAuth callbacks, and third-party integrations

28 January 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs