Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/audiopod-ai:audiopod-ai-voice-design-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: AudioPod AI Voice Design API
description: '# AudioPod AI APIs
## Overview
The AudioPod AI API provides advanced audio processing, AI-powered music generation, voice cloning, transcription, and audio publishing services over a versioned REST interface, with API-key authentication, typed error responses, and published rate limits. ## Base URL
```
https://api.audiopod.ai/api/v1
```
## Authentication
### API Key Authentication (Recommended)
Most API endpoints use API key authentication. Include your key in the header:
```
X-API-Key: ap_your_api_key
```
### JWT Token Authentication
For session-based access (web applications), obtain a token via `/auth/token`:
```
Authorization: Bearer
```
### Public Endpoints
Some endpoints like newsletter subscription, health checks, and shared content don''t require authentication. ## Versioning & Deprecation Policy
The API is versioned **in the URL path**. The current version is `v1`, served at
`https://api.audiopod.ai/api/v1`. Integrate against an explicit version — never
against an unversioned path. - **Additive changes ship in place.** New endpoints, new optional request
fields, and new response fields can appear in `v1` at any time. Clients must
ignore unknown response fields rather than failing on them. - **Breaking changes ship as a new path version** (`/api/v2`). A breaking change
is: removing or renaming a field or endpoint, changing a field''s type, adding a
required request field, or changing the meaning of an existing value. - **Retirement is announced on the wire.** When an endpoint or version is
scheduled for removal, its responses carry:
- `Deprecation: true` — the endpoint is deprecated as of now. - `Sunset: ` — the date after which it stops responding
(RFC 8594). - `Link: ; rel="successor-version"` — where to migrate to. - **Minimum notice: 6 months** between the first `Sunset` header and removal, for
any endpoint outside a `dev`/preview tag. - Deprecated operations are also marked `"deprecated": true` in this
specification, so a generated client can surface the warning at build time. ## Rate Limiting
Limits are applied per API key (falling back to client IP for unauthenticated
requests) and **scale with subscription tier** — higher tiers get proportionally
more headroom on the same routes. Indicative baselines for the free tier:
- **Standard**: 100 requests/minute
- **Auth endpoints**: 10 requests/minute
- **Upload endpoints**: 20 requests/minute
- **Music generation**: `50/minute`
- **Music retake**: `10/minute`
- **Music repaint / extend / edit**: `3/minute`
Do not hard-code these numbers. **Read the quota off the response headers**,
which are returned on every rate-limited route (routes with no explicit limit
send no quota headers — absence means "not throttled here", not "quota
exhausted"):
| Header | Meaning |
|---|---|
| `RateLimit-Limit` | Requests allowed in the current window |
| `RateLimit-Remaining` | Requests still available in the current window |
| `RateLimit-Reset` | Seconds until the window resets |
| `RateLimit-Policy` | The quota policy, e.g. `100;w=60` |
| `Retry-After` | On a `429` only: seconds to wait before retrying |
The legacy `X-RateLimit-Limit` / `-Remaining` / `-Reset` names are still sent
alongside the standard ones for older clients. On a `429`, back off for at least `Retry-After` seconds. Retries with
exponential backoff and jitter are expected; tight retry loops are not. ## Errors
Every `4xx` and `5xx` response uses one typed envelope:
```json
{
"error": "NOT_FOUND",
"message": "The requested resource was not found.",
"status": 404,
"detail": "..."
}
```
- `error` — a **stable, machine-readable code**. Branch on this. - `message` — human-readable prose. Do not parse; wording can change. - `status` — the HTTP status, repeated for convenience. - `detail` — the legacy payload, retained for backward compatibility. For a
`422` it is the array of failing fields. The full shape is published as the `ErrorResponse` schema, and each operation
below documents the statuses it can return.'
version: 2.0.0
servers:
- url: https://api.audiopod.ai
description: Production
security:
- apiKeyAuth: []
- bearerAuth: []
tags:
- name: voice-design
paths:
/api/v1/voice/design:
post:
tags:
- voice-design
summary: Design Voice
description: 'Generate candidate voices from a text description (paid: 250 credits per
preview). Returns short presigned previews the user can audition, then
publish via ``/design/publish``.'
operationId: design_voice
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceDesignRequest'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceDesignResponse'
'422':
$ref: '#/components/responses/ValidationFailed'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/InternalError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
x-original-operation-id: design_voice_api_v1_voice_design_post
/api/v1/voice/design/publish:
post:
tags:
- voice-design
summary: Publish Designed Voice
description: Publish a designed preview into a durable custom voice (free).
operationId: publish_designed_voice
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/VoiceDesignPublishRequest'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/Voice'
'422':
$ref: '#/components/responses/ValidationFailed'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'402':
$ref: '#/components/responses/PaymentRequired'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/InternalError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
x-original-operation-id: publish_designed_voice_api_v1_voice_design_publish_post
components:
headers:
RetryAfter:
description: Seconds to wait before retrying.
schema:
type: integer
RateLimitLimit:
description: Request quota for the current window on this route.
schema:
type: integer
RateLimitRemaining:
description: Requests remaining in the current window.
schema:
type: integer
RateLimitReset:
description: Seconds until the current window resets.
schema:
type: integer
RateLimitPolicy:
description: Quota policy for this route, e.g. `100;w=60`. Limits scale with subscription tier.
schema:
type: string
responses:
BadRequest:
description: Bad request — malformed syntax or an invalid parameter combination.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
PaymentRequired:
description: 'Not enough credits to run this job. `detail` carries the typed InsufficientCreditsDetail object: what the job costs, what the account holds, and how to add more.'
content:
application/json:
schema:
$ref: '#/components/schemas/InsufficientCreditsResponse'
InternalError:
description: Unexpected server error.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Forbidden:
description: Authenticated, but not permitted (wrong scope, or a plan-gated feature).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
ServiceUnavailable:
description: Temporarily unavailable. Safe to retry with backoff.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Unauthorized:
description: Authentication required or the supplied credential is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
RateLimited:
description: Rate limit exceeded. Honour `Retry-After` before retrying.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
headers:
RateLimit-Limit:
$ref: '#/components/headers/RateLimitLimit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimitRemaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimitReset'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Retry-After:
$ref: '#/components/headers/RetryAfter'
NotFound:
description: The requested resource does not exist.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Conflict:
description: Conflict with the current state of the resource.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
ValidationFailed:
description: Request validation failed. `detail` lists the offending fields.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
schemas:
VoiceDesignPreview:
properties:
preview_id:
type: string
title: Preview Id
audio_url:
type: string
title: Audio Url
expires_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Expires At
preview_text:
anyOf:
- type: string
- type: 'null'
title: Preview Text
type: object
required:
- preview_id
- audio_url
title: VoiceDesignPreview
VoiceDesignResponse:
properties:
previews:
items:
$ref: '#/components/schemas/VoiceDesignPreview'
type: array
title: Previews
credits_charged:
type: integer
title: Credits Charged
default: 0
type: object
title: VoiceDesignResponse
InsufficientCreditsDetail:
type: object
title: InsufficientCreditsDetail
description: 'Everything needed to resolve a credit shortfall: what the job costs, what the account holds, and the ways to add more.'
properties:
error:
type: string
description: Always `INSUFFICIENT_CREDITS` on this response.
examples:
- INSUFFICIENT_CREDITS
message:
type: string
description: Human-readable explanation. Do not parse.
credits_required:
type:
- integer
- 'null'
description: Credits this job needs. Null when the shortfall was detected without a priced estimate — show no figure rather than a wrong one.
credits_available:
type: integer
description: 'Total spendable credits: subscription plus pay-as-you-go.'
subscription_credits:
type: integer
description: Plan credits remaining in the current cycle.
payg_credits:
type: integer
description: Pay-as-you-go credits, which never expire.
current_plan:
type: string
examples:
- Basic
upgrade_options:
type: array
description: Plans above the current one, cheapest first.
items:
type: object
properties:
plan:
type: string
price:
type: string
credits:
type: string
annual:
type: string
payg_option:
type: object
description: Where to buy credits that never expire.
properties:
description:
type: string
url:
type: string
upgrade_url:
type: string
examples:
- /pricing
auto_refill:
type: object
description: Whether an automatic top-up is handling this shortfall. `off` means none is running and the caller should top up or upgrade; `pending` means one is in flight, so poll the balance and retry the same request; `failed` means one was attempted and did not complete; `ineligible` means automatic top-up cannot run for this account.
properties:
state:
type: string
enum:
- 'off'
- pending
- failed
- ineligible
required:
- state
upload_ref:
type:
- string
- 'null'
description: Reference to the input already uploaded for this request, when there was one, so a retry after topping up does not have to send the file again. Null when the request carried no upload.
required:
- error
- message
- credits_available
- current_plan
InsufficientCreditsResponse:
type: object
title: InsufficientCreditsResponse
description: Error envelope for a credit shortfall. Identical to ErrorResponse except that `detail` is the typed InsufficientCreditsDetail object.
properties:
code:
type: string
description: Stable machine-readable code. **Branch on this field.**
examples:
- PAYMENT_REQUIRED
error:
type: string
examples:
- PAYMENT_REQUIRED
message:
type: string
description: Human-readable explanation. Do not parse.
status:
type: integer
examples:
- 402
detail:
$ref: '#/components/schemas/InsufficientCreditsDetail'
required:
- code
- message
- status
ProcessingStatus:
type: string
enum:
- PENDING
- PROCESSING
- COMPLETED
- FAILED
- CANCELLED
title: ProcessingStatus
VoiceDesignPublishRequest:
properties:
preview_id:
type: string
title: Preview Id
name:
type: string
maxLength: 100
minLength: 1
title: Name
description:
anyOf:
- type: string
- type: 'null'
title: Description
type: object
required:
- preview_id
- name
title: VoiceDesignPublishRequest
app__schemas__enums__VoiceType:
type: string
enum:
- CUSTOM
- STANDARD
title: VoiceType
description: 'Type of voice: custom (user-uploaded) or standard (public/provider)'
VoiceDesignRequest:
properties:
design_prompt:
type: string
maxLength: 250
minLength: 30
title: Design Prompt
language:
anyOf:
- type: string
- type: 'null'
title: Language
preview_text:
type: string
maxLength: 300
minLength: 20
title: Preview Text
default: Welcome to AudioPod! Here's a preview of the voice you designed.
num_samples:
type: integer
maximum: 3.0
minimum: 1.0
title: Num Samples
default: 3
type: object
required:
- design_prompt
title: VoiceDesignRequest
ErrorResponse:
type: object
title: ErrorResponse
description: Standard error envelope. Every 4xx and 5xx response from the AudioPod AI API carries `code`, `message` and `status`. Branch on `code` — a stable machine-readable string — rather than parsing `message`, which is human-facing prose and may be reworded at any time. `detail` and `error` are retained for backward compatibility with older integrations, and their shapes vary by endpoint.
properties:
code:
type: string
description: Stable machine-readable error code, present on every error response. **Branch on this field.** Values are additive and existing codes are not renamed.
examples:
- NOT_FOUND
- AUTHENTICATION_REQUIRED
- RATE_LIMIT_EXCEEDED
error:
description: Legacy error field. Usually the same string as `code`, but a few older endpoints emit an object here instead (`code` / `message` / `details`). Prefer `code`, which is always a string.
examples:
- NOT_FOUND
- AUTHENTICATION_REQUIRED
message:
type: string
description: Human-readable explanation. Do not parse.
examples:
- The requested resource was not found.
status:
type: integer
description: HTTP status code, repeated in the body for convenience.
examples:
- 404
detail:
description: Legacy detail payload, preserved verbatim for backward compatibility. A string for most errors, an array of field errors for validation failures, an object for auth failures.
required:
- code
- message
- status
Voice:
properties:
id:
type: integer
title: Id
uuid:
type: string
format: uuid
title: Uuid
slug:
type: string
title: Slug
description: URL-safe form of `uuid`.
default: ''
display_name:
type: string
title: Display Name
description: The voice's human label. Always present, never empty.
description:
anyOf:
- type: string
- type: 'null'
title: Description
description: Voice description.
gender:
anyOf:
- type: string
- type: 'null'
title: Gender
accent:
anyOf:
- type: string
- type: 'null'
title: Accent
age_group:
anyOf:
- type: string
- type: 'null'
title: Age Group
voice_style:
anyOf:
- type: string
- type: 'null'
title: Voice Style
language_code:
anyOf:
- type: string
- type: 'null'
title: Language Code
description: Primary BCP-47 code for this voice.
language_name:
anyOf:
- type: string
- type: 'null'
title: Language Name
supported_languages:
items:
type: string
type: array
title: Supported Languages
description: BCP-47 codes this voice can speak.
language_codes:
items:
type: string
type: array
title: Language Codes
description: Alias of `supported_languages`, kept for existing clients.
best_suited_languages:
items:
type: string
type: array
title: Best Suited Languages
description: BCP-47 codes this specific voice is best suited for. May be empty, which means 'not characterised', not 'no languages'.
language_filter_codes:
items:
type: string
type: array
title: Language Filter Codes
description: The codes a voice picker should FILTER this voice under. Resolved server-side; prefer it over deriving one from the language lists. Empty means 'not characterised' — keep your own fallback.
cross_lingual_capable:
type: boolean
title: Cross Lingual Capable
description: True when the engine can synthesize this voice well beyond its best-suited languages. Display fact only — nothing is gated on it.
default: false
use_case:
anyOf:
- type: string
- type: 'null'
title: Use Case
description: 'Derived filter axis: narration | conversational | character | explainer. Filter voice pickers on this rather than on `voice_style`.'
use_cases:
items:
type: string
type: array
title: Use Cases
description: Marketing-curated tags. Populated on no catalog row today; use the singular `use_case` above.
tags:
items:
type: string
type: array
title: Tags
description: Voice descriptors.
categories:
items:
type: string
type: array
title: Categories
description: Voice categories.
sample_audio_url:
anyOf:
- type: string
- type: 'null'
title: Sample Audio Url
description: A URL the player can use directly. Present whenever this voice has any preview audio at all.
can_be_conversion_target:
type: boolean
title: Can Be Conversion Target
description: Whether this voice can be the TARGET of a voice conversion. Conversion needs a stored reference clip; a catalog voice synthesized on demand has a preview but no clip, so it is a valid TTS speaker and an invalid conversion target.
default: false
sample_text:
anyOf:
- type: string
- type: 'null'
title: Sample Text
description: The line spoken in the preview.
is_public:
type: boolean
title: Is Public
description: Whether this voice is visible to other accounts.
default: false
voice_type:
anyOf:
- $ref: '#/components/schemas/app__schemas__enums__VoiceType'
- type: 'null'
description: STANDARD for catalog voices, CUSTOM for cloned ones.
featured_rank:
anyOf:
- type: integer
- type: 'null'
title: Featured Rank
description: Curated 'Start here' position, 1-based, or null.
popularity_score:
type: integer
title: Popularity Score
description: Distinct accounts that used this voice in the last 30 days.
default: 0
is_premium_engine:
type: boolean
title: Is Premium Engine
description: Whether this voice renders on the premium engine.
default: false
is_designed:
type: boolean
title: Is Designed
description: Whether this voice was created with Design a Voice.
default: false
is_owner:
anyOf:
- type: boolean
- type: 'null'
title: Is Owner
tier:
anyOf:
- type: integer
- type: 'null'
title: Tier
relevance_score:
anyOf:
- type: number
- type: 'null'
title: Relevance Score
created_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Created At
status:
anyOf:
- $ref: '#/components/schemas/ProcessingStatus'
- type: 'null'
processed_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Processed At
error_message:
anyOf:
- type: string
- type: 'null'
title: Error Message
needs_reprocessing:
type: boolean
title: Needs Reprocessing
description: Whether this voice must be re-saved before it can narrate stories or audiobooks.
default: false
type: object
required:
- id
- uuid
- display_name
title: Voice
description: 'A voice as returned to a signed-in caller.
Adds the requester-relative `is_owner` flag, the ranking annotations, and
the processing state of a voice the caller is cloning.'
securitySchemes:
OAuth2PasswordBearer:
type: oauth2
flows:
password:
scopes: {}
tokenUrl: /api/v1/auth/token
OptionalOAuth2Scheme:
type: oauth2
flows:
password:
scopes: {}
tokenUrl: /api/v1/auth/token
apiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: 'AudioPod API key. Create one in the dashboard under API Keys and send it as `X-API-Key: ap_...`. This is the recommended method for server-to-server and agent integrations.'
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: Session token obtained from `/api/v1/auth/token`. Intended for first-party web sessions; prefer an API key for integrations.