Auto Audio API

Automatically convert web content to audio

Transform any article or webpage into high-quality, professionally narrated audio with a single API call.

Overview

The Auto Audio API enables automatic conversion of web articles into high-quality audio content. Simply provide a URL, and the system will extract content, generate professional narration, apply audio mixing, and return an embeddable audio player.

Universal Compatibility

Works with any public URL. Automatic content extraction from any website.

Multi-Language

Automatic language detection with support for 11+ languages.

Audio Mixing

Professional background music, intro/outro support, and audio polish.

Smart Caching

Instant retrieval of previously converted articles with automatic update detection.

Conversation Mode

Multi-voice narration for engaging audio experiences.

CMS Integration

Native support for Fusion, NEXT_DATA, and Brightspot structured data.

Base URL: https://creator.everlit.audio
Quick Start: For step-by-step implementation guides, see Web Integration (websites & CMS) or Mobile Integration (native apps).

Usage

The simplest way to add Everlit Auto Audio to your website is by including a widget container and the JavaScript SDK. The widget will automatically detect content on your page and convert it to audio.

Basic Implementation

Add the following HTML to your page where you want the audio player to appear:

<!-- 1. The widget container -->
<div
  id="everlit-auto-audio-widget"
  data-publication-id="YOUR-PUBLICATION-ID"
  style="height: 136px; width: 100%;"
  hidden
><a href="https://everlit.audio/" rel="nofollow">Listen to this article &mdash; audio by Everlit</a></div>

<!-- 2. The script -->
<script
  defer
  src="https://cdn.everlit.audio/libs/everlitAutoAudio.js"
  type="text/javascript"
></script>

Widget Container

Attribute Required Description
id Yes Must be everlit-auto-audio-widget
data-publication-id Yes Your unique Everlit publication ID (e.g., pblc_abc123xyz)
hidden Recommended Hides the container until audio is ready
style Optional Set dimensions; recommended height is 136px
Fallback link Recommended The link inside the container is never shown to visitors — it is replaced by the player (or stays hidden). It gives non-JavaScript crawlers a text fallback and is automatically excluded from audio conversion.

Script Tag

Attribute Description
defer Loads the script without blocking page rendering
src Always use https://cdn.everlit.audio/libs/everlitAutoAudio.js
That's it! Once added, the widget will automatically detect your page's content, check for existing audio, and display the player when available. The hidden attribute is automatically removed when the player is ready.

How It Works

When the script loads, it will:

  1. Detect the canonical URL of your page
  2. Check if audio already exists for this content
  3. If audio exists, display the embedded player
  4. If not, display a click-to-create widget (if enabled for your publication)
  5. Dispatch JavaScript events for each state change
Need your Publication ID? Contact Everlit support to obtain your credentials.

Authentication

All API requests require authentication using a bearer token:

Authorization: Bearer YOUR_API_TOKEN
Contact Everlit support to obtain API credentials for your publication.

Endpoints

POST /audio/auto POST

POST https://creator.everlit.audio/audio/auto

Initiates audio conversion for a given URL. This endpoint is asynchronous and will either return a completed embed immediately (if cached), indicate processing is in progress, or start a new conversion job.

Request Body

{
  "url": "https://example.com/article",
  "publication_id": "pblc_abc123xyz",
  "conversation_mode": true,
  "sonic_optimizer": true
}

Required Parameters

Parameter Type Description
url string The URL of the article to convert
publication_id string Your publication ID (format: pblc_xxxxx)

Optional Parameters

Parameter Type Default Description
primary_voice_id string pub default Voice ID for primary narrator
guest_voice_id string pub default Voice ID for secondary narrator
conversation_mode boolean false Enable multi-voice conversation mode
sonic_optimizer boolean false Enable Audio Polish for enhanced quality
mix boolean true Apply background music mixing
read_urls boolean false Read URLs found in content aloud
read_alt_text boolean false Read image alt text
intro_mixable_id string null Custom intro audio mixable ID
outro_mixable_id string null Custom outro audio mixable ID
disclaimer string null Disclaimer text to read before content
read_author_in_audio_enabled boolean true Read the author byline aloud in the audio
Full parameter reference: See the complete parameter table for all available options.

Response Examples

{
  "successful": true,
  "embed": "<iframe src=\"https://everlit.audio/embeds/artl_abc123?eut=xyz\" frameborder=\"0\"></iframe>",
  "article_id": "artl_abc123",
  "metadata": {
    "title": "Article Title",
    "summary": "Article summary text",
    "duration": 245.5
  },
  "dom_query_params": null,
  "published_at": "2025-09-29T10:30:00Z",
  "duration": 245.5,
  "title": "Article Title",
  "summary": "Article summary text",
  "authors": ["Author Name"],
  "tags": ["category:News", "author:Author Name", "language:English"],
  "disclaimer_ui_text": "This audio was generated using AI"
}
{
  "successful": true,
  "waiting": true,
  "message": "Everlit audio conversion is still in progress."
}
{
  "successful": false,
  "reason": "Unable to fetch the article content."
}

GET /audio/auto/check GET

GET https://creator.everlit.audio/audio/auto/check?evp=BASE64

Checks the status of audio conversion for a given URL. This is the recommended endpoint for polling conversion status, as it's lightweight and optimized for frequent checks.

Query Parameters

Parameter Type Description
evp string Base64-encoded JSON containing url, publication_id, and optional parameters

EVP Encoding

The evp parameter contains URL-safe base64-encoded JSON:

// Original object
const params = {
  url: "https://example.com/article",
  publication_id: "pblc_abc123xyz",
  eut: "optional_analytics_token"
};

// Encode to URL-safe base64
const evp = btoa(JSON.stringify(params))
  .replace(/\+/g, '-')
  .replace(/\//g, '_')
  .replace(/=/g, '');
Note: GET requests will never initiate a new conversion - they only check existing status.

Code Examples

Complete JavaScript Implementation

async function convertToAudio(url, publicationId) {
  // Check current status
  const params = {
    url: url,
    publication_id: publicationId
  };

  const evp = btoa(JSON.stringify(params))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');

  const checkResponse = await fetch(
    `https://creator.everlit.audio/audio/auto/check?evp=${evp}`
  );
  const checkData = await checkResponse.json();

  if (checkData.embed) {
    return checkData.embed; // Already ready!
  }

  if (checkData.create || checkData.waiting) {
    // Initiate if needed
    if (checkData.create) {
      await fetch('https://creator.everlit.audio/audio/auto', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(params)
      });
    }

    // Poll for completion
    return await pollForCompletion(url, publicationId);
  }
}

async function pollForCompletion(url, publicationId, maxAttempts = 60) {
  for (let i = 0; i < maxAttempts; i++) {
    await new Promise(r => setTimeout(r, 5000)); // Wait 5s

    const params = { url, publication_id: publicationId };
    const evp = btoa(JSON.stringify(params))
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=/g, '');

    const response = await fetch(
      `https://creator.everlit.audio/audio/auto/check?evp=${evp}`
    );
    const data = await response.json();

    if (data.embed) return data.embed;
    if (!data.waiting) throw new Error(data.reason);
  }

  throw new Error('Conversion timeout');
}

// Usage
const embed = await convertToAudio(
  'https://example.com/article',
  'pblc_abc123xyz'
);
document.getElementById('player').innerHTML = embed;

cURL Commands

# Initiate conversion
curl -X POST https://creator.everlit.audio/audio/auto \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
    "url": "https://example.com/article",
    "publication_id": "pblc_abc123xyz",
    "conversation_mode": true,
    "sonic_optimizer": true
  }'

# Check status (encode the parameters first)
EVP=$(echo -n '{"url":"https://example.com/article","publication_id":"pblc_abc123xyz"}' | \
  base64 | tr '+/' '-_' | tr -d '=')

curl "https://creator.everlit.audio/audio/auto/check?evp=$EVP"

Python Implementation

import requests
import json
import base64
import time

class EverlitAutoAudio:
    BASE_URL = 'https://creator.everlit.audio'

    def __init__(self, publication_id, api_token=None):
        self.publication_id = publication_id
        self.api_token = api_token

    def convert_article(self, url, **options):
        # Check status
        status = self.check_status(url)
        if status.get('embed'):
            return status['embed']

        # Initiate if needed
        if status.get('create'):
            self.initiate_conversion(url, **options)

        # Poll for completion
        return self.poll_for_completion(url)

    def check_status(self, url):
        params = {'url': url, 'publication_id': self.publication_id}
        evp = base64.urlsafe_b64encode(
            json.dumps(params).encode()
        ).decode().rstrip('=')

        response = requests.get(
            f'{self.BASE_URL}/audio/auto/check',
            params={'evp': evp}
        )
        return response.json()

    def initiate_conversion(self, url, **options):
        headers = {'Content-Type': 'application/json'}
        if self.api_token:
            headers['Authorization'] = f'Bearer {self.api_token}'

        payload = {
            'url': url,
            'publication_id': self.publication_id,
            **options
        }

        response = requests.post(
            f'{self.BASE_URL}/audio/auto',
            headers=headers,
            json=payload
        )
        return response.json()

    def poll_for_completion(self, url, max_attempts=60):
        for _ in range(max_attempts):
            time.sleep(5)
            status = self.check_status(url)
            if status.get('embed'):
                return status['embed']
        raise Exception('Conversion timeout')

# Usage
client = EverlitAutoAudio('pblc_abc123xyz', 'your_token')
embed = client.convert_article(
    'https://example.com/article',
    conversation_mode=True,
    sonic_optimizer=True
)
print(embed)

Ruby Implementation

require 'net/http'
require 'json'
require 'base64'

class EverlitAutoAudio
  BASE_URL = 'https://creator.everlit.audio'

  def initialize(publication_id, api_token = nil)
    @publication_id = publication_id
    @api_token = api_token
  end

  def convert_article(url, options = {})
    status = check_status(url)
    return status[:embed] if status[:embed]

    initiate_conversion(url, options) if status[:create]
    poll_for_completion(url)
  end

  def check_status(url)
    params = { url: url, publication_id: @publication_id }
    evp = Base64.urlsafe_encode64(params.to_json, padding: false)

    uri = URI("#{BASE_URL}/audio/auto/check?evp=#{evp}")
    response = Net::HTTP.get_response(uri)
    JSON.parse(response.body, symbolize_names: true)
  end

  def initiate_conversion(url, options = {})
    uri = URI("#{BASE_URL}/audio/auto")
    request = Net::HTTP::Post.new(uri)
    request['Content-Type'] = 'application/json'
    request['Authorization'] = "Bearer #{@api_token}" if @api_token

    body = { url: url, publication_id: @publication_id }.merge(options)
    request.body = body.to_json

    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end

    JSON.parse(response.body, symbolize_names: true)
  end

  def poll_for_completion(url, max_attempts = 60)
    max_attempts.times do
      sleep(5)
      status = check_status(url)
      return status[:embed] if status[:embed]
    end
    raise "Conversion timeout"
  end
end

# Usage
client = EverlitAutoAudio.new('pblc_abc123xyz', 'your_token')
embed = client.convert_article(
  'https://example.com/article',
  conversation_mode: true,
  sonic_optimizer: true
)
puts embed

Error Handling

Common Error Scenarios

Scenario Response Action
Missing URL {"successful": false, "message": "No URL was sent..."} Provide valid URL parameter
Rate Limited {"successful": true, "reason": "Everlit is already hard at work..."} Wait 30+ seconds and retry
URL Blocked {"successful": false, "reason": "This URL is not available..."} Check whitelist settings
Monthly Limit 403: {"error": "Monthly article limit reached"} Upgrade plan or wait for reset
Invalid Voice {"successful": false, "reason": "Invalid parameters: voice_id..."} Use valid voice ID for your publisher
Extraction Failed {"successful": false, "reason": "Unable to fetch article..."} Check URL accessibility and format

Retry Strategy

Recommended: Implement exponential backoff for transient errors (5s, 10s, 20s, 40s) with max 5 attempts.
async function withRetry(fn, maxRetries = 5) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === maxRetries - 1) throw error;

      const delay = Math.pow(2, i) * 1000; // Exponential backoff
      await new Promise(r => setTimeout(r, delay));
    }
  }
}

Complete Parameter Reference

Parameter Type Required Default Description
url string Yes - Article URL to convert
publication_id string Yes - Your publication ID
eut string No auto Analytics tracking token
primary_voice_id string No pub setting Primary narrator voice ID
guest_voice_id string No pub setting Secondary narrator voice ID
conversation_mode boolean No false Enable multi-voice mode
read_urls boolean No false Read URLs aloud
read_alt_text boolean No false Read image alt text
sonic_optimizer boolean No false Enable Audio Polish
optimizer_level string No default "light", "default", "heavy"
mix boolean No true Apply audio mixing
intro_mixable_id string No null Custom intro audio ID
outro_mixable_id string No null Custom outro audio ID
intro_duration integer No 0 Intro length (seconds)
outro_duration integer No 0 Outro length (seconds)
intro_pad integer No 0 Intro padding (seconds)
outro_pad integer No 0 Outro padding (seconds)
disclaimer string No null Disclaimer text
disclaimer_voice_id string No null Disclaimer voice ID
read_author_in_audio_enabled boolean No true Read author byline aloud
disable_language_detection boolean No false Disable auto voice selection
click_to_create boolean No false From click widget
content_last_published_timestamp integer No null Unix timestamp (ms)
dom_content string No null Raw page HTML for content extraction
rendered_html string No null Rendered HTML for media extraction
page_url string No null Page URL for syndicated content

Server-Side Content Ingestion

If your system already has the article content (for example, a headless CMS or a feed ingestion pipeline), you can supply it directly in the POST /audio/auto body instead of relying on automatic content extraction. This produces deterministic audio that does not depend on the quality of server-side scraping.

Server-to-server only. This path is intended for authenticated backend integrations and requires a valid bearer token (see Authentication). Do not send article bodies from browser/widget code — the JavaScript widget should send the page URL (and optional structured data) instead.

Modes of Operation

  • Full override (scraping skipped): when the body contains both text and title, the system uses your content verbatim and does not fetch or scrape the page. The url is still required, but only as the canonical identifier and cache key.
  • Per-field override (scraping fills the gaps): if you provide some content fields but omit text or title (and send no structured data), the page is scraped and your supplied fields take precedence — extraction fills only the fields you leave blank. For example, send only text to replace the article body while letting extraction supply the title, image, and byline.

Ingestion Parameters

Parameter Type Description
text string Article body to narrate. With title, fully replaces content extraction.
title string Article headline. With text, fully replaces content extraction.
authors array of strings Author bylines. Normalized, read aloud in the narration, and added as author: tags.
custom_byline string Exact byline text to read aloud, overriding the auto-generated author string.
summary string Article summary / description.
category string Single section/category. Added as a category: tag.
art_url string URL of the article's artwork/featured image.
published_at string Publication timestamp (ISO 8601). Used for deduplication and update detection.
tags array of strings Additional pass-through tags (e.g., stock tickers).

Example (Full Override)

curl -X POST https://creator.everlit.audio/audio/auto \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
    "url": "https://example.com/article",
    "publication_id": "pblc_abc123xyz",
    "title": "City Council Approves New Transportation Plan",
    "text": "The city council voted 7-2 on Tuesday to approve a comprehensive transportation plan...",
    "authors": ["Jane Doe", "John Smith"],
    "summary": "A comprehensive look at the new transportation plan.",
    "category": "Local News",
    "art_url": "https://example.com/images/council.jpg",
    "published_at": "2026-05-29T10:30:00Z",
    "tags": ["transportation", "city-council"]
  }'
Note: When content is supplied this way, all other generation options (voice selection, mixing, disclaimer, conversation mode, etc.) behave exactly as they do for URL-based conversions.

JavaScript Events

The Auto Audio widget emits custom DOM events that allow you to react to various states of the audio player lifecycle. These events are useful for showing/hiding related UI elements, tracking analytics, or integrating with your page's behavior.

Available Events

Event Name When Fired Use Case
everlit:ready Audio player iframe is successfully embedded Show related UI elements, display duration
everlit:clickToCreate Click-to-create widget is displayed Show hints or call-to-action elements
everlit:processing Audio conversion has started Show loading indicators
everlit:error An error occurred during check or conversion Display error messages, hide player area

Event Details

everlit:ready

Fired when the audio player is successfully embedded on the page. This is the primary event for most integrations.

Event Detail Properties
Property Type Description
embed boolean Always true for this event
element HTMLElement The container element holding the audio player iframe
articleId string | null The Everlit article ID (e.g., "artl_abc123")
metadata object | null Article metadata object (see below)
Metadata Object
Property Type Example Description
title string "Breaking: Major Event Unfolds" The article title
summary string "A brief overview of the article content..." AI-generated summary of the article
duration number 245.5 Audio duration in seconds
Example Response
// Example e.detail value:
{
  embed: true,
  element: HTMLDivElement,
  articleId: "artl_7kX9mPqR2Nw",
  metadata: {
    title: "City Council Approves New Transportation Plan",
    summary: "The city council voted 7-2 to approve a comprehensive transportation plan that includes new bike lanes, expanded bus routes, and infrastructure improvements.",
    duration: 187.3
  }
}
Usage Example
document.addEventListener('everlit:ready', function(e) {
  console.log('Audio player ready!', e.detail);

  // Show a related element
  document.querySelector('.audio-controls').style.display = 'block';

  // Display formatted duration
  if (e.detail.metadata?.duration) {
    const minutes = Math.round(e.detail.metadata.duration / 60);
    document.querySelector('.listen-time').textContent = minutes + ' min listen';
  }

  // Display title
  if (e.detail.metadata?.title) {
    document.querySelector('.audio-title').textContent = e.detail.metadata.title;
  }
});

everlit:clickToCreate

Fired when a click-to-create widget is displayed (for publications with on-demand audio generation).

document.addEventListener('everlit:clickToCreate', function(e) {
  // e.detail contains:
  // {
  //   clickToCreate: true,
  //   processing: false,        // true if already being created
  //   element: HTMLElement      // The click widget element
  // }

  if (!e.detail.processing) {
    // Show a hint to encourage users to click
    document.querySelector('.create-audio-hint').style.display = 'block';
  }
});

everlit:processing

Fired when audio conversion begins (after user clicks to create or auto-conversion starts).

document.addEventListener('everlit:processing', function(e) {
  // e.detail contains:
  // {
  //   processing: true,
  //   url: "https://example.com/article"
  // }

  // Show a loading state
  document.querySelector('.audio-loading').style.display = 'block';
});

everlit:error

Fired when an error occurs during the audio check or conversion process.

document.addEventListener('everlit:error', function(e) {
  // e.detail contains:
  // {
  //   error: true,
  //   reason: "Error description"
  // }

  console.error('Everlit error:', e.detail.reason);

  // Optionally hide the player area on error
  document.querySelector('.audio-player-container').style.display = 'none';
});

Complete Integration Example

Here's a full example showing how to use events to control page elements based on audio availability:

<!-- Your page HTML -->
<div id="everlit-auto-audio-widget" data-publication-id="pblc_xxx"></div>

<div class="audio-info" style="display: none;">
  <span class="listen-time"></span>
  <button class="share-audio-btn">Share Audio</button>
</div>

<script src="https://cdn.everlit.audio/everlitAutoAudio.min.js"></script>
<script>
  // Show audio info when player is ready
  document.addEventListener('everlit:ready', function(e) {
    const audioInfo = document.querySelector('.audio-info');
    audioInfo.style.display = 'flex';

    // Display duration
    if (e.detail.metadata?.duration) {
      const minutes = Math.round(e.detail.metadata.duration / 60);
      document.querySelector('.listen-time').textContent = minutes + ' min listen';
    }

    // Log for analytics
    console.log('Audio loaded for article:', e.detail.articleId);
  });

  // Hide audio info on error
  document.addEventListener('everlit:error', function(e) {
    document.querySelector('.audio-info').style.display = 'none';
  });
</script>
Note: Events are dispatched on the document object and bubble up, so you can listen for them anywhere in your page.

Best Practices

Widget Placement

  • Place the widget container early in your article template for best visibility
  • Use the hidden attribute to prevent layout shifts before audio loads
  • Set a fixed height (136px recommended) to reserve space for the player

Performance Tips

  • Use the defer attribute on the script tag to avoid blocking page load
  • The widget automatically caches results - repeated page loads are instant
  • Consider using the JavaScript events to lazy-load related UI elements

Content Optimization

  • Ensure your pages have a valid canonical URL for consistent audio matching
  • Use semantic HTML to help content extraction identify article body text
  • Include proper meta tags (title, description, author) for better audio metadata

Error Handling

  • Listen for the everlit:error event to gracefully handle failures
  • Implement retry logic with exponential backoff for transient errors
  • Use the check endpoint for status polling rather than repeatedly calling the POST endpoint
Pro tip: Combine the everlit:ready event with your analytics to track audio engagement alongside article pageviews.

Support & Resources

Technical Support

support@everlit.audio

Mobile / WebView Integration

View Documentation