On this pageShow

Addon Developer Guide

Build addons that extend Auddio with new audiobook sources, indexers, and debrid streaming providers. An addon is a lightweight HTTP microservice that provides search results, cache checking, catalog browsing, and stream URLs. Auddio handles the rest — playback, chapter navigation, lock screen controls, offline downloads, and library sync.

TypeScript SDK v1.0.1 (Bun & Node)
Protocol v1.0.0
GitHub SDK Repo API Reference Quick Start →

How It Works

Auddio addons operate over a decentralized, open JSON-over-HTTP protocol. You can write your addon in any backend runtime — TypeScript/Bun, Node.js, Python, Go, or Rust. The client communicates with your server using standard REST endpoints:

Endpoint Method Required Purpose
/manifest.json GET Yes Declares addon identity, version, capabilities, and dynamic settings form.
/search POST Yes* Searches trackers for candidate audiobooks matching title, author, or IDs.
/check-cache POST No Verifies instant availability of torrent infoHashes on the user's Debrid provider.
/resolve POST Yes* Resolves infoHashes into streamable audio URLs via our 2-step selection flow.
/progress/:torrentId GET No Monitors active background downloading on debrid for uncached torrents.
/info POST No Returns raw internal file layout and chapter groupings from public torrent caches.
/airlock POST No Toggles permanent cloud caching on TorBox debrid to prevent inactivity expiry.
/catalog/filters GET / POST No Discovers available categories (e.g. Fiction) and genres (e.g. Sci-Fi) for browsing.
/catalog POST / GET No Returns paginated book collections filtered by category, genre, and sorting.

* Required depending on addon type: SCRAPER requires /search; DEBRID requires /check-cache and /resolve; UNIFIED implements both.

Zero Client Hardcoding: Auddio builds settings forms dynamically based on your manifest's config.fields declaration. When users install your addon URL, the mobile app creates the input UI, collects their API keys or custom proxy hosts, and includes those values in subsequent API requests automatically.

Quick Start

Developing an addon involves building an HTTP server that answers requests according to the protocol specification.

1. Create the Manifest (GET /manifest.json)

Your server must expose a manifest at /manifest.json describing its identity, capabilities, and settings requirements:

JSON
{
  "id": "com.example.my-audiobook-source",
  "name": "My Audiobook Source",
  "version": "1.0.0",
  "description": "Searches public audiobook trackers and streams via debrid",
  "type": "UNIFIED",
  "capabilities": ["SEARCH", "CHECK_CACHE", "RESOLVE", "PROGRESS", "CATALOG"],
  "icon": "https://example.com/icon.png",
  "config": {
    "fields": [
      {
        "id": "debrid_provider",
        "label": "Debrid Provider",
        "type": "dropdown",
        "required": true,
        "default": "realdebrid",
        "options": [
          { "value": "realdebrid", "label": "Real-Debrid" },
          { "value": "alldebrid", "label": "AllDebrid" }
        ]
      },
      {
        "id": "debrid_api_key",
        "label": "Debrid API Key",
        "type": "password",
        "required": true,
        "placeholder": "Enter your debrid token...",
        "help": "Acquire from your provider account settings"
      }
    ]
  }
}

Manifest Fields Reference

Field Type Required Description
id String Yes Unique reverse-domain identifier (e.g. com.yourname.addon).
name String Yes Display name shown in Auddio search dropdowns and addon manager.
version String Yes Semver version string (e.g. 1.0.0).
type String Yes Operational mode: "UNIFIED", "SCRAPER", or "DEBRID".
capabilities Array Yes Declared features: "SEARCH", "CHECK_CACHE", "RESOLVE", "PROGRESS", "INFO", "CATALOG".
icon String No Direct HTTPS URL to a square PNG/JPEG (recommended 128×128).
config Object No Declares dynamic form inputs collected by client apps upon installation.

Called when the user searches for an audiobook or when Auddio searches candidate sources for a book detail page:

Request Body
{
  "title": "Dune",
  "author": "Frank Herbert",
  "limit": 10
}

Respond with a list of candidate results matching the query:

Response JSON
{
  "results": [
    {
      "infoHash": "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
      "title": "Dune (Frank Herbert) [MP3@64kbps]",
      "author": "Frank Herbert",
      "narrator": "George Guidall",
      "size": 322485640,
      "sizeFormatted": "307.54 MiB",
      "seeders": 42,
      "leechers": 3,
      "source": "AudioBookBay",
      "format": "MP3",
      "bitrate": "64kbps"
    }
  ],
  "total": 1,
  "query": { "title": "Dune" }
}

3. Implement Cache Checking (POST /check-cache)

Before initiating streams, Auddio asks your addon if any candidate hashes are already cached on the user's debrid cloud for instant playback with zero waiting:

Request Body
{
  "provider": "realdebrid",
  "apiKey": "USER_DEBRID_TOKEN",
  "infoHashes": [
    "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
    "b8c321e1a49c23b8fca8e4f5a112f45c99182b8a"
  ]
}
Response JSON
{
  "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f": {
    "cached": true,
    "torrentId": "rd_torrent_9821a"
  },
  "b8c321e1a49c23b8fca8e4f5a112f45c99182b8a": {
    "cached": false
  }
}

4. Stream Resolution & Two-Step Selection Flow (POST /resolve)

Audiobooks frequently contain dozens of individual chapter MP3s alongside PDF digital booklets and artwork. Downloading all files wastes bandwidth. Auddio implements a clean Two-Step Selection Flow:

Step 4A: Probe Request (infoHash Only)

When the user taps an audiobook, Auddio sends only the infoHash. Your addon contacts the debrid provider and inspects the files:

Step 4A Response: selectionRequired
{
  "torrentId": "rd_torrent_9821a",
  "infoHash": "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
  "status": "selection_required",
  "files": [
    { "id": 1, "filename": "01_Dune_Chapter_1.mp3", "size": 15240291 },
    { "id": 2, "filename": "02_Dune_Chapter_2.mp3", "size": 16892010 },
    { "id": 3, "filename": "Dune_Artwork.pdf", "size": 2401822 }
  ]
}

Step 4B: Resolution Request (torrentId + fileIds)

Auddio auto-selects all audio tracks (or lets the user pick), and posts back with torrentId and fileIds:

Step 4B Request
{
  "provider": "realdebrid",
  "apiKey": "USER_DEBRID_TOKEN",
  "infoHash": "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
  "torrentId": "rd_torrent_9821a",
  "fileIds": [1, 2]
}
Step 4B Response: status ready
{
  "torrentId": "rd_torrent_9821a",
  "infoHash": "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
  "status": "ready",
  "files": [
    {
      "id": 1,
      "filename": "01_Dune_Chapter_1.mp3",
      "url": "https://real-debrid.com/d/direct-stream-link-1",
      "size": 15240291,
      "status": "ready",
      "mimeType": "audio/mpeg"
    },
    {
      "id": 2,
      "filename": "02_Dune_Chapter_2.mp3",
      "url": "https://real-debrid.com/d/direct-stream-link-2",
      "size": 16892010,
      "status": "ready",
      "mimeType": "audio/mpeg"
    }
  ],
  "totalSize": 32132301
}
Instant Playback Resumption: Because direct stream URLs expire, Auddio saves torrentId and fileIds in its local database. When resuming listening hours or days later, Auddio executes Step 4B directly, instantly fetching fresh stream links without prompting the user.

5. Download Progress Polling (GET /progress/:torrentId)

If an audiobook was not cached, the debrid service begins downloading the torrent. Auddio polls this endpoint every 3 seconds to display download percentage and ETA:

Response JSON
{
  "infoHash": "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
  "status": "downloading",
  "progress": 68.4,
  "filename": "Dune Complete Audio",
  "files": [
    {
      "id": "1",
      "filename": "01_Dune_Chapter_1.mp3",
      "size": 15240291,
      "status": "ready"
    },
    {
      "id": "2",
      "filename": "02_Dune_Chapter_2.mp3",
      "size": 16892010,
      "status": "downloading"
    }
  ]
}

6. Torrent Metadata & Layout (POST /info)

Fetches the internal flat file layout and groupings from public torrent caches without calling debrid servers:

Response JSON
{
  "infoHash": "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
  "name": "Dune Frank Herbert Complete",
  "files": [
    {
      "fileId": 1,
      "name": "01_Chapter1.mp3",
      "path": "Dune/01_Chapter1.mp3",
      "bookName": "Dune",
      "size": 15240291,
      "sizeFormatted": "14.53 MiB",
      "isAudio": true
    }
  ],
  "totalSize": 15240291,
  "totalSizeFormatted": "14.53 MiB"
}

7. Permanent Caching with TorBox Airlock (POST /airlock)

For addons integrating with the TorBox debrid provider, cached torrents may be automatically deleted after 30 days of inactivity. The AIRLOCK capability allows client apps to toggle permanent retention:

Request Body
{
  "provider": "torbox",
  "apiKey": "USER_TORBOX_API_KEY",
  "torrentId": "tb_torrent_49182",
  "airlocked": true
}
Response JSON
{
  "success": true,
  "airlocked": true,
  "torrentId": "tb_torrent_49182"
}

8. Books Catalogs & Genre Discovery

Addons supporting the CATALOG capability expose categorized collections of audiobooks for the Home, Discover, and Browse screens.

A. Discover Categories & Genres (GET /catalog/filters)

Response JSON
{
  "categories": [
    { "id": "fiction", "name": "Fiction", "description": "Fictional audiobooks" },
    { "id": "non-fiction", "name": "Non-Fiction", "description": "Educational and biographies" },
    { "id": "bestsellers", "name": "Bestsellers", "description": "Top trending titles" }
  ],
  "genres": [
    { "id": "sci-fi", "name": "Science Fiction" },
    { "id": "fantasy", "name": "Fantasy" },
    { "id": "mystery", "name": "Mystery & Thriller" },
    { "id": "biography", "name": "Biography & Memoir" }
  ]
}

B. Fetch Filtered Books (POST /catalog or GET /catalog)

Accepts category, genre, page (1-indexed), limit (default 20, max 100), and sortBy (popular, latest, title):

Response JSON
{
  "books": [
    {
      "id": "B002V1OF70",
      "asin": "B002V1OF70",
      "title": "Dune",
      "author": "Frank Herbert",
      "coverUrl": "https://m.media-amazon.com/images/I/91dSMhdIzTL._SL500_.jpg"
    }
  ],
  "page": 1,
  "limit": 20,
  "hasMore": true,
  "category": "fiction",
  "genre": "sci-fi"
}

Auddio supports 1-click addon installation directly from web pages and GitHub readmes via custom URL schemes:

Deeplink Format
auddio:///addon/install?url=https%3A%2F%2Fmy-addon.railway.app%2Fmanifest.json&debrid_provider=realdebrid

Using the TypeScript SDK helper:

TypeScript
import { getInstallDeeplink } from "auddio-addon-sdk";

const installUrl = getInstallDeeplink("https://my-addon.railway.app/manifest.json", {
  debrid_provider: "realdebrid"
});
// => "auddio:///addon/install?url=https%3A%2F%2Fmy-addon.railway.app%2Fmanifest.json&debrid_provider=realdebrid"

10. Dynamic Configuration Form

Declare fields in your manifest under config.fields. Auddio builds native settings screens automatically:

JSON
"config": {
  "fields": [
    {
      "id": "debrid_provider",
      "label": "Provider",
      "type": "dropdown",
      "required": true,
      "default": "realdebrid",
      "options": [
        { "value": "realdebrid", "label": "Real-Debrid" },
        { "value": "alldebrid", "label": "AllDebrid" }
      ]
    },
    {
      "id": "debrid_api_key",
      "label": "API Key",
      "type": "password",
      "required": true,
      "placeholder": "Enter token...",
      "help": "Your private token remains encrypted on your device"
    },
    {
      "id": "require_cached",
      "label": "Instant Availability Only",
      "type": "checkbox",
      "default": true,
      "help": "Hide torrents not already cached on debrid"
    }
  ]
}

Complete Example: TypeScript SDK (Bun)

Our official TypeScript framework runs natively on Bun with built-in Zod schema validation, type safety, and automatic HTTP handling.

Shell
bun add auddio-addon-sdk

1. Scraper Addon

scraper.ts
import { AddonServer } from "auddio-addon-sdk";

const addon = new AddonServer({
  id: "com.example.audiobookbay-scraper",
  name: "AudioBookBay Scraper",
  version: "1.0.0",
  type: "SCRAPER",
  capabilities: ["SEARCH"],
});

addon.onSearch(async ({ title, author }) => {
  // Replace with tracker scraper or database lookup
  return {
    results: [
      {
        infoHash: "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
        title: `${title} - Unabridged`,
        author: author || "Unknown Author",
        narrator: "Full Cast",
        size: 322485640,
        sizeFormatted: "307.54 MiB",
        seeders: 50,
        leechers: 2,
        source: "AudioBookBay",
        format: "MP3",
        bitrate: "64kbps",
      }
    ],
    total: 1,
    query: { title }
  };
});

addon.listen(3000);
console.log("Scraper addon running on http://localhost:3000");

2. Unified Addon (Search + Debrid Cache + Resolution)

unified.ts
import { AddonServer } from "auddio-addon-sdk";

const addon = new AddonServer({
  id: "com.example.unified-source",
  name: "Unified Audiobook Source",
  version: "1.0.0",
  type: "UNIFIED",
  capabilities: ["SEARCH", "CHECK_CACHE", "RESOLVE", "PROGRESS"],
  config: {
    fields: [
      {
        id: "debrid_provider",
        label: "Debrid Provider",
        type: "dropdown",
        required: true,
        default: "realdebrid",
        options: [
          { value: "realdebrid", label: "Real-Debrid" },
          { value: "alldebrid", label: "AllDebrid" }
        ]
      },
      {
        id: "debrid_api_key",
        label: "Debrid API Key",
        type: "password",
        required: true,
        help: "Your token from your debrid account settings"
      }
    ]
  }
});

// 1. Search candidates
addon.onSearch(async (query) => {
  return {
    results: [
      {
        infoHash: "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
        title: query.title,
        author: query.author,
        size: 322485640,
        sizeFormatted: "307.54 MiB",
        seeders: 32,
        leechers: 1,
        source: "Public Tracker",
        format: "MP3"
      }
    ],
    total: 1,
    query: { title: query.title }
  };
});

// 2. Check instant cache on provider
addon.onCheckCache(async ({ provider, apiKey, infoHashes }) => {
  return {
    "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f": {
      cached: true,
      torrentId: "rd_9821a"
    }
  };
});

// 3. Resolve streams with two-step flow
addon.onResolve(async ({ provider, apiKey, infoHash, torrentId, fileIds }) => {
  if (!fileIds || fileIds.length === 0) {
    return {
      torrentId: "rd_9821a",
      infoHash,
      status: "selection_required",
      files: [
        { id: 1, filename: "Part_01.mp3", size: 161242820 },
        { id: 2, filename: "Part_02.mp3", size: 161242820 }
      ]
    };
  }

  return {
    torrentId: "rd_9821a",
    infoHash,
    status: "ready",
    files: [
      {
        id: 1,
        filename: "Part_01.mp3",
        url: "https://real-debrid.com/d/streamable-link-1",
        size: 161242820,
        status: "ready",
        mimeType: "audio/mpeg"
      }
    ],
    totalSize: 161242820
  };
});

// 4. Poll progress for uncached torrents
addon.onProgress(async ({ torrentId, apiKey }) => {
  return {
    infoHash: "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
    status: "downloading",
    progress: 85.0,
    filename: "Audiobook Collection",
    files: [
      { id: "1", filename: "Part_01.mp3", size: 161242820, status: "ready" }
    ]
  };
});

addon.listen(3000);

3. Books Catalog Addon

catalog.ts
import { AddonServer } from "auddio-addon-sdk";

const addon = new AddonServer({
  id: "com.example.curated-catalog",
  name: "Curated Audiobooks",
  version: "1.0.0",
  capabilities: ["CATALOG", "SEARCH"],
  endpoints: {
    catalog: "/catalog",
    catalogFilters: "/catalog/filters",
  }
});

addon.onCatalogFilters(async () => {
  return {
    categories: [
      { id: "fiction", name: "Fiction" },
      { id: "non-fiction", name: "Non-Fiction" }
    ],
    genres: [
      { id: "sci-fi", name: "Science Fiction" },
      { id: "fantasy", name: "Fantasy" },
      { id: "mystery", name: "Mystery & Thriller" }
    ]
  };
});

addon.onCatalog(async ({ category, genre, page = 1, limit = 20, sortBy }) => {
  return {
    books: [
      {
        id: "dune-1",
        asin: "B002V1OF70",
        title: "Dune",
        author: "Frank Herbert",
        coverUrl: "https://m.media-amazon.com/images/I/91dSMhdIzTL._SL500_.jpg"
      }
    ],
    page,
    limit,
    hasMore: false,
    category,
    genre
  };
});

addon.listen(3000);

Complete Example: Node.js & Express

If you prefer vanilla Node.js, you can build an addon with Express and CORS in less than 70 lines:

server.js
const express = require('express');
const cors = require('cors');

const app = express();
app.use(cors());
app.use(express.json());

// Manifest
app.get('/manifest.json', (req, res) => {
  res.json({
    id: "com.example.express-addon",
    name: "Express Audiobook Addon",
    version: "1.0.0",
    type: "UNIFIED",
    capabilities: ["SEARCH", "CHECK_CACHE", "RESOLVE"],
    config: {
      fields: [
        {
          id: "debrid_api_key",
          label: "Debrid API Key",
          type: "password",
          required: true
        }
      ]
    }
  });
});

// Search
app.post('/search', (req, res) => {
  const { title } = req.body;
  res.json({
    results: [
      {
        infoHash: "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
        title: title || "Demo Audiobook",
        author: "Demo Author",
        size: 322485640,
        sizeFormatted: "307.54 MiB",
        seeders: 25,
        leechers: 1,
        source: "Public Tracker",
        format: "MP3"
      }
    ],
    total: 1,
    query: { title }
  });
});

// Check Cache
app.post('/check-cache', (req, res) => {
  const { infoHashes } = req.body;
  const result = {};
  (infoHashes || []).forEach(hash => {
    result[hash] = { cached: true, torrentId: "rd_demo_1" };
  });
  res.json(result);
});

// Resolve
app.post('/resolve', (req, res) => {
  const { infoHash, fileIds } = req.body;
  if (!fileIds || fileIds.length === 0) {
    return res.json({
      torrentId: "rd_demo_1",
      infoHash,
      status: "selection_required",
      files: [
        { id: 1, filename: "Chapter_1.mp3", size: 15240291 }
      ]
    });
  }
  res.json({
    torrentId: "rd_demo_1",
    infoHash,
    status: "ready",
    files: [
      {
        id: 1,
        filename: "Chapter_1.mp3",
        url: "https://your-debrid.com/stream/file_1.mp3",
        size: 15240291,
        status: "ready",
        mimeType: "audio/mpeg"
      }
    ]
  });
});

app.listen(3000, () => console.log('Addon listening on port 3000'));
Shell
npm init -y
npm install express cors
node server.js

Complete Example: Python & Flask

app.py
from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route('/manifest.json', methods=['GET'])
def manifest():
    return jsonify({
        "id": "com.example.python-addon",
        "name": "Python Audiobook Addon",
        "version": "1.0.0",
        "type": "UNIFIED",
        "capabilities": ["SEARCH", "CHECK_CACHE", "RESOLVE"]
    })

@app.route('/search', methods=['POST'])
def search():
    data = request.get_json() or {}
    title = data.get('title', 'Unknown')
    return jsonify({
        "results": [{
            "infoHash": "a5f822e1b12b23a9dcb8e4f5a112f45c22881a5f",
            "title": title,
            "author": data.get('author', 'Author'),
            "size": 322485640,
            "sizeFormatted": "307.54 MiB",
            "seeders": 40,
            "format": "MP3"
        }],
        "total": 1,
        "query": {"title": title}
    })

@app.route('/check-cache', methods=['POST'])
def check_cache():
    data = request.get_json() or {}
    hashes = data.get('infoHashes', [])
    return jsonify({h: {"cached": True, "torrentId": "rd_py_1"} for h in hashes})

@app.route('/resolve', methods=['POST'])
def resolve():
    data = request.get_json() or {}
    file_ids = data.get('fileIds', [])
    if not file_ids:
        return jsonify({
            "torrentId": "rd_py_1",
            "infoHash": data.get('infoHash'),
            "status": "selection_required",
            "files": [{"id": 1, "filename": "Chapter_01.mp3", "size": 15000000}]
        })
    return jsonify({
        "torrentId": "rd_py_1",
        "infoHash": data.get('infoHash'),
        "status": "ready",
        "files": [{
            "id": 1,
            "filename": "Chapter_01.mp3",
            "url": "https://your-debrid.com/py/stream.mp3",
            "size": 15000000,
            "status": "ready"
        }]
    })

if __name__ == '__main__':
    app.run(port=3000)


TypeScript SDK API Reference (Generated from Code)

The following API reference is generated automatically from the official auddio-addon-sdk TypeScript source code and JSDoc docstrings using TypeDoc.

Class

AddonServer

The primary HTTP server framework for developing Auddio Addon microservices with Bun.
class AddonServer(manifest: Manifest)

Methods

Method Signature & Parameters Description (from JSDoc)
constructor() constructor(manifest: object): AddonServer Handler registration method.
onSearch() onSearch(handler: (req: object) => Promise<SearchResponse>): this Define the search capability handler
onCheckCache() onCheckCache(handler: (req: object) => Promise<CheckCacheResponse>): this Define the check cache capability handler
onResolve() onResolve(handler: (req: object) => Promise<ResolveResponse>): this Define the resolve capability handler
onProgress() onProgress(handler: (req: object) => Promise<object>): this Define the progress capability handler
onTorrentFiles() onTorrentFiles(handler: (req: object) => Promise<object>): this Define the torrent files handler (POST /info)
onAirlock() onAirlock(handler: (req: object) => Promise<AirlockResponse>): this Define the airlock handler (POST /airlock). Called when the app wants to toggle permanent caching on a TorBox torrent. Only relevant for addons that use the TorBox debrid provider.
onCatalogFilters() onCatalogFilters(handler: (req: object) => Promise<object>): this Define the catalog filters capability handler (returns categories and genres list)
onCatalog() onCatalog(handler: (req: object) => Promise<object>): this Define the catalog books capability handler (returns books by category / genre)
listen() listen(port: number): Server<undefined> Start the Bun.serve server
Function

getInstallDeeplink

Generates the deeplink for installing an addon in the Auddio app. Uses the scheme: auddio:///
getInstallDeeplink(manifestUrl: string, configValues: Record<string, string | number | boolean>): string

Capabilities Reference

Every addon advertises its supported operations inside the capabilities array in its manifest. The mobile client inspects these flags to selectively enable search indexing, instant cloud playback, catalog screens, or airlock caching.

SEARCH POST /search

Search & Scraping

Enables title, author, and book ID matching across external trackers, private indexers, and public audiobook sources.

CHECK_CACHE POST /check-cache

Instant Cloud Cache

Checks whether candidate torrent infoHashes are cached on Real-Debrid, TorBox, or AllDebrid for instantaneous zero-wait playback.

RESOLVE POST /resolve

Stream Resolution

Unlocks our 2-step chapter selection flow to extract and deliver playable, seekable audio streaming links for each track.

PROGRESS GET /progress/:id

Download Polling

Tracks background download percentages and file completion when a user chooses to cache an uncached torrent to debrid.

INFO POST /info

Torrent Metadata

Inspects full file layouts, track numbers, and chapter names from public torrent cache engines without hitting debrid API quotas.

AIRLOCK POST /airlock

TorBox Airlock

Toggles permanent storage retention on TorBox debrid servers to safeguard frequently played audiobooks from automatic 30-day eviction.

CATALOG /catalog*

Books Catalogs

Populates Auddio's Discover, Category, and Genre tabs with rich audiobook shelves, covers, and curated recommendations.

Capability Required Endpoint Description & App Behavior
"SEARCH" POST /search Enables search integration across torrent trackers and providers.
"CHECK_CACHE" POST /check-cache Allows client to query instant cache status of torrent infoHashes on Debrid clouds.
"RESOLVE" POST /resolve Resolves infoHashes into direct playable audio stream URLs via 2-step selection.
"PROGRESS" GET /progress/:torrentId Monitors debrid download status for uncached torrents being fetched to cloud storage.
"INFO" POST /info Returns raw internal file layout and groupings from public torrent caches without Debrid API calls.
"AIRLOCK" POST /airlock Toggles permanent torrent retention on TorBox providers to prevent 30-day inactivity deletion.
"CATALOG" /catalog & /catalog/filters Populates Home, Discover, and Browse shelves with curated audiobook categories and genres.

Config Field Schema Reference

Every element in manifest.config.fields supports the following attributes:

Property Type Required Description
id String Yes Unique key transmitted in request payloads (e.g. debrid_api_key).
label String Yes Human-readable title displayed next to the widget in the app settings.
type String Yes Widget control type: "text", "password", "number", "textarea", "dropdown", or "checkbox".
required Boolean Yes If true, client blocks installation until the user supplies a value.
default Any No Fallback initial value populated before the user edits the field.
placeholder String No Faint prompt text rendered inside text input controls.
help String No Explaining hint rendered beneath the field in small font.
options Array Dropdown only Array of { "value": string, "label": string } options for dropdown pickers.

Protocol Error Specifications

When handling requests, addons return JSON error responses with descriptive error codes and standard HTTP statuses:

Error Code HTTP Status Description & App Behavior
INVALID_INPUT 400 Bad Request Missing required parameters or malformed infoHash.
INVALID_API_KEY 401 Unauthorized The user's private debrid API token was rejected by the provider.
NOT_FOUND 404 Not Found Requested audiobook or scraper query returned no matches.
NOT_CACHED 412 Precondition Failed Torrent is not cached on debrid, and the user requested instant cache only.
RATE_LIMIT_EXCEEDED 429 Too Many Requests Addon or downstream provider rate limits exceeded.
PROVIDER_ERROR 502 Bad Gateway The downstream debrid service returned an internal error or timed out.

Hosting & Deployment

Your production addon must be accessible over HTTPS. Popular hosting options:

Platform Free Tier Best For
Railway $5/mo credit Full Node.js/Bun servers, persistent Docker containers.
Fly.io 3 shared VMs Global edge Docker microservices with fast cold starts.
Cloudflare Workers 100k requests/day Ultra-fast serverless scrapers running at the edge.
Custom VPS - Any standard Linux VPS running Nginx/Caddy with SSL.
Testing on Physical Devices: For local development on an iPhone, iPad, or Android phone, bind your server to 0.0.0.0 and enter your Mac's LAN IP address (e.g. http://192.168.1.100:3000/manifest.json). Auddio accepts unencrypted HTTP on local network subnets!

Installing Your Addon in Auddio

  1. Open the Auddio app on iOS, iPadOS, or Android.
  2. Navigate to Settings → Addons → Add Custom Addon.
  3. Paste your addon's manifest URL (e.g. https://my-addon.railway.app/manifest.json).
  4. Auddio fetches the manifest, renders the dynamic config form, and displays a preview.
  5. Fill in any required settings (like your Debrid API key) and tap Install.
  6. Your addon is now active across Search, Cloud Streaming, and Catalog browsing!

Frequently Asked Questions

Can I build an addon in any programming language?

Yes — any backend language that can serve JSON responses over HTTP works seamlessly. We provide an official TypeScript framework for Bun, but you can build in Node.js, Python, Go, Rust, Java, or C#.

Does my addon need to store user database records?

No. Auddio addons are typically stateless microservices. All user configuration parameters (API tokens, mirrors, filters) are stored locally on the user's client device and sent with each request.

How does Auddio prevent downloading the entire torrent?

Through our Two-Step Selection Flow. When an infoHash contains multiple chapter files, the addon returns status: "selection_required". Auddio then requests stream links only for the specific audio file the listener is playing.

Can an addon provide audiobook catalogs?

Yes! Declare "CATALOG" in your manifest's capabilities and implement /catalog/filters and /catalog. Your categorized rows (Bestsellers, Sci-Fi, Non-Fiction) will display directly in Auddio's Discover tab.

What audio formats are supported?

Auddio supports MP3, M4B, AAC, FLAC, OPUS, and WAV. For M4B and MP3 files, embedded chapter markers and titles are parsed automatically by the player.

Is my Debrid API Key safe?

Yes. Keys are stored in the device's secure enclave and transmitted directly over HTTPS to your addon server.

Accent